OSDN Git Service

Merge "Fix VtsHalGraphicsComposerV2_1TargetTest" into oc-mr1-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, maxBytesCount = 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 (timestampDevTest && (flags != OMX_BUFFERFLAG_CODECCONFIG))
910             timestampUslist.push_back(timestamp);
911         if (maxBytesCount < bytesCount) maxBytesCount = bytesCount;
912     }
913     eleInfo.close();
914
915     // As the frame sizes are known ahead, use it to configure i/p buffer size
916     maxBytesCount = ALIGN_POWER_OF_TWO(maxBytesCount, 10);
917     status = setPortBufferSize(omxNode, kPortIndexInput, maxBytesCount);
918     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
919
920     // set port mode
921     portMode[0] = PortMode::PRESET_BYTE_BUFFER;
922     portMode[1] = PortMode::DYNAMIC_ANW_BUFFER;
923     status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
924     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
925     status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
926     if (status != ::android::hardware::media::omx::V1_0::Status::OK) {
927         portMode[1] = PortMode::PRESET_BYTE_BUFFER;
928         status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
929         ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
930     }
931
932     // set Port Params
933     uint32_t nFrameWidth, nFrameHeight, xFramerate;
934     getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight,
935                         &xFramerate);
936     // get default color format
937     OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused;
938     getDefaultColorFormat(omxNode, kPortIndexOutput, portMode[1],
939                           &eColorFormat);
940     ASSERT_NE(eColorFormat, OMX_COLOR_FormatUnused);
941     status =
942         setVideoPortFormat(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
943                            eColorFormat, xFramerate);
944     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
945     setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
946                         eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
947
948     // disabling adaptive playback.
949     omxNode->prepareForAdaptivePlayback(kPortIndexOutput, false, 1920, 1080);
950
951     android::Vector<BufferInfo> iBuffer, oBuffer;
952
953     // set state to idle
954     changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
955                             kPortIndexInput, kPortIndexOutput, portMode);
956     // set state to executing
957     changeStateIdletoExecute(omxNode, observer);
958
959     if (portMode[1] != PortMode::PRESET_BYTE_BUFFER) {
960         OMX_PARAM_PORTDEFINITIONTYPE portDef;
961
962         status = getPortParam(omxNode, OMX_IndexParamPortDefinition,
963                               kPortIndexOutput, &portDef);
964         ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
965         allocateGraphicBuffers(
966             omxNode, kPortIndexOutput, &oBuffer,
967             portDef.format.video.nFrameWidth, portDef.format.video.nFrameHeight,
968             &portDef.format.video.nStride, portDef.format.video.eColorFormat,
969             portDef.nBufferCountActual);
970     }
971
972     // Port Reconfiguration
973     eleStream.open(mURL, std::ifstream::binary);
974     ASSERT_EQ(eleStream.is_open(), true);
975     decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
976                   kPortIndexOutput, eleStream, &Info, 0, (int)Info.size(),
977                   portMode[1]);
978     eleStream.close();
979     waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
980                            kPortIndexInput, kPortIndexOutput, portMode[1]);
981     testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, portMode,
982             portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr);
983     if (timestampDevTest) EXPECT_EQ(timestampUslist.empty(), true);
984     // set state to idle
985     changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
986     // set state to executing
987     changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
988                             kPortIndexInput, kPortIndexOutput);
989 }
990
991 // end of sequence test
992 TEST_F(VideoDecHidlTest, EOSTest_M) {
993     description("Test End of stream monkeying");
994     if (disableTest) return;
995     android::hardware::media::omx::V1_0::Status status;
996     uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
997     status = setRole(omxNode, gEnv->getRole().c_str());
998     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
999     OMX_PORT_PARAM_TYPE params;
1000     status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
1001     if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1002         ASSERT_EQ(params.nPorts, 2U);
1003         kPortIndexInput = params.nStartPortNumber;
1004         kPortIndexOutput = kPortIndexInput + 1;
1005     }
1006
1007     // set port mode
1008     status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
1009     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1010     status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
1011     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1012
1013     // set Port Params
1014     uint32_t nFrameWidth, nFrameHeight, xFramerate;
1015     getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight,
1016                         &xFramerate);
1017     // get default color format
1018     OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused;
1019     getDefaultColorFormat(omxNode, kPortIndexOutput, portMode[1],
1020                           &eColorFormat);
1021     ASSERT_NE(eColorFormat, OMX_COLOR_FormatUnused);
1022     status =
1023         setVideoPortFormat(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
1024                            eColorFormat, xFramerate);
1025     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1026     setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
1027                         eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
1028
1029     android::Vector<BufferInfo> iBuffer, oBuffer;
1030
1031     // set state to idle
1032     changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
1033                             kPortIndexInput, kPortIndexOutput, portMode);
1034     // set state to executing
1035     changeStateIdletoExecute(omxNode, observer);
1036
1037     // request EOS at the start
1038     testEOS(omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, portMode,
1039             portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr);
1040     flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1041                kPortIndexOutput);
1042     EXPECT_GE(framesReceived, 0U);
1043     framesReceived = 0;
1044     timestampUs = 0;
1045
1046     // set state to idle
1047     changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
1048     // set state to executing
1049     changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
1050                             kPortIndexInput, kPortIndexOutput);
1051 }
1052
1053 // end of sequence test
1054 TEST_F(VideoDecHidlTest, ThumbnailTest) {
1055     description("Test Request for thumbnail");
1056     if (disableTest) return;
1057     android::hardware::media::omx::V1_0::Status status;
1058     uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1059     status = setRole(omxNode, gEnv->getRole().c_str());
1060     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1061     OMX_PORT_PARAM_TYPE params;
1062     status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
1063     if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1064         ASSERT_EQ(params.nPorts, 2U);
1065         kPortIndexInput = params.nStartPortNumber;
1066         kPortIndexOutput = kPortIndexInput + 1;
1067     }
1068     char mURL[512], info[512];
1069     strcpy(mURL, gEnv->getRes().c_str());
1070     strcpy(info, gEnv->getRes().c_str());
1071     GetURLForComponent(compName, mURL, info);
1072
1073     std::ifstream eleStream, eleInfo;
1074
1075     eleInfo.open(info);
1076     ASSERT_EQ(eleInfo.is_open(), true);
1077     android::Vector<FrameData> Info;
1078     int bytesCount = 0, maxBytesCount = 0;
1079     uint32_t flags = 0;
1080     uint32_t timestamp = 0;
1081     while (1) {
1082         if (!(eleInfo >> bytesCount)) break;
1083         eleInfo >> flags;
1084         eleInfo >> timestamp;
1085         Info.push_back({bytesCount, flags, timestamp});
1086         if (maxBytesCount < bytesCount) maxBytesCount = bytesCount;
1087     }
1088     eleInfo.close();
1089
1090     // As the frame sizes are known ahead, use it to configure i/p buffer size
1091     maxBytesCount = ALIGN_POWER_OF_TWO(maxBytesCount, 10);
1092     status = setPortBufferSize(omxNode, kPortIndexInput, maxBytesCount);
1093     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1094
1095     // set port mode
1096     status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
1097     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1098     status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
1099     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1100
1101     // set Port Params
1102     uint32_t nFrameWidth, nFrameHeight, xFramerate;
1103     getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight,
1104                         &xFramerate);
1105     // get default color format
1106     OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused;
1107     getDefaultColorFormat(omxNode, kPortIndexOutput, portMode[1],
1108                           &eColorFormat);
1109     ASSERT_NE(eColorFormat, OMX_COLOR_FormatUnused);
1110     status =
1111         setVideoPortFormat(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
1112                            eColorFormat, xFramerate);
1113     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1114     setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
1115                         eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
1116
1117     android::Vector<BufferInfo> iBuffer, oBuffer;
1118
1119     // set state to idle
1120     changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
1121                             kPortIndexInput, kPortIndexOutput, portMode);
1122     // set state to executing
1123     changeStateIdletoExecute(omxNode, observer);
1124
1125     // request EOS for thumbnail
1126     size_t i = 0;
1127     while (!(Info[i].flags & OMX_BUFFERFLAG_SYNCFRAME)) i++;
1128     eleStream.open(mURL, std::ifstream::binary);
1129     ASSERT_EQ(eleStream.is_open(), true);
1130     decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1131                   kPortIndexOutput, eleStream, &Info, 0, i + 1, portMode[1]);
1132     eleStream.close();
1133     waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
1134                            kPortIndexInput, kPortIndexOutput, portMode[1]);
1135     testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, portMode,
1136             portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr);
1137     flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1138                kPortIndexOutput);
1139     EXPECT_GE(framesReceived, 1U);
1140     framesReceived = 0;
1141     timestampUs = 0;
1142
1143     eleStream.open(mURL, std::ifstream::binary);
1144     ASSERT_EQ(eleStream.is_open(), true);
1145     decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1146                   kPortIndexOutput, eleStream, &Info, 0, i + 1, portMode[1],
1147                   false);
1148     eleStream.close();
1149     waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
1150                            kPortIndexInput, kPortIndexOutput, portMode[1]);
1151     testEOS(omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, portMode,
1152             portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr);
1153     flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1154                kPortIndexOutput);
1155     EXPECT_GE(framesReceived, 1U);
1156     framesReceived = 0;
1157     timestampUs = 0;
1158
1159     // set state to idle
1160     changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
1161     // set state to executing
1162     changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
1163                             kPortIndexInput, kPortIndexOutput);
1164 }
1165
1166 // end of sequence test
1167 TEST_F(VideoDecHidlTest, SimpleEOSTest) {
1168     description("Test End of stream");
1169     if (disableTest) return;
1170     android::hardware::media::omx::V1_0::Status status;
1171     uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1172     status = setRole(omxNode, gEnv->getRole().c_str());
1173     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1174     OMX_PORT_PARAM_TYPE params;
1175     status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
1176     if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1177         ASSERT_EQ(params.nPorts, 2U);
1178         kPortIndexInput = params.nStartPortNumber;
1179         kPortIndexOutput = kPortIndexInput + 1;
1180     }
1181     char mURL[512], info[512];
1182     strcpy(mURL, gEnv->getRes().c_str());
1183     strcpy(info, gEnv->getRes().c_str());
1184     GetURLForComponent(compName, mURL, info);
1185
1186     std::ifstream eleStream, eleInfo;
1187
1188     eleInfo.open(info);
1189     ASSERT_EQ(eleInfo.is_open(), true);
1190     android::Vector<FrameData> Info;
1191     int bytesCount = 0, maxBytesCount = 0;
1192     uint32_t flags = 0;
1193     uint32_t timestamp = 0;
1194     while (1) {
1195         if (!(eleInfo >> bytesCount)) break;
1196         eleInfo >> flags;
1197         eleInfo >> timestamp;
1198         Info.push_back({bytesCount, flags, timestamp});
1199         if (maxBytesCount < bytesCount) maxBytesCount = bytesCount;
1200     }
1201     eleInfo.close();
1202
1203     // As the frame sizes are known ahead, use it to configure i/p buffer size
1204     maxBytesCount = ALIGN_POWER_OF_TWO(maxBytesCount, 10);
1205     status = setPortBufferSize(omxNode, kPortIndexInput, maxBytesCount);
1206     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1207
1208     // set port mode
1209     status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
1210     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1211     status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
1212     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1213
1214     // set Port Params
1215     uint32_t nFrameWidth, nFrameHeight, xFramerate;
1216     getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight,
1217                         &xFramerate);
1218     // get default color format
1219     OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused;
1220     getDefaultColorFormat(omxNode, kPortIndexOutput, portMode[1],
1221                           &eColorFormat);
1222     ASSERT_NE(eColorFormat, OMX_COLOR_FormatUnused);
1223     status =
1224         setVideoPortFormat(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
1225                            eColorFormat, xFramerate);
1226     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1227     setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
1228                         eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
1229
1230     android::Vector<BufferInfo> iBuffer, oBuffer;
1231
1232     // set state to idle
1233     changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
1234                             kPortIndexInput, kPortIndexOutput, portMode);
1235     // set state to executing
1236     changeStateIdletoExecute(omxNode, observer);
1237
1238     // request EOS at the end
1239     eleStream.open(mURL, std::ifstream::binary);
1240     ASSERT_EQ(eleStream.is_open(), true);
1241     decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1242                   kPortIndexOutput, eleStream, &Info, 0, (int)Info.size(),
1243                   portMode[1], false);
1244     eleStream.close();
1245     waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
1246                            kPortIndexInput, kPortIndexOutput, portMode[1]);
1247     testEOS(omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, portMode,
1248             portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr);
1249     flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1250                kPortIndexOutput);
1251     framesReceived = 0;
1252     timestampUs = 0;
1253
1254     // set state to idle
1255     changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
1256     // set state to executing
1257     changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
1258                             kPortIndexInput, kPortIndexOutput);
1259 }
1260
1261 // test input/output port flush
1262 TEST_F(VideoDecHidlTest, FlushTest) {
1263     description("Test Flush");
1264     if (disableTest) return;
1265     android::hardware::media::omx::V1_0::Status status;
1266     uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1267     status = setRole(omxNode, gEnv->getRole().c_str());
1268     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1269     OMX_PORT_PARAM_TYPE params;
1270     status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
1271     if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1272         ASSERT_EQ(params.nPorts, 2U);
1273         kPortIndexInput = params.nStartPortNumber;
1274         kPortIndexOutput = kPortIndexInput + 1;
1275     }
1276     char mURL[512], info[512];
1277     strcpy(mURL, gEnv->getRes().c_str());
1278     strcpy(info, gEnv->getRes().c_str());
1279     GetURLForComponent(compName, mURL, info);
1280
1281     std::ifstream eleStream, eleInfo;
1282
1283     eleInfo.open(info);
1284     ASSERT_EQ(eleInfo.is_open(), true);
1285     android::Vector<FrameData> Info;
1286     int bytesCount = 0, maxBytesCount = 0;
1287     uint32_t flags = 0;
1288     uint32_t timestamp = 0;
1289     while (1) {
1290         if (!(eleInfo >> bytesCount)) break;
1291         eleInfo >> flags;
1292         eleInfo >> timestamp;
1293         Info.push_back({bytesCount, flags, timestamp});
1294         if (maxBytesCount < bytesCount) maxBytesCount = bytesCount;
1295     }
1296     eleInfo.close();
1297
1298     // As the frame sizes are known ahead, use it to configure i/p buffer size
1299     maxBytesCount = ALIGN_POWER_OF_TWO(maxBytesCount, 10);
1300     status = setPortBufferSize(omxNode, kPortIndexInput, maxBytesCount);
1301     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1302
1303     // set port mode
1304     status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
1305     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1306     status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
1307     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1308
1309     // set Port Params
1310     uint32_t nFrameWidth, nFrameHeight, xFramerate;
1311     getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight,
1312                         &xFramerate);
1313     // get default color format
1314     OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused;
1315     getDefaultColorFormat(omxNode, kPortIndexOutput, portMode[1],
1316                           &eColorFormat);
1317     ASSERT_NE(eColorFormat, OMX_COLOR_FormatUnused);
1318     status =
1319         setVideoPortFormat(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
1320                            eColorFormat, xFramerate);
1321     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1322     setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
1323                         eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
1324
1325     android::Vector<BufferInfo> iBuffer, oBuffer;
1326
1327     // set state to idle
1328     changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
1329                             kPortIndexInput, kPortIndexOutput, portMode);
1330     // set state to executing
1331     changeStateIdletoExecute(omxNode, observer);
1332
1333     // Decode 128 frames and flush. here 128 is chosen to ensure there is a key
1334     // frame after this so that the below section can be convered for all
1335     // components
1336     int nFrames = 128;
1337     eleStream.open(mURL, std::ifstream::binary);
1338     ASSERT_EQ(eleStream.is_open(), true);
1339     decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1340                   kPortIndexOutput, eleStream, &Info, 0, nFrames, portMode[1],
1341                   false);
1342     flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1343                kPortIndexOutput);
1344     framesReceived = 0;
1345
1346     // Seek to next key frame and start decoding till the end
1347     int index = nFrames;
1348     bool keyFrame = false;
1349     while (index < (int)Info.size()) {
1350         if ((Info[index].flags & OMX_BUFFERFLAG_SYNCFRAME) ==
1351             OMX_BUFFERFLAG_SYNCFRAME) {
1352             timestampUs = Info[index - 1].timestamp;
1353             keyFrame = true;
1354             break;
1355         }
1356         eleStream.ignore(Info[index].bytesCount);
1357         index++;
1358     }
1359     if (keyFrame) {
1360         decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1361                       kPortIndexOutput, eleStream, &Info, index,
1362                       Info.size() - index, portMode[1], false);
1363     }
1364     eleStream.close();
1365     flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1366                kPortIndexOutput);
1367     framesReceived = 0;
1368
1369     // set state to idle
1370     changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
1371     // set state to executing
1372     changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
1373                             kPortIndexInput, kPortIndexOutput);
1374 }
1375
1376 int main(int argc, char** argv) {
1377     gEnv = new ComponentTestEnvironment();
1378     ::testing::AddGlobalTestEnvironment(gEnv);
1379     ::testing::InitGoogleTest(&argc, argv);
1380     int status = gEnv->initFromOptions(argc, argv);
1381     if (status == 0) {
1382         status = RUN_ALL_TESTS();
1383         ALOGI("Test result = %d", status);
1384     }
1385     return status;
1386 }