2 * Copyright (C) 2017 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #define LOG_TAG "media_omx_hidl_video_dec_test"
18 #include <android-base/logging.h>
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>
31 using ::android::hardware::graphics::common::V1_0::BufferUsage;
32 using ::android::hardware::graphics::common::V1_0::PixelFormat;
33 using ::android::hardware::media::omx::V1_0::IOmx;
34 using ::android::hardware::media::omx::V1_0::IOmxObserver;
35 using ::android::hardware::media::omx::V1_0::IOmxNode;
36 using ::android::hardware::media::omx::V1_0::Message;
37 using ::android::hardware::media::omx::V1_0::CodecBuffer;
38 using ::android::hardware::media::omx::V1_0::PortMode;
39 using ::android::hidl::allocator::V1_0::IAllocator;
40 using ::android::hidl::memory::V1_0::IMemory;
41 using ::android::hidl::memory::V1_0::IMapper;
42 using ::android::hardware::Return;
43 using ::android::hardware::Void;
44 using ::android::hardware::hidl_vec;
45 using ::android::hardware::hidl_string;
48 #include <VtsHalHidlTargetTestBase.h>
50 #include <media_hidl_test_common.h>
51 #include <media_video_hidl_test_common.h>
54 // A class for test environment setup
55 class ComponentTestEnvironment : public ::testing::Environment {
57 virtual void SetUp() {}
58 virtual void TearDown() {}
60 ComponentTestEnvironment() : instance("default"), res("/sdcard/media/") {}
62 void setInstance(const char* _instance) { instance = _instance; }
64 void setComponent(const char* _component) { component = _component; }
66 void setRole(const char* _role) { role = _role; }
68 void setRes(const char* _res) { res = _res; }
70 const hidl_string getInstance() const { return instance; }
72 const hidl_string getComponent() const { return component; }
74 const hidl_string getRole() const { return role; }
76 const hidl_string getRes() const { return res; }
78 int initFromOptions(int argc, char** argv) {
79 static struct option options[] = {
80 {"instance", required_argument, 0, 'I'},
81 {"component", required_argument, 0, 'C'},
82 {"role", required_argument, 0, 'R'},
83 {"res", required_argument, 0, 'P'},
88 int c = getopt_long(argc, argv, "I:C:R:P:", options, &index);
113 "unrecognized option: %s\n\n"
114 "usage: %s <gtest options> <test options>\n\n"
115 "test options are:\n\n"
116 "-I, --instance: HAL instance to test\n"
117 "-C, --component: OMX component to test\n"
118 "-R, --role: OMX component Role\n"
119 "-P, --res: Resource files directory location\n",
120 argv[optind ?: 1], argv[0]);
127 hidl_string instance;
128 hidl_string component;
133 static ComponentTestEnvironment* gEnv = nullptr;
135 // video decoder test fixture class
136 class VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
138 typedef ::testing::VtsHalHidlTargetTestBase Super;
140 ::std::string getTestCaseInfo() const override {
141 return ::std::string() +
142 "Component: " + gEnv->getComponent().c_str() + " | " +
143 "Role: " + gEnv->getRole().c_str() + " | " +
144 "Instance: " + gEnv->getInstance().c_str() + " | " +
145 "Res: " + gEnv->getRes().c_str();
148 virtual void SetUp() override {
151 android::hardware::media::omx::V1_0::Status status;
152 omx = Super::getService<IOmx>(gEnv->getInstance());
153 ASSERT_NE(omx, nullptr);
155 new CodecObserver([this](Message msg, const BufferInfo* buffer) {
156 handleMessage(msg, buffer);
158 ASSERT_NE(observer, nullptr);
159 if (strncmp(gEnv->getComponent().c_str(), "OMX.", 4) != 0)
161 EXPECT_TRUE(omx->allocateNode(
162 gEnv->getComponent(), observer,
163 [&](android::hardware::media::omx::V1_0::Status _s,
164 sp<IOmxNode> const& _nl) {
169 ASSERT_NE(omxNode, nullptr);
170 ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
171 struct StringToName {
173 standardComp CompName;
175 const StringToName kStringToName[] = {
176 {"h263", h263}, {"avc", avc}, {"mpeg2", mpeg2}, {"mpeg4", mpeg4},
177 {"hevc", hevc}, {"vp8", vp8}, {"vp9", vp9},
179 const size_t kNumStringToName =
180 sizeof(kStringToName) / sizeof(kStringToName[0]);
182 char substring[OMX_MAX_STRINGNAME_SIZE];
183 strcpy(substring, gEnv->getRole().c_str());
184 pch = strchr(substring, '.');
185 ASSERT_NE(pch, nullptr);
186 compName = unknown_comp;
187 for (size_t i = 0; i < kNumStringToName; ++i) {
188 if (!strcasecmp(pch + 1, kStringToName[i].Name)) {
189 compName = kStringToName[i].CompName;
193 if (compName == unknown_comp) disableTest = true;
194 struct CompToCompression {
195 standardComp CompName;
196 OMX_VIDEO_CODINGTYPE eCompressionFormat;
198 static const CompToCompression kCompToCompression[] = {
199 {h263, OMX_VIDEO_CodingH263}, {avc, OMX_VIDEO_CodingAVC},
200 {mpeg2, OMX_VIDEO_CodingMPEG2}, {mpeg4, OMX_VIDEO_CodingMPEG4},
201 {hevc, OMX_VIDEO_CodingHEVC}, {vp8, OMX_VIDEO_CodingVP8},
202 {vp9, OMX_VIDEO_CodingVP9},
204 static const size_t kNumCompToCompression =
205 sizeof(kCompToCompression) / sizeof(kCompToCompression[0]);
207 for (i = 0; i < kNumCompToCompression; ++i) {
208 if (kCompToCompression[i].CompName == compName) {
209 eCompressionFormat = kCompToCompression[i].eCompressionFormat;
213 if (i == kNumCompToCompression) disableTest = true;
214 portMode[0] = portMode[1] = PortMode::PRESET_BYTE_BUFFER;
218 timestampDevTest = false;
220 size_t suffixLen = strlen(".secure");
221 if (strlen(gEnv->getComponent().c_str()) >= suffixLen) {
223 !strcmp(gEnv->getComponent().c_str() +
224 strlen(gEnv->getComponent().c_str()) - suffixLen,
227 if (isSecure) disableTest = true;
228 if (disableTest) std::cout << "[ ] Warning ! Test Disabled\n";
231 virtual void TearDown() override {
232 if (omxNode != nullptr) {
233 EXPECT_TRUE((omxNode->freeNode()).isOk());
239 // callback function to process messages received by onMessages() from IL
241 void handleMessage(Message msg, const BufferInfo* buffer) {
243 if (msg.type == Message::Type::FILL_BUFFER_DONE) {
244 if (msg.data.extendedBufferData.flags & OMX_BUFFERFLAG_EOS) {
247 if (msg.data.extendedBufferData.rangeLength != 0) {
249 // For decoder components current timestamp always exceeds
250 // previous timestamp
251 EXPECT_GE(msg.data.extendedBufferData.timestampUs, timestampUs);
252 timestampUs = msg.data.extendedBufferData.timestampUs;
253 // Test if current timestamp is among the list of queued
255 if (timestampDevTest) {
257 android::List<uint64_t>::iterator it =
258 timestampUslist.begin();
259 while (it != timestampUslist.end()) {
260 if (*it == timestampUs) {
261 timestampUslist.erase(it);
267 if (tsHit == false) {
268 if (timestampUslist.empty() == false) {
269 EXPECT_EQ(tsHit, true)
270 << "TimeStamp not recognized";
273 << "[ ] Warning ! Received non-zero "
274 "output / TimeStamp not recognized \n";
278 #define WRITE_OUTPUT 0
280 static int count = 0;
283 ofp = fopen("out.bin", "ab");
285 ofp = fopen("out.bin", "wb");
286 if (ofp != nullptr &&
287 portMode[1] == PortMode::PRESET_BYTE_BUFFER) {
288 fwrite(static_cast<void*>(buffer->mMemory->getPointer()),
290 msg.data.extendedBufferData.rangeLength, ofp);
311 sp<CodecObserver> observer;
312 sp<IOmxNode> omxNode;
313 standardComp compName;
314 OMX_VIDEO_CODINGTYPE eCompressionFormat;
316 PortMode portMode[2];
318 uint32_t framesReceived;
319 uint64_t timestampUs;
320 ::android::List<uint64_t> timestampUslist;
321 bool timestampDevTest;
325 static void description(const std::string& description) {
326 RecordProperty("description", description);
330 // Set Default port param.
331 void setDefaultPortParam(sp<IOmxNode> omxNode, OMX_U32 portIndex,
332 OMX_VIDEO_CODINGTYPE eCompressionFormat,
333 OMX_COLOR_FORMATTYPE eColorFormat,
334 OMX_U32 nFrameWidth = 352, OMX_U32 nFrameHeight = 288,
335 OMX_U32 nBitrate = 0,
336 OMX_U32 xFramerate = (24U << 16)) {
337 switch ((int)eCompressionFormat) {
338 case OMX_VIDEO_CodingUnused:
339 setupRAWPort(omxNode, portIndex, nFrameWidth, nFrameHeight,
340 nBitrate, xFramerate, eColorFormat);
347 // In decoder components, often the input port parameters get updated upon
348 // parsing the header of elementary stream. Client needs to collect this
349 // information to reconfigure other ports that share data with this input
351 void getInputChannelInfo(sp<IOmxNode> omxNode, OMX_U32 kPortIndexInput,
352 uint32_t* nFrameWidth, uint32_t* nFrameHeight,
353 uint32_t* xFramerate) {
354 android::hardware::media::omx::V1_0::Status status;
357 *xFramerate = (24U << 16);
359 OMX_PARAM_PORTDEFINITIONTYPE portDef;
360 status = getPortParam(omxNode, OMX_IndexParamPortDefinition,
361 kPortIndexInput, &portDef);
362 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
363 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
364 *nFrameWidth = portDef.format.video.nFrameWidth;
365 *nFrameHeight = portDef.format.video.nFrameHeight;
366 *xFramerate = portDef.format.video.xFramerate;
370 // LookUpTable of clips and metadata for component testing
371 void GetURLForComponent(VideoDecHidlTest::standardComp comp, char* mURL,
374 VideoDecHidlTest::standardComp comp;
378 static const CompToURL kCompToURL[] = {
379 {VideoDecHidlTest::standardComp::avc,
380 "bbb_avc_1920x1080_5000kbps_30fps.h264",
381 "bbb_avc_1920x1080_5000kbps_30fps.info"},
382 {VideoDecHidlTest::standardComp::hevc,
383 "bbb_hevc_640x360_1600kbps_30fps.hevc",
384 "bbb_hevc_640x360_1600kbps_30fps.info"},
385 {VideoDecHidlTest::standardComp::mpeg2,
386 "bbb_mpeg2_176x144_105kbps_25fps.m2v",
387 "bbb_mpeg2_176x144_105kbps_25fps.info"},
388 {VideoDecHidlTest::standardComp::h263,
389 "bbb_h263_352x288_300kbps_12fps.h263",
390 "bbb_h263_352x288_300kbps_12fps.info"},
391 {VideoDecHidlTest::standardComp::mpeg4,
392 "bbb_mpeg4_1280x720_1000kbps_25fps.m4v",
393 "bbb_mpeg4_1280x720_1000kbps_25fps.info"},
394 {VideoDecHidlTest::standardComp::vp8, "bbb_vp8_640x360_2mbps_30fps.vp8",
395 "bbb_vp8_640x360_2mbps_30fps.info"},
396 {VideoDecHidlTest::standardComp::vp9,
397 "bbb_vp9_640x360_1600kbps_30fps.vp9",
398 "bbb_vp9_640x360_1600kbps_30fps.info"},
401 for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
402 if (kCompToURL[i].comp == comp) {
403 strcat(mURL, kCompToURL[i].mURL);
404 strcat(info, kCompToURL[i].info);
410 void allocateGraphicBuffers(sp<IOmxNode> omxNode, OMX_U32 portIndex,
411 android::Vector<BufferInfo>* buffArray,
412 uint32_t nFrameWidth, uint32_t nFrameHeight,
413 int32_t* nStride, uint32_t count) {
414 android::hardware::media::omx::V1_0::Status status;
415 sp<android::hardware::graphics::allocator::V2_0::IAllocator> allocator =
416 android::hardware::graphics::allocator::V2_0::IAllocator::getService();
417 ASSERT_NE(nullptr, allocator.get());
419 sp<android::hardware::graphics::mapper::V2_0::IMapper> mapper =
420 android::hardware::graphics::mapper::V2_0::IMapper::getService();
421 ASSERT_NE(mapper.get(), nullptr);
423 android::hardware::graphics::mapper::V2_0::IMapper::BufferDescriptorInfo
427 descriptorInfo.width = nFrameWidth;
428 descriptorInfo.height = nFrameHeight;
429 descriptorInfo.layerCount = 1;
430 descriptorInfo.format = PixelFormat::RGBA_8888;
431 descriptorInfo.usage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN);
432 omxNode->getGraphicBufferUsage(
434 [&status, &usage](android::hardware::media::omx::V1_0::Status _s,
439 if (status == android::hardware::media::omx::V1_0::Status::OK) {
440 descriptorInfo.usage |= usage;
443 ::android::hardware::hidl_vec<uint32_t> descriptor;
444 android::hardware::graphics::mapper::V2_0::Error error;
445 mapper->createDescriptor(
446 descriptorInfo, [&error, &descriptor](
447 android::hardware::graphics::mapper::V2_0::Error _s,
448 ::android::hardware::hidl_vec<uint32_t> _n1) {
452 EXPECT_EQ(error, android::hardware::graphics::mapper::V2_0::Error::NONE);
454 EXPECT_EQ(buffArray->size(), count);
457 [&](android::hardware::graphics::mapper::V2_0::Error _s, uint32_t _n1,
458 const ::android::hardware::hidl_vec<
459 ::android::hardware::hidl_handle>& _n2) {
460 ASSERT_EQ(android::hardware::graphics::mapper::V2_0::Error::NONE,
463 ASSERT_EQ(count, _n2.size());
464 for (uint32_t i = 0; i < count; i++) {
465 buffArray->editItemAt(i).omxBuffer.nativeHandle = _n2[i];
466 buffArray->editItemAt(i).omxBuffer.attr.anwBuffer.width =
468 buffArray->editItemAt(i).omxBuffer.attr.anwBuffer.height =
470 buffArray->editItemAt(i).omxBuffer.attr.anwBuffer.stride = _n1;
471 buffArray->editItemAt(i).omxBuffer.attr.anwBuffer.format =
472 descriptorInfo.format;
473 buffArray->editItemAt(i).omxBuffer.attr.anwBuffer.usage =
474 descriptorInfo.usage;
475 buffArray->editItemAt(i).omxBuffer.attr.anwBuffer.layerCount =
476 descriptorInfo.layerCount;
477 buffArray->editItemAt(i).omxBuffer.attr.anwBuffer.id =
483 // port settings reconfiguration during runtime. reconfigures frame dimensions
484 void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
485 android::Vector<BufferInfo>* iBuffer,
486 android::Vector<BufferInfo>* oBuffer,
487 OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
488 Message msg, PortMode oPortMode, void* args) {
489 android::hardware::media::omx::V1_0::Status status;
492 if (msg.data.eventData.event == OMX_EventPortSettingsChanged) {
493 ASSERT_EQ(msg.data.eventData.data1, kPortIndexOutput);
494 if (msg.data.eventData.data2 == OMX_IndexParamPortDefinition ||
495 msg.data.eventData.data2 == 0) {
496 status = omxNode->sendCommand(
497 toRawCommandType(OMX_CommandPortDisable), kPortIndexOutput);
498 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
500 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer,
503 android::hardware::media::omx::V1_0::Status::TIMED_OUT) {
504 for (size_t i = 0; i < oBuffer->size(); ++i) {
505 // test if client got all its buffers back
506 EXPECT_EQ((*oBuffer)[i].owner, client);
509 omxNode->freeBuffer(kPortIndexOutput, (*oBuffer)[i].id);
511 android::hardware::media::omx::V1_0::Status::OK);
513 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
516 android::hardware::media::omx::V1_0::Status::OK);
517 ASSERT_EQ(msg.type, Message::Type::EVENT);
518 ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
519 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortDisable);
520 ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
523 uint32_t nFrameWidth, nFrameHeight, xFramerate;
524 OMX_COLOR_FORMATTYPE eColorFormat =
525 OMX_COLOR_FormatYUV420Planar;
526 getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth,
527 &nFrameHeight, &xFramerate);
528 setDefaultPortParam(omxNode, kPortIndexOutput,
529 OMX_VIDEO_CodingUnused, eColorFormat,
530 nFrameWidth, nFrameHeight, 0, xFramerate);
532 // If you can disable a port, then you should be able to
535 status = omxNode->sendCommand(
536 toRawCommandType(OMX_CommandPortEnable), kPortIndexOutput);
538 android::hardware::media::omx::V1_0::Status::OK);
540 // do not enable the port until all the buffers are supplied
541 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
545 android::hardware::media::omx::V1_0::Status::TIMED_OUT);
547 allocatePortBuffers(omxNode, oBuffer, kPortIndexOutput,
549 if (oPortMode != PortMode::PRESET_BYTE_BUFFER) {
550 OMX_PARAM_PORTDEFINITIONTYPE portDef;
552 status = getPortParam(omxNode, OMX_IndexParamPortDefinition,
553 kPortIndexOutput, &portDef);
556 ::android::hardware::media::omx::V1_0::Status::OK);
557 allocateGraphicBuffers(omxNode, kPortIndexOutput, oBuffer,
558 portDef.format.video.nFrameWidth,
559 portDef.format.video.nFrameHeight,
560 &portDef.format.video.nStride,
561 portDef.nBufferCountActual);
563 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
566 android::hardware::media::omx::V1_0::Status::OK);
567 ASSERT_EQ(msg.type, Message::Type::EVENT);
568 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortEnable);
569 ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
571 // dispatch output buffers
572 for (size_t i = 0; i < oBuffer->size(); i++) {
573 dispatchOutputBuffer(omxNode, oBuffer, i, oPortMode);
578 } else if (msg.data.eventData.data2 ==
579 OMX_IndexConfigCommonOutputCrop) {
580 std::cout << "[ ] Warning ! OMX_EventPortSettingsChanged/ "
581 "OMX_IndexConfigCommonOutputCrop not handled \n";
582 } else if (msg.data.eventData.data2 == OMX_IndexVendorStartUnused + 3) {
583 std::cout << "[ ] Warning ! OMX_EventPortSettingsChanged/ "
584 "kDescribeColorAspectsIndex not handled \n";
586 } else if (msg.data.eventData.event == OMX_EventError) {
587 std::cout << "[ ] Warning ! OMX_EventError/ "
588 "Decode Frame Call might be failed \n";
590 } else if (msg.data.eventData.event == OMX_EventBufferFlag) {
591 // soft omx components donot send this, we will just ignore it
594 // something unexpected happened
599 // blocking call to ensures application to Wait till all the inputs are consumed
600 void waitOnInputConsumption(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
601 android::Vector<BufferInfo>* iBuffer,
602 android::Vector<BufferInfo>* oBuffer,
603 OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
604 PortMode oPortMode) {
605 android::hardware::media::omx::V1_0::Status status;
607 int timeOut = TIMEOUT_COUNTER_Q;
612 observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
613 if (status == android::hardware::media::omx::V1_0::Status::OK) {
614 EXPECT_EQ(msg.type, Message::Type::EVENT);
615 portReconfiguration(omxNode, observer, iBuffer, oBuffer,
616 kPortIndexInput, kPortIndexOutput, msg,
619 // status == TIMED_OUT, it could be due to process time being large
620 // than DEFAULT_TIMEOUT or component needs output buffers to start
622 for (; i < iBuffer->size(); i++) {
623 if ((*iBuffer)[i].owner != client) break;
625 if (i == iBuffer->size()) break;
627 // Dispatch an output buffer assuming outQueue.empty() is true
629 if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
630 dispatchOutputBuffer(omxNode, oBuffer, index, oPortMode);
631 timeOut = TIMEOUT_COUNTER_Q;
637 void decodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
638 android::Vector<BufferInfo>* iBuffer,
639 android::Vector<BufferInfo>* oBuffer,
640 OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
641 std::ifstream& eleStream, android::Vector<FrameData>* Info,
642 int offset, int range, PortMode oPortMode,
643 bool signalEOS = true) {
644 android::hardware::media::omx::V1_0::Status status;
647 // dispatch output buffers
648 for (size_t i = 0; i < oBuffer->size(); i++) {
649 dispatchOutputBuffer(omxNode, oBuffer, i, oPortMode);
651 // dispatch input buffers
653 int frameID = offset;
654 for (size_t i = 0; (i < iBuffer->size()) && (frameID < (int)Info->size()) &&
655 (frameID < (offset + range));
657 char* ipBuffer = static_cast<char*>(
658 static_cast<void*>((*iBuffer)[i].mMemory->getPointer()));
659 ASSERT_LE((*Info)[frameID].bytesCount,
660 static_cast<int>((*iBuffer)[i].mMemory->getSize()));
661 eleStream.read(ipBuffer, (*Info)[frameID].bytesCount);
662 ASSERT_EQ(eleStream.gcount(), (*Info)[frameID].bytesCount);
663 flags = (*Info)[frameID].flags;
664 if (signalEOS && ((frameID == (int)Info->size() - 1) ||
665 (frameID == (offset + range - 1))))
666 flags |= OMX_BUFFERFLAG_EOS;
667 dispatchInputBuffer(omxNode, iBuffer, i, (*Info)[frameID].bytesCount,
668 flags, (*Info)[frameID].timestamp);
672 int timeOut = TIMEOUT_COUNTER_Q;
673 bool iQueued, oQueued;
675 iQueued = oQueued = false;
677 observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
679 // Port Reconfiguration
680 if (status == android::hardware::media::omx::V1_0::Status::OK &&
681 msg.type == Message::Type::EVENT) {
682 portReconfiguration(omxNode, observer, iBuffer, oBuffer,
683 kPortIndexInput, kPortIndexOutput, msg,
687 if (frameID == (int)Info->size() || frameID == (offset + range)) break;
689 // Dispatch input buffer
691 if ((index = getEmptyBufferID(iBuffer)) < iBuffer->size()) {
692 char* ipBuffer = static_cast<char*>(
693 static_cast<void*>((*iBuffer)[index].mMemory->getPointer()));
694 ASSERT_LE((*Info)[frameID].bytesCount,
695 static_cast<int>((*iBuffer)[index].mMemory->getSize()));
696 eleStream.read(ipBuffer, (*Info)[frameID].bytesCount);
697 ASSERT_EQ(eleStream.gcount(), (*Info)[frameID].bytesCount);
698 flags = (*Info)[frameID].flags;
699 if (signalEOS && ((frameID == (int)Info->size() - 1) ||
700 (frameID == (offset + range - 1))))
701 flags |= OMX_BUFFERFLAG_EOS;
702 dispatchInputBuffer(omxNode, iBuffer, index,
703 (*Info)[frameID].bytesCount, flags,
704 (*Info)[frameID].timestamp);
708 if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
709 dispatchOutputBuffer(omxNode, oBuffer, index, oPortMode);
712 if (iQueued || oQueued)
713 timeOut = TIMEOUT_COUNTER_Q;
717 EXPECT_TRUE(false) << "Wait on Input/Output is found indefinite";
723 // set component role
724 TEST_F(VideoDecHidlTest, SetRole) {
725 description("Test Set Component Role");
726 if (disableTest) return;
727 android::hardware::media::omx::V1_0::Status status;
728 status = setRole(omxNode, gEnv->getRole().c_str());
729 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
732 // port format enumeration
733 TEST_F(VideoDecHidlTest, EnumeratePortFormat) {
734 description("Test Component on Mandatory Port Parameters (Port Format)");
735 if (disableTest) return;
736 android::hardware::media::omx::V1_0::Status status;
737 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
738 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatYUV420Planar;
739 OMX_U32 xFramerate = (24U << 16);
740 status = setRole(omxNode, gEnv->getRole().c_str());
741 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
742 OMX_PORT_PARAM_TYPE params;
743 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
744 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
745 ASSERT_EQ(params.nPorts, 2U);
746 kPortIndexInput = params.nStartPortNumber;
747 kPortIndexOutput = kPortIndexInput + 1;
749 status = setVideoPortFormat(omxNode, kPortIndexInput, eCompressionFormat,
750 OMX_COLOR_FormatUnused, 0U);
751 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
753 setVideoPortFormat(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
754 eColorFormat, xFramerate);
755 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
758 // test port settings reconfiguration, elementary stream decode and timestamp
760 TEST_F(VideoDecHidlTest, DecodeTest) {
761 description("Tests Port Reconfiguration, Decode and timestamp deviation");
762 if (disableTest) return;
763 android::hardware::media::omx::V1_0::Status status;
764 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
765 status = setRole(omxNode, gEnv->getRole().c_str());
766 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
767 OMX_PORT_PARAM_TYPE params;
768 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
769 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
770 ASSERT_EQ(params.nPorts, 2U);
771 kPortIndexInput = params.nStartPortNumber;
772 kPortIndexOutput = kPortIndexInput + 1;
774 char mURL[512], info[512];
775 strcpy(mURL, gEnv->getRes().c_str());
776 strcpy(info, gEnv->getRes().c_str());
777 GetURLForComponent(compName, mURL, info);
779 std::ifstream eleStream, eleInfo;
782 ASSERT_EQ(eleInfo.is_open(), true);
783 android::Vector<FrameData> Info;
786 uint32_t timestamp = 0;
787 timestampDevTest = true;
789 if (!(eleInfo >> bytesCount)) break;
791 eleInfo >> timestamp;
792 Info.push_back({bytesCount, flags, timestamp});
793 if (flags != OMX_BUFFERFLAG_CODECCONFIG)
794 timestampUslist.push_back(timestamp);
799 portMode[0] = PortMode::PRESET_BYTE_BUFFER;
800 portMode[1] = PortMode::DYNAMIC_ANW_BUFFER;
801 status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
802 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
803 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
804 if (status != ::android::hardware::media::omx::V1_0::Status::OK) {
805 portMode[1] = PortMode::PRESET_BYTE_BUFFER;
806 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
807 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
811 uint32_t nFrameWidth, nFrameHeight, xFramerate;
812 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatYUV420Planar;
813 getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight,
815 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
816 eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
817 omxNode->prepareForAdaptivePlayback(kPortIndexOutput, false, 1920, 1080);
819 android::Vector<BufferInfo> iBuffer, oBuffer;
822 changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
823 kPortIndexInput, kPortIndexOutput, portMode);
824 // set state to executing
825 changeStateIdletoExecute(omxNode, observer);
827 if (portMode[1] != PortMode::PRESET_BYTE_BUFFER) {
828 OMX_PARAM_PORTDEFINITIONTYPE portDef;
830 status = getPortParam(omxNode, OMX_IndexParamPortDefinition,
831 kPortIndexOutput, &portDef);
832 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
833 allocateGraphicBuffers(
834 omxNode, kPortIndexOutput, &oBuffer,
835 portDef.format.video.nFrameWidth, portDef.format.video.nFrameHeight,
836 &portDef.format.video.nStride, portDef.nBufferCountActual);
839 // Port Reconfiguration
840 eleStream.open(mURL, std::ifstream::binary);
841 ASSERT_EQ(eleStream.is_open(), true);
842 decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
843 kPortIndexOutput, eleStream, &Info, 0, (int)Info.size(),
846 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
847 kPortIndexInput, kPortIndexOutput, portMode[1]);
848 testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, portMode,
849 portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr);
850 EXPECT_EQ(timestampUslist.empty(), true);
852 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
853 // set state to executing
854 changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
855 kPortIndexInput, kPortIndexOutput);
858 // end of sequence test
859 TEST_F(VideoDecHidlTest, EOSTest_M) {
860 description("Test End of stream monkeying");
861 if (disableTest) return;
862 android::hardware::media::omx::V1_0::Status status;
863 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
864 status = setRole(omxNode, gEnv->getRole().c_str());
865 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
866 OMX_PORT_PARAM_TYPE params;
867 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
868 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
869 ASSERT_EQ(params.nPorts, 2U);
870 kPortIndexInput = params.nStartPortNumber;
871 kPortIndexOutput = kPortIndexInput + 1;
875 uint32_t nFrameWidth, nFrameHeight, xFramerate;
876 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatYUV420Planar;
877 getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight,
879 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
880 eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
883 PortMode portMode[2];
884 portMode[0] = portMode[1] = PortMode::PRESET_BYTE_BUFFER;
885 status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
886 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
887 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
888 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
890 android::Vector<BufferInfo> iBuffer, oBuffer;
893 changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
894 kPortIndexInput, kPortIndexOutput, portMode);
895 // set state to executing
896 changeStateIdletoExecute(omxNode, observer);
898 // request EOS at the start
899 testEOS(omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, portMode,
900 portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr);
901 flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
903 EXPECT_GE(framesReceived, 0U);
908 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
909 // set state to executing
910 changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
911 kPortIndexInput, kPortIndexOutput);
914 // end of sequence test
915 TEST_F(VideoDecHidlTest, ThumbnailTest) {
916 description("Test Request for thumbnail");
917 if (disableTest) return;
918 android::hardware::media::omx::V1_0::Status status;
919 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
920 status = setRole(omxNode, gEnv->getRole().c_str());
921 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
922 OMX_PORT_PARAM_TYPE params;
923 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
924 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
925 ASSERT_EQ(params.nPorts, 2U);
926 kPortIndexInput = params.nStartPortNumber;
927 kPortIndexOutput = kPortIndexInput + 1;
929 char mURL[512], info[512];
930 strcpy(mURL, gEnv->getRes().c_str());
931 strcpy(info, gEnv->getRes().c_str());
932 GetURLForComponent(compName, mURL, info);
934 std::ifstream eleStream, eleInfo;
937 ASSERT_EQ(eleInfo.is_open(), true);
938 android::Vector<FrameData> Info;
941 uint32_t timestamp = 0;
943 if (!(eleInfo >> bytesCount)) break;
945 eleInfo >> timestamp;
946 Info.push_back({bytesCount, flags, timestamp});
951 uint32_t nFrameWidth, nFrameHeight, xFramerate;
952 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatYUV420Planar;
953 getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight,
955 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
956 eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
959 PortMode portMode[2];
960 portMode[0] = portMode[1] = PortMode::PRESET_BYTE_BUFFER;
961 status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
962 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
963 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
964 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
966 android::Vector<BufferInfo> iBuffer, oBuffer;
969 changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
970 kPortIndexInput, kPortIndexOutput, portMode);
971 // set state to executing
972 changeStateIdletoExecute(omxNode, observer);
974 // request EOS for thumbnail
976 while (!(Info[i].flags & OMX_BUFFERFLAG_SYNCFRAME)) i++;
977 eleStream.open(mURL, std::ifstream::binary);
978 ASSERT_EQ(eleStream.is_open(), true);
979 decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
980 kPortIndexOutput, eleStream, &Info, 0, i + 1, portMode[1]);
982 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
983 kPortIndexInput, kPortIndexOutput, portMode[1]);
984 testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, portMode,
985 portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr);
986 flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
988 EXPECT_GE(framesReceived, 1U);
992 eleStream.open(mURL, std::ifstream::binary);
993 ASSERT_EQ(eleStream.is_open(), true);
994 decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
995 kPortIndexOutput, eleStream, &Info, 0, i + 1, portMode[1],
998 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
999 kPortIndexInput, kPortIndexOutput, portMode[1]);
1000 testEOS(omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, portMode,
1001 portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr);
1002 flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1004 EXPECT_GE(framesReceived, 1U);
1008 // set state to idle
1009 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
1010 // set state to executing
1011 changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
1012 kPortIndexInput, kPortIndexOutput);
1015 // end of sequence test
1016 TEST_F(VideoDecHidlTest, SimpleEOSTest) {
1017 description("Test End of stream");
1018 if (disableTest) return;
1019 android::hardware::media::omx::V1_0::Status status;
1020 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1021 status = setRole(omxNode, gEnv->getRole().c_str());
1022 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1023 OMX_PORT_PARAM_TYPE params;
1024 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
1025 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1026 ASSERT_EQ(params.nPorts, 2U);
1027 kPortIndexInput = params.nStartPortNumber;
1028 kPortIndexOutput = kPortIndexInput + 1;
1030 char mURL[512], info[512];
1031 strcpy(mURL, gEnv->getRes().c_str());
1032 strcpy(info, gEnv->getRes().c_str());
1033 GetURLForComponent(compName, mURL, info);
1035 std::ifstream eleStream, eleInfo;
1038 ASSERT_EQ(eleInfo.is_open(), true);
1039 android::Vector<FrameData> Info;
1042 uint32_t timestamp = 0;
1044 if (!(eleInfo >> bytesCount)) break;
1046 eleInfo >> timestamp;
1047 Info.push_back({bytesCount, flags, timestamp});
1052 uint32_t nFrameWidth, nFrameHeight, xFramerate;
1053 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatYUV420Planar;
1054 getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight,
1056 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
1057 eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
1060 PortMode portMode[2];
1061 portMode[0] = portMode[1] = PortMode::PRESET_BYTE_BUFFER;
1062 status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
1063 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1064 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
1065 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1067 android::Vector<BufferInfo> iBuffer, oBuffer;
1069 // set state to idle
1070 changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
1071 kPortIndexInput, kPortIndexOutput, portMode);
1072 // set state to executing
1073 changeStateIdletoExecute(omxNode, observer);
1075 // request EOS at the end
1076 eleStream.open(mURL, std::ifstream::binary);
1077 ASSERT_EQ(eleStream.is_open(), true);
1078 decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1079 kPortIndexOutput, eleStream, &Info, 0, (int)Info.size(),
1080 portMode[1], false);
1082 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
1083 kPortIndexInput, kPortIndexOutput, portMode[1]);
1084 testEOS(omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, portMode,
1085 portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr);
1086 flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1091 // set state to idle
1092 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
1093 // set state to executing
1094 changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
1095 kPortIndexInput, kPortIndexOutput);
1098 // test input/output port flush
1099 TEST_F(VideoDecHidlTest, FlushTest) {
1100 description("Test Flush");
1101 if (disableTest) return;
1102 android::hardware::media::omx::V1_0::Status status;
1103 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1104 status = setRole(omxNode, gEnv->getRole().c_str());
1105 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1106 OMX_PORT_PARAM_TYPE params;
1107 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
1108 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1109 ASSERT_EQ(params.nPorts, 2U);
1110 kPortIndexInput = params.nStartPortNumber;
1111 kPortIndexOutput = kPortIndexInput + 1;
1113 char mURL[512], info[512];
1114 strcpy(mURL, gEnv->getRes().c_str());
1115 strcpy(info, gEnv->getRes().c_str());
1116 GetURLForComponent(compName, mURL, info);
1118 std::ifstream eleStream, eleInfo;
1121 ASSERT_EQ(eleInfo.is_open(), true);
1122 android::Vector<FrameData> Info;
1125 uint32_t timestamp = 0;
1127 if (!(eleInfo >> bytesCount)) break;
1129 eleInfo >> timestamp;
1130 Info.push_back({bytesCount, flags, timestamp});
1135 uint32_t nFrameWidth, nFrameHeight, xFramerate;
1136 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatYUV420Planar;
1137 getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight,
1139 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
1140 eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
1143 PortMode portMode[2];
1144 portMode[0] = portMode[1] = PortMode::PRESET_BYTE_BUFFER;
1145 status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
1146 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1147 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
1148 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1150 android::Vector<BufferInfo> iBuffer, oBuffer;
1152 // set state to idle
1153 changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
1154 kPortIndexInput, kPortIndexOutput, portMode);
1155 // set state to executing
1156 changeStateIdletoExecute(omxNode, observer);
1158 // Decode 128 frames and flush. here 128 is chosen to ensure there is a key
1159 // frame after this so that the below section can be convered for all
1162 eleStream.open(mURL, std::ifstream::binary);
1163 ASSERT_EQ(eleStream.is_open(), true);
1164 decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1165 kPortIndexOutput, eleStream, &Info, 0, nFrames, portMode[1],
1167 flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1171 // Seek to next key frame and start decoding till the end
1172 int index = nFrames;
1173 bool keyFrame = false;
1174 while (index < (int)Info.size()) {
1175 if ((Info[index].flags & OMX_BUFFERFLAG_SYNCFRAME) ==
1176 OMX_BUFFERFLAG_SYNCFRAME) {
1177 timestampUs = Info[index - 1].timestamp;
1181 eleStream.ignore(Info[index].bytesCount);
1185 decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1186 kPortIndexOutput, eleStream, &Info, index,
1187 Info.size() - index, portMode[1], false);
1189 flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1193 // set state to idle
1194 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
1195 // set state to executing
1196 changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
1197 kPortIndexInput, kPortIndexOutput);
1200 int main(int argc, char** argv) {
1201 gEnv = new ComponentTestEnvironment();
1202 ::testing::AddGlobalTestEnvironment(gEnv);
1203 ::testing::InitGoogleTest(&argc, argv);
1204 int status = gEnv->initFromOptions(argc, argv);
1206 status = RUN_ALL_TESTS();
1207 ALOGI("Test result = %d", status);