OSDN Git Service

Merge "Bluetooth: Check the number of file descriptors" into oc-dr1-dev
[android-x86/hardware-interfaces.git] / media / omx / 1.0 / vts / functional / video / VtsHalMediaOmxV1_0TargetVideoDecTest.cpp
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #define LOG_TAG "media_omx_hidl_video_dec_test"
18 #include <android-base/logging.h>
19
20 #include <android/hardware/graphics/allocator/2.0/IAllocator.h>
21 #include <android/hardware/graphics/mapper/2.0/IMapper.h>
22 #include <android/hardware/graphics/mapper/2.0/types.h>
23 #include <android/hardware/media/omx/1.0/IOmx.h>
24 #include <android/hardware/media/omx/1.0/IOmxNode.h>
25 #include <android/hardware/media/omx/1.0/IOmxObserver.h>
26 #include <android/hardware/media/omx/1.0/types.h>
27 #include <android/hidl/allocator/1.0/IAllocator.h>
28 #include <android/hidl/memory/1.0/IMapper.h>
29 #include <android/hidl/memory/1.0/IMemory.h>
30 #include <cutils/atomic.h>
31
32 using ::android::hardware::graphics::common::V1_0::BufferUsage;
33 using ::android::hardware::graphics::common::V1_0::PixelFormat;
34 using ::android::hardware::media::omx::V1_0::IOmx;
35 using ::android::hardware::media::omx::V1_0::IOmxObserver;
36 using ::android::hardware::media::omx::V1_0::IOmxNode;
37 using ::android::hardware::media::omx::V1_0::Message;
38 using ::android::hardware::media::omx::V1_0::CodecBuffer;
39 using ::android::hardware::media::omx::V1_0::PortMode;
40 using ::android::hidl::allocator::V1_0::IAllocator;
41 using ::android::hidl::memory::V1_0::IMemory;
42 using ::android::hidl::memory::V1_0::IMapper;
43 using ::android::hardware::Return;
44 using ::android::hardware::Void;
45 using ::android::hardware::hidl_vec;
46 using ::android::hardware::hidl_string;
47 using ::android::sp;
48
49 #include <VtsHalHidlTargetTestBase.h>
50 #include <getopt.h>
51 #include <media/hardware/HardwareAPI.h>
52 #include <media_hidl_test_common.h>
53 #include <media_video_hidl_test_common.h>
54 #include <fstream>
55
56 // A class for test environment setup
57 class ComponentTestEnvironment : public ::testing::Environment {
58    public:
59     virtual void SetUp() {}
60     virtual void TearDown() {}
61
62     ComponentTestEnvironment() : instance("default"), res("/sdcard/media/") {}
63
64     void setInstance(const char* _instance) { instance = _instance; }
65
66     void setComponent(const char* _component) { component = _component; }
67
68     void setRole(const char* _role) { role = _role; }
69
70     void setRes(const char* _res) { res = _res; }
71
72     const hidl_string getInstance() const { return instance; }
73
74     const hidl_string getComponent() const { return component; }
75
76     const hidl_string getRole() const { return role; }
77
78     const hidl_string getRes() const { return res; }
79
80     int initFromOptions(int argc, char** argv) {
81         static struct option options[] = {
82             {"instance", required_argument, 0, 'I'},
83             {"component", required_argument, 0, 'C'},
84             {"role", required_argument, 0, 'R'},
85             {"res", required_argument, 0, 'P'},
86             {0, 0, 0, 0}};
87
88         while (true) {
89             int index = 0;
90             int c = getopt_long(argc, argv, "I:C:R:P:", options, &index);
91             if (c == -1) {
92                 break;
93             }
94
95             switch (c) {
96                 case 'I':
97                     setInstance(optarg);
98                     break;
99                 case 'C':
100                     setComponent(optarg);
101                     break;
102                 case 'R':
103                     setRole(optarg);
104                     break;
105                 case 'P':
106                     setRes(optarg);
107                     break;
108                 case '?':
109                     break;
110             }
111         }
112
113         if (optind < argc) {
114             fprintf(stderr,
115                     "unrecognized option: %s\n\n"
116                     "usage: %s <gtest options> <test options>\n\n"
117                     "test options are:\n\n"
118                     "-I, --instance: HAL instance to test\n"
119                     "-C, --component: OMX component to test\n"
120                     "-R, --role: OMX component Role\n"
121                     "-P, --res: Resource files directory location\n",
122                     argv[optind ?: 1], argv[0]);
123             return 2;
124         }
125         return 0;
126     }
127
128    private:
129     hidl_string instance;
130     hidl_string component;
131     hidl_string role;
132     hidl_string res;
133 };
134
135 static ComponentTestEnvironment* gEnv = nullptr;
136
137 // video decoder test fixture class
138 class VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
139    private:
140     typedef ::testing::VtsHalHidlTargetTestBase Super;
141    public:
142     ::std::string getTestCaseInfo() const override {
143         return ::std::string() +
144                 "Component: " + gEnv->getComponent().c_str() + " | " +
145                 "Role: " + gEnv->getRole().c_str() + " | " +
146                 "Instance: " + gEnv->getInstance().c_str() + " | " +
147                 "Res: " + gEnv->getRes().c_str();
148     }
149
150     virtual void SetUp() override {
151         Super::SetUp();
152         disableTest = false;
153         android::hardware::media::omx::V1_0::Status status;
154         omx = Super::getService<IOmx>(gEnv->getInstance());
155         ASSERT_NE(omx, nullptr);
156         observer =
157             new CodecObserver([this](Message msg, const BufferInfo* buffer) {
158                 handleMessage(msg, buffer);
159             });
160         ASSERT_NE(observer, nullptr);
161         if (strncmp(gEnv->getComponent().c_str(), "OMX.", 4) != 0)
162             disableTest = true;
163         EXPECT_TRUE(omx->allocateNode(
164                            gEnv->getComponent(), observer,
165                            [&](android::hardware::media::omx::V1_0::Status _s,
166                                sp<IOmxNode> const& _nl) {
167                                status = _s;
168                                this->omxNode = _nl;
169                            })
170                         .isOk());
171         ASSERT_NE(omxNode, nullptr);
172         ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
173         struct StringToName {
174             const char* Name;
175             standardComp CompName;
176         };
177         const StringToName kStringToName[] = {
178             {"h263", h263}, {"avc", avc}, {"mpeg2", mpeg2}, {"mpeg4", mpeg4},
179             {"hevc", hevc}, {"vp8", vp8}, {"vp9", vp9},
180         };
181         const size_t kNumStringToName =
182             sizeof(kStringToName) / sizeof(kStringToName[0]);
183         const char* pch;
184         char substring[OMX_MAX_STRINGNAME_SIZE];
185         strcpy(substring, gEnv->getRole().c_str());
186         pch = strchr(substring, '.');
187         ASSERT_NE(pch, nullptr);
188         compName = unknown_comp;
189         for (size_t i = 0; i < kNumStringToName; ++i) {
190             if (!strcasecmp(pch + 1, kStringToName[i].Name)) {
191                 compName = kStringToName[i].CompName;
192                 break;
193             }
194         }
195         if (compName == unknown_comp) disableTest = true;
196         struct CompToCompression {
197             standardComp CompName;
198             OMX_VIDEO_CODINGTYPE eCompressionFormat;
199         };
200         static const CompToCompression kCompToCompression[] = {
201             {h263, OMX_VIDEO_CodingH263},   {avc, OMX_VIDEO_CodingAVC},
202             {mpeg2, OMX_VIDEO_CodingMPEG2}, {mpeg4, OMX_VIDEO_CodingMPEG4},
203             {hevc, OMX_VIDEO_CodingHEVC},   {vp8, OMX_VIDEO_CodingVP8},
204             {vp9, OMX_VIDEO_CodingVP9},
205         };
206         static const size_t kNumCompToCompression =
207             sizeof(kCompToCompression) / sizeof(kCompToCompression[0]);
208         size_t i;
209         for (i = 0; i < kNumCompToCompression; ++i) {
210             if (kCompToCompression[i].CompName == compName) {
211                 eCompressionFormat = kCompToCompression[i].eCompressionFormat;
212                 break;
213             }
214         }
215         if (i == kNumCompToCompression) disableTest = true;
216         portMode[0] = portMode[1] = PortMode::PRESET_BYTE_BUFFER;
217         eosFlag = false;
218         framesReceived = 0;
219         timestampUs = 0;
220         timestampDevTest = false;
221         isSecure = false;
222         size_t suffixLen = strlen(".secure");
223         if (strlen(gEnv->getComponent().c_str()) >= suffixLen) {
224             isSecure =
225                 !strcmp(gEnv->getComponent().c_str() +
226                             strlen(gEnv->getComponent().c_str()) - suffixLen,
227                         ".secure");
228         }
229         if (isSecure) disableTest = true;
230         if (disableTest) std::cout << "[          ] Warning !  Test Disabled\n";
231     }
232
233     virtual void TearDown() override {
234         if (omxNode != nullptr) {
235             EXPECT_TRUE((omxNode->freeNode()).isOk());
236             omxNode = nullptr;
237         }
238         Super::TearDown();
239     }
240
241     // callback function to process messages received by onMessages() from IL
242     // client.
243     void handleMessage(Message msg, const BufferInfo* buffer) {
244         (void)buffer;
245         if (msg.type == Message::Type::FILL_BUFFER_DONE) {
246             if (msg.data.extendedBufferData.flags & OMX_BUFFERFLAG_EOS) {
247                 eosFlag = true;
248             }
249             if (msg.data.extendedBufferData.rangeLength != 0) {
250                 framesReceived += 1;
251                 // For decoder components current timestamp always exceeds
252                 // previous timestamp
253                 EXPECT_GE(msg.data.extendedBufferData.timestampUs, timestampUs);
254                 timestampUs = msg.data.extendedBufferData.timestampUs;
255                 // Test if current timestamp is among the list of queued
256                 // timestamps
257                 if (timestampDevTest) {
258                     bool tsHit = false;
259                     android::List<uint64_t>::iterator it =
260                         timestampUslist.begin();
261                     while (it != timestampUslist.end()) {
262                         if (*it == timestampUs) {
263                             timestampUslist.erase(it);
264                             tsHit = true;
265                             break;
266                         }
267                         it++;
268                     }
269                     if (tsHit == false) {
270                         if (timestampUslist.empty() == false) {
271                             EXPECT_EQ(tsHit, true)
272                                 << "TimeStamp not recognized";
273                         } else {
274                             std::cout
275                                 << "[          ] Warning ! Received non-zero "
276                                    "output / TimeStamp not recognized \n";
277                         }
278                     }
279                 }
280 #define WRITE_OUTPUT 0
281 #if WRITE_OUTPUT
282                 static int count = 0;
283                 FILE* ofp = nullptr;
284                 if (count)
285                     ofp = fopen("out.bin", "ab");
286                 else
287                     ofp = fopen("out.bin", "wb");
288                 if (ofp != nullptr &&
289                     portMode[1] == PortMode::PRESET_BYTE_BUFFER) {
290                     fwrite(static_cast<void*>(buffer->mMemory->getPointer()),
291                            sizeof(char),
292                            msg.data.extendedBufferData.rangeLength, ofp);
293                     fclose(ofp);
294                     count++;
295                 }
296 #endif
297             }
298         }
299     }
300
301     enum standardComp {
302         h263,
303         avc,
304         mpeg2,
305         mpeg4,
306         hevc,
307         vp8,
308         vp9,
309         unknown_comp,
310     };
311
312     sp<IOmx> omx;
313     sp<CodecObserver> observer;
314     sp<IOmxNode> omxNode;
315     standardComp compName;
316     OMX_VIDEO_CODINGTYPE eCompressionFormat;
317     bool disableTest;
318     PortMode portMode[2];
319     bool eosFlag;
320     uint32_t framesReceived;
321     uint64_t timestampUs;
322     ::android::List<uint64_t> timestampUslist;
323     bool timestampDevTest;
324     bool isSecure;
325
326    protected:
327     static void description(const std::string& description) {
328         RecordProperty("description", description);
329     }
330 };
331
332 // Set Default port param.
333 void setDefaultPortParam(sp<IOmxNode> omxNode, OMX_U32 portIndex,
334                          OMX_VIDEO_CODINGTYPE eCompressionFormat,
335                          OMX_COLOR_FORMATTYPE eColorFormat,
336                          OMX_U32 nFrameWidth = 352, OMX_U32 nFrameHeight = 288,
337                          OMX_U32 nBitrate = 0,
338                          OMX_U32 xFramerate = (24U << 16)) {
339     switch ((int)eCompressionFormat) {
340         case OMX_VIDEO_CodingUnused:
341             setupRAWPort(omxNode, portIndex, nFrameWidth, nFrameHeight,
342                          nBitrate, xFramerate, eColorFormat);
343             break;
344         default:
345             break;
346     }
347 }
348
349 // In decoder components, often the input port parameters get updated upon
350 // parsing the header of elementary stream. Client needs to collect this
351 // information to reconfigure other ports that share data with this input
352 // port.
353 void getInputChannelInfo(sp<IOmxNode> omxNode, OMX_U32 kPortIndexInput,
354                          uint32_t* nFrameWidth, uint32_t* nFrameHeight,
355                          uint32_t* xFramerate) {
356     android::hardware::media::omx::V1_0::Status status;
357     *nFrameWidth = 352;
358     *nFrameHeight = 288;
359     *xFramerate = (24U << 16);
360
361     OMX_PARAM_PORTDEFINITIONTYPE portDef;
362     status = getPortParam(omxNode, OMX_IndexParamPortDefinition,
363                           kPortIndexInput, &portDef);
364     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
365     if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
366         *nFrameWidth = portDef.format.video.nFrameWidth;
367         *nFrameHeight = portDef.format.video.nFrameHeight;
368         *xFramerate = portDef.format.video.xFramerate;
369     }
370 }
371
372 // LookUpTable of clips and metadata for component testing
373 void GetURLForComponent(VideoDecHidlTest::standardComp comp, char* mURL,
374                         char* info) {
375     struct CompToURL {
376         VideoDecHidlTest::standardComp comp;
377         const char* mURL;
378         const char* info;
379     };
380     static const CompToURL kCompToURL[] = {
381         {VideoDecHidlTest::standardComp::avc,
382          "bbb_avc_1920x1080_5000kbps_30fps.h264",
383          "bbb_avc_1920x1080_5000kbps_30fps.info"},
384         {VideoDecHidlTest::standardComp::hevc,
385          "bbb_hevc_640x360_1600kbps_30fps.hevc",
386          "bbb_hevc_640x360_1600kbps_30fps.info"},
387         {VideoDecHidlTest::standardComp::mpeg2,
388          "bbb_mpeg2_176x144_105kbps_25fps.m2v",
389          "bbb_mpeg2_176x144_105kbps_25fps.info"},
390         {VideoDecHidlTest::standardComp::h263,
391          "bbb_h263_352x288_300kbps_12fps.h263",
392          "bbb_h263_352x288_300kbps_12fps.info"},
393         {VideoDecHidlTest::standardComp::mpeg4,
394          "bbb_mpeg4_1280x720_1000kbps_25fps.m4v",
395          "bbb_mpeg4_1280x720_1000kbps_25fps.info"},
396         {VideoDecHidlTest::standardComp::vp8, "bbb_vp8_640x360_2mbps_30fps.vp8",
397          "bbb_vp8_640x360_2mbps_30fps.info"},
398         {VideoDecHidlTest::standardComp::vp9,
399          "bbb_vp9_640x360_1600kbps_30fps.vp9",
400          "bbb_vp9_640x360_1600kbps_30fps.info"},
401     };
402
403     for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
404         if (kCompToURL[i].comp == comp) {
405             strcat(mURL, kCompToURL[i].mURL);
406             strcat(info, kCompToURL[i].info);
407             return;
408         }
409     }
410 }
411
412 void allocateGraphicBuffers(sp<IOmxNode> omxNode, OMX_U32 portIndex,
413                             android::Vector<BufferInfo>* buffArray,
414                             uint32_t nFrameWidth, uint32_t nFrameHeight,
415                             int32_t* nStride, int format, uint32_t count) {
416     android::hardware::media::omx::V1_0::Status status;
417     sp<android::hardware::graphics::allocator::V2_0::IAllocator> allocator =
418         android::hardware::graphics::allocator::V2_0::IAllocator::getService();
419     ASSERT_NE(nullptr, allocator.get());
420
421     sp<android::hardware::graphics::mapper::V2_0::IMapper> mapper =
422         android::hardware::graphics::mapper::V2_0::IMapper::getService();
423     ASSERT_NE(mapper.get(), nullptr);
424
425     android::hardware::graphics::mapper::V2_0::IMapper::BufferDescriptorInfo
426         descriptorInfo;
427     uint32_t usage;
428
429     descriptorInfo.width = nFrameWidth;
430     descriptorInfo.height = nFrameHeight;
431     descriptorInfo.layerCount = 1;
432     descriptorInfo.format = static_cast<PixelFormat>(format);
433     descriptorInfo.usage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN);
434     omxNode->getGraphicBufferUsage(
435         portIndex,
436         [&status, &usage](android::hardware::media::omx::V1_0::Status _s,
437                           uint32_t _n1) {
438             status = _s;
439             usage = _n1;
440         });
441     if (status == android::hardware::media::omx::V1_0::Status::OK) {
442         descriptorInfo.usage |= usage;
443     }
444
445     ::android::hardware::hidl_vec<uint32_t> descriptor;
446     android::hardware::graphics::mapper::V2_0::Error error;
447     mapper->createDescriptor(
448         descriptorInfo, [&error, &descriptor](
449                             android::hardware::graphics::mapper::V2_0::Error _s,
450                             ::android::hardware::hidl_vec<uint32_t> _n1) {
451             error = _s;
452             descriptor = _n1;
453         });
454     EXPECT_EQ(error, android::hardware::graphics::mapper::V2_0::Error::NONE);
455
456     EXPECT_EQ(buffArray->size(), count);
457
458     static volatile int32_t nextId = 0;
459     uint64_t id = static_cast<uint64_t>(getpid()) << 32;
460     allocator->allocate(
461         descriptor, count,
462         [&](android::hardware::graphics::mapper::V2_0::Error _s, uint32_t _n1,
463             const ::android::hardware::hidl_vec<
464                 ::android::hardware::hidl_handle>& _n2) {
465             ASSERT_EQ(android::hardware::graphics::mapper::V2_0::Error::NONE,
466                       _s);
467             *nStride = _n1;
468             ASSERT_EQ(count, _n2.size());
469             for (uint32_t i = 0; i < count; i++) {
470                 buffArray->editItemAt(i).omxBuffer.nativeHandle = _n2[i];
471                 buffArray->editItemAt(i).omxBuffer.attr.anwBuffer.width =
472                     nFrameWidth;
473                 buffArray->editItemAt(i).omxBuffer.attr.anwBuffer.height =
474                     nFrameHeight;
475                 buffArray->editItemAt(i).omxBuffer.attr.anwBuffer.stride = _n1;
476                 buffArray->editItemAt(i).omxBuffer.attr.anwBuffer.format =
477                     descriptorInfo.format;
478                 buffArray->editItemAt(i).omxBuffer.attr.anwBuffer.usage =
479                     descriptorInfo.usage;
480                 buffArray->editItemAt(i).omxBuffer.attr.anwBuffer.layerCount =
481                     descriptorInfo.layerCount;
482                 buffArray->editItemAt(i).omxBuffer.attr.anwBuffer.id =
483                     id | static_cast<uint32_t>(android_atomic_inc(&nextId));
484             }
485         });
486 }
487
488 // port settings reconfiguration during runtime. reconfigures frame dimensions
489 void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
490                          android::Vector<BufferInfo>* iBuffer,
491                          android::Vector<BufferInfo>* oBuffer,
492                          OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
493                          Message msg, PortMode oPortMode, void* args) {
494     android::hardware::media::omx::V1_0::Status status;
495     (void)args;
496
497     if (msg.data.eventData.event == OMX_EventPortSettingsChanged) {
498         ASSERT_EQ(msg.data.eventData.data1, kPortIndexOutput);
499         if (msg.data.eventData.data2 == OMX_IndexParamPortDefinition ||
500             msg.data.eventData.data2 == 0) {
501             status = omxNode->sendCommand(
502                 toRawCommandType(OMX_CommandPortDisable), kPortIndexOutput);
503             ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
504
505             status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer,
506                                               oBuffer);
507             if (status ==
508                 android::hardware::media::omx::V1_0::Status::TIMED_OUT) {
509                 for (size_t i = 0; i < oBuffer->size(); ++i) {
510                     // test if client got all its buffers back
511                     EXPECT_EQ((*oBuffer)[i].owner, client);
512                     // free the buffers
513                     status =
514                         omxNode->freeBuffer(kPortIndexOutput, (*oBuffer)[i].id);
515                     ASSERT_EQ(status,
516                               android::hardware::media::omx::V1_0::Status::OK);
517                 }
518                 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
519                                                   iBuffer, oBuffer);
520                 ASSERT_EQ(status,
521                           android::hardware::media::omx::V1_0::Status::OK);
522                 ASSERT_EQ(msg.type, Message::Type::EVENT);
523                 ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
524                 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortDisable);
525                 ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
526
527                 // set Port Params
528                 uint32_t nFrameWidth, nFrameHeight, xFramerate;
529                 getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth,
530                                     &nFrameHeight, &xFramerate);
531                 // get configured color format
532                 OMX_PARAM_PORTDEFINITIONTYPE portDef;
533                 status = getPortParam(omxNode, OMX_IndexParamPortDefinition,
534                                       kPortIndexOutput, &portDef);
535                 setDefaultPortParam(omxNode, kPortIndexOutput,
536                                     OMX_VIDEO_CodingUnused,
537                                     portDef.format.video.eColorFormat,
538                                     nFrameWidth, nFrameHeight, 0, xFramerate);
539
540                 // If you can disable a port, then you should be able to
541                 // enable
542                 // it as well
543                 status = omxNode->sendCommand(
544                     toRawCommandType(OMX_CommandPortEnable), kPortIndexOutput);
545                 ASSERT_EQ(status,
546                           android::hardware::media::omx::V1_0::Status::OK);
547
548                 // do not enable the port until all the buffers are supplied
549                 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
550                                                   iBuffer, oBuffer);
551                 ASSERT_EQ(
552                     status,
553                     android::hardware::media::omx::V1_0::Status::TIMED_OUT);
554
555                 allocatePortBuffers(omxNode, oBuffer, kPortIndexOutput,
556                                     oPortMode);
557                 if (oPortMode != PortMode::PRESET_BYTE_BUFFER) {
558                     OMX_PARAM_PORTDEFINITIONTYPE portDef;
559
560                     status = getPortParam(omxNode, OMX_IndexParamPortDefinition,
561                                           kPortIndexOutput, &portDef);
562                     ASSERT_EQ(
563                         status,
564                         ::android::hardware::media::omx::V1_0::Status::OK);
565                     allocateGraphicBuffers(omxNode, kPortIndexOutput, oBuffer,
566                                            portDef.format.video.nFrameWidth,
567                                            portDef.format.video.nFrameHeight,
568                                            &portDef.format.video.nStride,
569                                            portDef.format.video.eColorFormat,
570                                            portDef.nBufferCountActual);
571                 }
572                 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
573                                                   iBuffer, oBuffer);
574                 ASSERT_EQ(status,
575                           android::hardware::media::omx::V1_0::Status::OK);
576                 ASSERT_EQ(msg.type, Message::Type::EVENT);
577                 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortEnable);
578                 ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
579
580                 // dispatch output buffers
581                 for (size_t i = 0; i < oBuffer->size(); i++) {
582                     dispatchOutputBuffer(omxNode, oBuffer, i, oPortMode);
583                 }
584             } else {
585                 ASSERT_TRUE(false);
586             }
587         } else if (msg.data.eventData.data2 ==
588                    OMX_IndexConfigCommonOutputCrop) {
589             std::cout << "[          ] Warning ! OMX_EventPortSettingsChanged/ "
590                          "OMX_IndexConfigCommonOutputCrop not handled \n";
591         } else if (msg.data.eventData.data2 == OMX_IndexVendorStartUnused + 3) {
592             std::cout << "[          ] Warning ! OMX_EventPortSettingsChanged/ "
593                          "kDescribeColorAspectsIndex not handled \n";
594         }
595     } else if (msg.data.eventData.event == OMX_EventError) {
596         std::cout << "[          ] Warning ! OMX_EventError/ "
597                      "Decode Frame Call might be failed \n";
598         return;
599     } else {
600         // something unexpected happened
601         ASSERT_TRUE(false);
602     }
603 }
604
605 // blocking call to ensures application to Wait till all the inputs are consumed
606 void waitOnInputConsumption(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
607                             android::Vector<BufferInfo>* iBuffer,
608                             android::Vector<BufferInfo>* oBuffer,
609                             OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
610                             PortMode oPortMode) {
611     android::hardware::media::omx::V1_0::Status status;
612     Message msg;
613     int timeOut = TIMEOUT_COUNTER_Q;
614
615     while (timeOut--) {
616         size_t i = 0;
617         status =
618             observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
619         if (status == android::hardware::media::omx::V1_0::Status::OK) {
620             EXPECT_EQ(msg.type, Message::Type::EVENT);
621             portReconfiguration(omxNode, observer, iBuffer, oBuffer,
622                                 kPortIndexInput, kPortIndexOutput, msg,
623                                 oPortMode, nullptr);
624         }
625         // status == TIMED_OUT, it could be due to process time being large
626         // than DEFAULT_TIMEOUT or component needs output buffers to start
627         // processing.
628         for (; i < iBuffer->size(); i++) {
629             if ((*iBuffer)[i].owner != client) break;
630         }
631         if (i == iBuffer->size()) break;
632
633         // Dispatch an output buffer assuming outQueue.empty() is true
634         size_t index;
635         if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
636             dispatchOutputBuffer(omxNode, oBuffer, index, oPortMode);
637             timeOut = TIMEOUT_COUNTER_Q;
638         }
639     }
640 }
641
642 // Decode N Frames
643 void decodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
644                    android::Vector<BufferInfo>* iBuffer,
645                    android::Vector<BufferInfo>* oBuffer,
646                    OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
647                    std::ifstream& eleStream, android::Vector<FrameData>* Info,
648                    int offset, int range, PortMode oPortMode,
649                    bool signalEOS = true) {
650     android::hardware::media::omx::V1_0::Status status;
651     Message msg;
652
653     // dispatch output buffers
654     for (size_t i = 0; i < oBuffer->size(); i++) {
655         dispatchOutputBuffer(omxNode, oBuffer, i, oPortMode);
656     }
657     // dispatch input buffers
658     uint32_t flags = 0;
659     int frameID = offset;
660     for (size_t i = 0; (i < iBuffer->size()) && (frameID < (int)Info->size()) &&
661                        (frameID < (offset + range));
662          i++) {
663         char* ipBuffer = static_cast<char*>(
664             static_cast<void*>((*iBuffer)[i].mMemory->getPointer()));
665         ASSERT_LE((*Info)[frameID].bytesCount,
666                   static_cast<int>((*iBuffer)[i].mMemory->getSize()));
667         eleStream.read(ipBuffer, (*Info)[frameID].bytesCount);
668         ASSERT_EQ(eleStream.gcount(), (*Info)[frameID].bytesCount);
669         flags = (*Info)[frameID].flags;
670         if (signalEOS && ((frameID == (int)Info->size() - 1) ||
671                           (frameID == (offset + range - 1))))
672             flags |= OMX_BUFFERFLAG_EOS;
673         dispatchInputBuffer(omxNode, iBuffer, i, (*Info)[frameID].bytesCount,
674                             flags, (*Info)[frameID].timestamp);
675         frameID++;
676     }
677
678     int timeOut = TIMEOUT_COUNTER_Q;
679     bool iQueued, oQueued;
680     while (1) {
681         iQueued = oQueued = false;
682         status =
683             observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
684
685         // Port Reconfiguration
686         if (status == android::hardware::media::omx::V1_0::Status::OK &&
687             msg.type == Message::Type::EVENT) {
688             portReconfiguration(omxNode, observer, iBuffer, oBuffer,
689                                 kPortIndexInput, kPortIndexOutput, msg,
690                                 oPortMode, nullptr);
691         }
692
693         if (frameID == (int)Info->size() || frameID == (offset + range)) break;
694
695         // Dispatch input buffer
696         size_t index = 0;
697         if ((index = getEmptyBufferID(iBuffer)) < iBuffer->size()) {
698             char* ipBuffer = static_cast<char*>(
699                 static_cast<void*>((*iBuffer)[index].mMemory->getPointer()));
700             ASSERT_LE((*Info)[frameID].bytesCount,
701                       static_cast<int>((*iBuffer)[index].mMemory->getSize()));
702             eleStream.read(ipBuffer, (*Info)[frameID].bytesCount);
703             ASSERT_EQ(eleStream.gcount(), (*Info)[frameID].bytesCount);
704             flags = (*Info)[frameID].flags;
705             if (signalEOS && ((frameID == (int)Info->size() - 1) ||
706                               (frameID == (offset + range - 1))))
707                 flags |= OMX_BUFFERFLAG_EOS;
708             dispatchInputBuffer(omxNode, iBuffer, index,
709                                 (*Info)[frameID].bytesCount, flags,
710                                 (*Info)[frameID].timestamp);
711             frameID++;
712             iQueued = true;
713         }
714         if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
715             dispatchOutputBuffer(omxNode, oBuffer, index, oPortMode);
716             oQueued = true;
717         }
718         if (iQueued || oQueued)
719             timeOut = TIMEOUT_COUNTER_Q;
720         else
721             timeOut--;
722         if (timeOut == 0) {
723             EXPECT_TRUE(false) << "Wait on Input/Output is found indefinite";
724             break;
725         }
726     }
727 }
728
729 // DescribeColorFormatParams Copy Constructor (Borrowed from OMXUtils.cpp)
730 android::DescribeColorFormatParams::DescribeColorFormatParams(
731     const android::DescribeColorFormat2Params& params) {
732     eColorFormat = params.eColorFormat;
733     nFrameWidth = params.nFrameWidth;
734     nFrameHeight = params.nFrameHeight;
735     nStride = params.nStride;
736     nSliceHeight = params.nSliceHeight;
737     bUsingNativeBuffers = params.bUsingNativeBuffers;
738 };
739
740 bool isColorFormatFlexibleYUV(sp<IOmxNode> omxNode,
741                               OMX_COLOR_FORMATTYPE eColorFormat) {
742     android::hardware::media::omx::V1_0::Status status;
743     unsigned int index = OMX_IndexMax, index2 = OMX_IndexMax;
744     omxNode->getExtensionIndex(
745         "OMX.google.android.index.describeColorFormat",
746         [&index](android::hardware::media::omx::V1_0::Status _s,
747                           unsigned int _nl) {
748             if (_s == ::android::hardware::media::omx::V1_0::Status::OK)
749                 index = _nl;
750         });
751     omxNode->getExtensionIndex(
752         "OMX.google.android.index.describeColorFormat2",
753         [&index2](android::hardware::media::omx::V1_0::Status _s,
754                            unsigned int _nl) {
755             if (_s == ::android::hardware::media::omx::V1_0::Status::OK)
756                 index2 = _nl;
757         });
758
759     android::DescribeColorFormat2Params describeParams;
760     describeParams.eColorFormat = eColorFormat;
761     describeParams.nFrameWidth = 128;
762     describeParams.nFrameHeight = 128;
763     describeParams.nStride = 128;
764     describeParams.nSliceHeight = 128;
765     describeParams.bUsingNativeBuffers = OMX_FALSE;
766     if (index != OMX_IndexMax) {
767         android::DescribeColorFormatParams describeParamsV1(describeParams);
768         status = getParam(omxNode, static_cast<OMX_INDEXTYPE>(index),
769                           &describeParamsV1);
770         if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
771             android::MediaImage& img = describeParamsV1.sMediaImage;
772             if (img.mType == android::MediaImage::MEDIA_IMAGE_TYPE_YUV) {
773                 if (img.mNumPlanes == 3 &&
774                     img.mPlane[img.Y].mHorizSubsampling == 1 &&
775                     img.mPlane[img.Y].mVertSubsampling == 1) {
776                     if (img.mPlane[img.U].mHorizSubsampling == 2 &&
777                         img.mPlane[img.U].mVertSubsampling == 2 &&
778                         img.mPlane[img.V].mHorizSubsampling == 2 &&
779                         img.mPlane[img.V].mVertSubsampling == 2) {
780                         if (img.mBitDepth <= 8) {
781                             return true;
782                         }
783                     }
784                 }
785             }
786         }
787     } else if (index2 != OMX_IndexMax) {
788         status = getParam(omxNode, static_cast<OMX_INDEXTYPE>(index2),
789                           &describeParams);
790         android::MediaImage2& img = describeParams.sMediaImage;
791         if (img.mType == android::MediaImage2::MEDIA_IMAGE_TYPE_YUV) {
792             if (img.mNumPlanes == 3 &&
793                 img.mPlane[img.Y].mHorizSubsampling == 1 &&
794                 img.mPlane[img.Y].mVertSubsampling == 1) {
795                 if (img.mPlane[img.U].mHorizSubsampling == 2 &&
796                     img.mPlane[img.U].mVertSubsampling == 2 &&
797                     img.mPlane[img.V].mHorizSubsampling == 2 &&
798                     img.mPlane[img.V].mVertSubsampling == 2) {
799                     if (img.mBitDepth <= 8) {
800                         return true;
801                     }
802                 }
803             }
804         }
805     }
806     return false;
807 }
808
809 // get default color format for output port
810 void getDefaultColorFormat(sp<IOmxNode> omxNode, OMX_U32 kPortIndexOutput,
811                            PortMode oPortMode,
812                            OMX_COLOR_FORMATTYPE* eColorFormat) {
813     android::hardware::media::omx::V1_0::Status status;
814     OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
815     *eColorFormat = OMX_COLOR_FormatUnused;
816     portFormat.nIndex = 0;
817     while (1) {
818         status = getPortParam(omxNode, OMX_IndexParamVideoPortFormat,
819                               kPortIndexOutput, &portFormat);
820         if (status != ::android::hardware::media::omx::V1_0::Status::OK) break;
821         EXPECT_EQ(portFormat.eCompressionFormat, OMX_VIDEO_CodingUnused);
822         if (oPortMode != PortMode::PRESET_BYTE_BUFFER) {
823             *eColorFormat = portFormat.eColorFormat;
824             break;
825         }
826         if (isColorFormatFlexibleYUV(omxNode, portFormat.eColorFormat)) {
827             *eColorFormat = portFormat.eColorFormat;
828             break;
829         }
830         if (OMX_COLOR_FormatYUV420SemiPlanar == portFormat.eColorFormat ||
831             OMX_COLOR_FormatYUV420Planar == portFormat.eColorFormat) {
832             *eColorFormat = portFormat.eColorFormat;
833             break;
834         }
835         portFormat.nIndex++;
836     }
837 }
838
839 // set component role
840 TEST_F(VideoDecHidlTest, SetRole) {
841     description("Test Set Component Role");
842     if (disableTest) return;
843     android::hardware::media::omx::V1_0::Status status;
844     status = setRole(omxNode, gEnv->getRole().c_str());
845     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
846 }
847
848 // port format enumeration
849 TEST_F(VideoDecHidlTest, EnumeratePortFormat) {
850     description("Test Component on Mandatory Port Parameters (Port Format)");
851     if (disableTest) return;
852     android::hardware::media::omx::V1_0::Status status;
853     uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
854     OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatYUV420Planar;
855     OMX_U32 xFramerate = (24U << 16);
856     status = setRole(omxNode, gEnv->getRole().c_str());
857     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
858     OMX_PORT_PARAM_TYPE params;
859     status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
860     if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
861         ASSERT_EQ(params.nPorts, 2U);
862         kPortIndexInput = params.nStartPortNumber;
863         kPortIndexOutput = kPortIndexInput + 1;
864     }
865     status = setVideoPortFormat(omxNode, kPortIndexInput, eCompressionFormat,
866                                 OMX_COLOR_FormatUnused, 0U);
867     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
868     status =
869         setVideoPortFormat(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
870                            eColorFormat, xFramerate);
871     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
872 }
873
874 // test port settings reconfiguration, elementary stream decode and timestamp
875 // deviation
876 TEST_F(VideoDecHidlTest, DecodeTest) {
877     description("Tests Port Reconfiguration, Decode and timestamp deviation");
878     if (disableTest) return;
879     android::hardware::media::omx::V1_0::Status status;
880     uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
881     status = setRole(omxNode, gEnv->getRole().c_str());
882     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
883     OMX_PORT_PARAM_TYPE params;
884     status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
885     if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
886         ASSERT_EQ(params.nPorts, 2U);
887         kPortIndexInput = params.nStartPortNumber;
888         kPortIndexOutput = kPortIndexInput + 1;
889     }
890     char mURL[512], info[512];
891     strcpy(mURL, gEnv->getRes().c_str());
892     strcpy(info, gEnv->getRes().c_str());
893     GetURLForComponent(compName, mURL, info);
894
895     std::ifstream eleStream, eleInfo;
896
897     eleInfo.open(info);
898     ASSERT_EQ(eleInfo.is_open(), true);
899     android::Vector<FrameData> Info;
900     int bytesCount = 0;
901     uint32_t flags = 0;
902     uint32_t timestamp = 0;
903     timestampDevTest = true;
904     while (1) {
905         if (!(eleInfo >> bytesCount)) break;
906         eleInfo >> flags;
907         eleInfo >> timestamp;
908         Info.push_back({bytesCount, flags, timestamp});
909         if (flags != OMX_BUFFERFLAG_CODECCONFIG)
910             timestampUslist.push_back(timestamp);
911     }
912     eleInfo.close();
913
914     // set port mode
915     portMode[0] = PortMode::PRESET_BYTE_BUFFER;
916     portMode[1] = PortMode::DYNAMIC_ANW_BUFFER;
917     status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
918     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
919     status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
920     if (status != ::android::hardware::media::omx::V1_0::Status::OK) {
921         portMode[1] = PortMode::PRESET_BYTE_BUFFER;
922         status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
923         ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
924     }
925
926     // set Port Params
927     uint32_t nFrameWidth, nFrameHeight, xFramerate;
928     getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight,
929                         &xFramerate);
930     // get default color format
931     OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused;
932     getDefaultColorFormat(omxNode, kPortIndexOutput, portMode[1],
933                           &eColorFormat);
934     ASSERT_NE(eColorFormat, OMX_COLOR_FormatUnused);
935     status =
936         setVideoPortFormat(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
937                            eColorFormat, xFramerate);
938     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
939     setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
940                         eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
941     omxNode->prepareForAdaptivePlayback(kPortIndexOutput, false, 1920, 1080);
942
943     android::Vector<BufferInfo> iBuffer, oBuffer;
944
945     // set state to idle
946     changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
947                             kPortIndexInput, kPortIndexOutput, portMode);
948     // set state to executing
949     changeStateIdletoExecute(omxNode, observer);
950
951     if (portMode[1] != PortMode::PRESET_BYTE_BUFFER) {
952         OMX_PARAM_PORTDEFINITIONTYPE portDef;
953
954         status = getPortParam(omxNode, OMX_IndexParamPortDefinition,
955                               kPortIndexOutput, &portDef);
956         ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
957         allocateGraphicBuffers(
958             omxNode, kPortIndexOutput, &oBuffer,
959             portDef.format.video.nFrameWidth, portDef.format.video.nFrameHeight,
960             &portDef.format.video.nStride, portDef.format.video.eColorFormat,
961             portDef.nBufferCountActual);
962     }
963
964     // Port Reconfiguration
965     eleStream.open(mURL, std::ifstream::binary);
966     ASSERT_EQ(eleStream.is_open(), true);
967     decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
968                   kPortIndexOutput, eleStream, &Info, 0, (int)Info.size(),
969                   portMode[1]);
970     eleStream.close();
971     waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
972                            kPortIndexInput, kPortIndexOutput, portMode[1]);
973     testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, portMode,
974             portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr);
975     EXPECT_EQ(timestampUslist.empty(), true);
976     // set state to idle
977     changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
978     // set state to executing
979     changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
980                             kPortIndexInput, kPortIndexOutput);
981 }
982
983 // end of sequence test
984 TEST_F(VideoDecHidlTest, EOSTest_M) {
985     description("Test End of stream monkeying");
986     if (disableTest) return;
987     android::hardware::media::omx::V1_0::Status status;
988     uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
989     status = setRole(omxNode, gEnv->getRole().c_str());
990     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
991     OMX_PORT_PARAM_TYPE params;
992     status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
993     if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
994         ASSERT_EQ(params.nPorts, 2U);
995         kPortIndexInput = params.nStartPortNumber;
996         kPortIndexOutput = kPortIndexInput + 1;
997     }
998
999     // set port mode
1000     status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
1001     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1002     status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
1003     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1004
1005     // set Port Params
1006     uint32_t nFrameWidth, nFrameHeight, xFramerate;
1007     getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight,
1008                         &xFramerate);
1009     // get default color format
1010     OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused;
1011     getDefaultColorFormat(omxNode, kPortIndexOutput, portMode[1],
1012                           &eColorFormat);
1013     ASSERT_NE(eColorFormat, OMX_COLOR_FormatUnused);
1014     status =
1015         setVideoPortFormat(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
1016                            eColorFormat, xFramerate);
1017     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1018     setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
1019                         eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
1020
1021     android::Vector<BufferInfo> iBuffer, oBuffer;
1022
1023     // set state to idle
1024     changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
1025                             kPortIndexInput, kPortIndexOutput, portMode);
1026     // set state to executing
1027     changeStateIdletoExecute(omxNode, observer);
1028
1029     // request EOS at the start
1030     testEOS(omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, portMode,
1031             portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr);
1032     flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1033                kPortIndexOutput);
1034     EXPECT_GE(framesReceived, 0U);
1035     framesReceived = 0;
1036     timestampUs = 0;
1037
1038     // set state to idle
1039     changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
1040     // set state to executing
1041     changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
1042                             kPortIndexInput, kPortIndexOutput);
1043 }
1044
1045 // end of sequence test
1046 TEST_F(VideoDecHidlTest, ThumbnailTest) {
1047     description("Test Request for thumbnail");
1048     if (disableTest) return;
1049     android::hardware::media::omx::V1_0::Status status;
1050     uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1051     status = setRole(omxNode, gEnv->getRole().c_str());
1052     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1053     OMX_PORT_PARAM_TYPE params;
1054     status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
1055     if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1056         ASSERT_EQ(params.nPorts, 2U);
1057         kPortIndexInput = params.nStartPortNumber;
1058         kPortIndexOutput = kPortIndexInput + 1;
1059     }
1060     char mURL[512], info[512];
1061     strcpy(mURL, gEnv->getRes().c_str());
1062     strcpy(info, gEnv->getRes().c_str());
1063     GetURLForComponent(compName, mURL, info);
1064
1065     std::ifstream eleStream, eleInfo;
1066
1067     eleInfo.open(info);
1068     ASSERT_EQ(eleInfo.is_open(), true);
1069     android::Vector<FrameData> Info;
1070     int bytesCount = 0;
1071     uint32_t flags = 0;
1072     uint32_t timestamp = 0;
1073     while (1) {
1074         if (!(eleInfo >> bytesCount)) break;
1075         eleInfo >> flags;
1076         eleInfo >> timestamp;
1077         Info.push_back({bytesCount, flags, timestamp});
1078     }
1079     eleInfo.close();
1080
1081     // set port mode
1082     status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
1083     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1084     status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
1085     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1086
1087     // set Port Params
1088     uint32_t nFrameWidth, nFrameHeight, xFramerate;
1089     getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight,
1090                         &xFramerate);
1091     // get default color format
1092     OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused;
1093     getDefaultColorFormat(omxNode, kPortIndexOutput, portMode[1],
1094                           &eColorFormat);
1095     ASSERT_NE(eColorFormat, OMX_COLOR_FormatUnused);
1096     status =
1097         setVideoPortFormat(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
1098                            eColorFormat, xFramerate);
1099     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1100     setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
1101                         eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
1102
1103     android::Vector<BufferInfo> iBuffer, oBuffer;
1104
1105     // set state to idle
1106     changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
1107                             kPortIndexInput, kPortIndexOutput, portMode);
1108     // set state to executing
1109     changeStateIdletoExecute(omxNode, observer);
1110
1111     // request EOS for thumbnail
1112     size_t i = 0;
1113     while (!(Info[i].flags & OMX_BUFFERFLAG_SYNCFRAME)) i++;
1114     eleStream.open(mURL, std::ifstream::binary);
1115     ASSERT_EQ(eleStream.is_open(), true);
1116     decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1117                   kPortIndexOutput, eleStream, &Info, 0, i + 1, portMode[1]);
1118     eleStream.close();
1119     waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
1120                            kPortIndexInput, kPortIndexOutput, portMode[1]);
1121     testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, portMode,
1122             portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr);
1123     flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1124                kPortIndexOutput);
1125     EXPECT_GE(framesReceived, 1U);
1126     framesReceived = 0;
1127     timestampUs = 0;
1128
1129     eleStream.open(mURL, std::ifstream::binary);
1130     ASSERT_EQ(eleStream.is_open(), true);
1131     decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1132                   kPortIndexOutput, eleStream, &Info, 0, i + 1, portMode[1],
1133                   false);
1134     eleStream.close();
1135     waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
1136                            kPortIndexInput, kPortIndexOutput, portMode[1]);
1137     testEOS(omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, portMode,
1138             portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr);
1139     flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1140                kPortIndexOutput);
1141     EXPECT_GE(framesReceived, 1U);
1142     framesReceived = 0;
1143     timestampUs = 0;
1144
1145     // set state to idle
1146     changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
1147     // set state to executing
1148     changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
1149                             kPortIndexInput, kPortIndexOutput);
1150 }
1151
1152 // end of sequence test
1153 TEST_F(VideoDecHidlTest, SimpleEOSTest) {
1154     description("Test End of stream");
1155     if (disableTest) return;
1156     android::hardware::media::omx::V1_0::Status status;
1157     uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1158     status = setRole(omxNode, gEnv->getRole().c_str());
1159     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1160     OMX_PORT_PARAM_TYPE params;
1161     status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
1162     if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1163         ASSERT_EQ(params.nPorts, 2U);
1164         kPortIndexInput = params.nStartPortNumber;
1165         kPortIndexOutput = kPortIndexInput + 1;
1166     }
1167     char mURL[512], info[512];
1168     strcpy(mURL, gEnv->getRes().c_str());
1169     strcpy(info, gEnv->getRes().c_str());
1170     GetURLForComponent(compName, mURL, info);
1171
1172     std::ifstream eleStream, eleInfo;
1173
1174     eleInfo.open(info);
1175     ASSERT_EQ(eleInfo.is_open(), true);
1176     android::Vector<FrameData> Info;
1177     int bytesCount = 0;
1178     uint32_t flags = 0;
1179     uint32_t timestamp = 0;
1180     while (1) {
1181         if (!(eleInfo >> bytesCount)) break;
1182         eleInfo >> flags;
1183         eleInfo >> timestamp;
1184         Info.push_back({bytesCount, flags, timestamp});
1185     }
1186     eleInfo.close();
1187
1188     // set port mode
1189     status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
1190     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1191     status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
1192     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1193
1194     // set Port Params
1195     uint32_t nFrameWidth, nFrameHeight, xFramerate;
1196     getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight,
1197                         &xFramerate);
1198     // get default color format
1199     OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused;
1200     getDefaultColorFormat(omxNode, kPortIndexOutput, portMode[1],
1201                           &eColorFormat);
1202     ASSERT_NE(eColorFormat, OMX_COLOR_FormatUnused);
1203     status =
1204         setVideoPortFormat(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
1205                            eColorFormat, xFramerate);
1206     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1207     setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
1208                         eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
1209
1210     android::Vector<BufferInfo> iBuffer, oBuffer;
1211
1212     // set state to idle
1213     changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
1214                             kPortIndexInput, kPortIndexOutput, portMode);
1215     // set state to executing
1216     changeStateIdletoExecute(omxNode, observer);
1217
1218     // request EOS at the end
1219     eleStream.open(mURL, std::ifstream::binary);
1220     ASSERT_EQ(eleStream.is_open(), true);
1221     decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1222                   kPortIndexOutput, eleStream, &Info, 0, (int)Info.size(),
1223                   portMode[1], false);
1224     eleStream.close();
1225     waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
1226                            kPortIndexInput, kPortIndexOutput, portMode[1]);
1227     testEOS(omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, portMode,
1228             portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr);
1229     flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1230                kPortIndexOutput);
1231     framesReceived = 0;
1232     timestampUs = 0;
1233
1234     // set state to idle
1235     changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
1236     // set state to executing
1237     changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
1238                             kPortIndexInput, kPortIndexOutput);
1239 }
1240
1241 // test input/output port flush
1242 TEST_F(VideoDecHidlTest, FlushTest) {
1243     description("Test Flush");
1244     if (disableTest) return;
1245     android::hardware::media::omx::V1_0::Status status;
1246     uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1247     status = setRole(omxNode, gEnv->getRole().c_str());
1248     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1249     OMX_PORT_PARAM_TYPE params;
1250     status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
1251     if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1252         ASSERT_EQ(params.nPorts, 2U);
1253         kPortIndexInput = params.nStartPortNumber;
1254         kPortIndexOutput = kPortIndexInput + 1;
1255     }
1256     char mURL[512], info[512];
1257     strcpy(mURL, gEnv->getRes().c_str());
1258     strcpy(info, gEnv->getRes().c_str());
1259     GetURLForComponent(compName, mURL, info);
1260
1261     std::ifstream eleStream, eleInfo;
1262
1263     eleInfo.open(info);
1264     ASSERT_EQ(eleInfo.is_open(), true);
1265     android::Vector<FrameData> Info;
1266     int bytesCount = 0;
1267     uint32_t flags = 0;
1268     uint32_t timestamp = 0;
1269     while (1) {
1270         if (!(eleInfo >> bytesCount)) break;
1271         eleInfo >> flags;
1272         eleInfo >> timestamp;
1273         Info.push_back({bytesCount, flags, timestamp});
1274     }
1275     eleInfo.close();
1276
1277     // set port mode
1278     status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
1279     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1280     status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
1281     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1282
1283     // set Port Params
1284     uint32_t nFrameWidth, nFrameHeight, xFramerate;
1285     getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight,
1286                         &xFramerate);
1287     // get default color format
1288     OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused;
1289     getDefaultColorFormat(omxNode, kPortIndexOutput, portMode[1],
1290                           &eColorFormat);
1291     ASSERT_NE(eColorFormat, OMX_COLOR_FormatUnused);
1292     status =
1293         setVideoPortFormat(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
1294                            eColorFormat, xFramerate);
1295     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1296     setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
1297                         eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
1298
1299     android::Vector<BufferInfo> iBuffer, oBuffer;
1300
1301     // set state to idle
1302     changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
1303                             kPortIndexInput, kPortIndexOutput, portMode);
1304     // set state to executing
1305     changeStateIdletoExecute(omxNode, observer);
1306
1307     // Decode 128 frames and flush. here 128 is chosen to ensure there is a key
1308     // frame after this so that the below section can be convered for all
1309     // components
1310     int nFrames = 128;
1311     eleStream.open(mURL, std::ifstream::binary);
1312     ASSERT_EQ(eleStream.is_open(), true);
1313     decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1314                   kPortIndexOutput, eleStream, &Info, 0, nFrames, portMode[1],
1315                   false);
1316     flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1317                kPortIndexOutput);
1318     framesReceived = 0;
1319
1320     // Seek to next key frame and start decoding till the end
1321     int index = nFrames;
1322     bool keyFrame = false;
1323     while (index < (int)Info.size()) {
1324         if ((Info[index].flags & OMX_BUFFERFLAG_SYNCFRAME) ==
1325             OMX_BUFFERFLAG_SYNCFRAME) {
1326             timestampUs = Info[index - 1].timestamp;
1327             keyFrame = true;
1328             break;
1329         }
1330         eleStream.ignore(Info[index].bytesCount);
1331         index++;
1332     }
1333     if (keyFrame) {
1334         decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1335                       kPortIndexOutput, eleStream, &Info, index,
1336                       Info.size() - index, portMode[1], false);
1337     }
1338     flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1339                kPortIndexOutput);
1340     framesReceived = 0;
1341
1342     // set state to idle
1343     changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
1344     // set state to executing
1345     changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
1346                             kPortIndexInput, kPortIndexOutput);
1347 }
1348
1349 int main(int argc, char** argv) {
1350     gEnv = new ComponentTestEnvironment();
1351     ::testing::AddGlobalTestEnvironment(gEnv);
1352     ::testing::InitGoogleTest(&argc, argv);
1353     int status = gEnv->initFromOptions(argc, argv);
1354     if (status == 0) {
1355         status = RUN_ALL_TESTS();
1356         ALOGI("Test result = %d", status);
1357     }
1358     return status;
1359 }