OSDN Git Service

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