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"
19 #define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
22 #include <android-base/logging.h>
24 #include <android/hardware/media/omx/1.0/IOmx.h>
25 #include <android/hardware/media/omx/1.0/IOmxNode.h>
26 #include <android/hardware/media/omx/1.0/IOmxObserver.h>
27 #include <android/hardware/media/omx/1.0/types.h>
28 #include <android/hidl/allocator/1.0/IAllocator.h>
29 #include <android/hidl/memory/1.0/IMapper.h>
30 #include <android/hidl/memory/1.0/IMemory.h>
32 using ::android::hardware::media::omx::V1_0::IOmx;
33 using ::android::hardware::media::omx::V1_0::IOmxObserver;
34 using ::android::hardware::media::omx::V1_0::IOmxNode;
35 using ::android::hardware::media::omx::V1_0::Message;
36 using ::android::hardware::media::omx::V1_0::CodecBuffer;
37 using ::android::hardware::media::omx::V1_0::PortMode;
38 using ::android::hidl::allocator::V1_0::IAllocator;
39 using ::android::hidl::memory::V1_0::IMemory;
40 using ::android::hidl::memory::V1_0::IMapper;
41 using ::android::hardware::Return;
42 using ::android::hardware::Void;
43 using ::android::hardware::hidl_vec;
44 using ::android::hardware::hidl_string;
47 #include <VtsHalHidlTargetTestBase.h>
49 #include <media/hardware/HardwareAPI.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_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
170 ASSERT_NE(omxNode, nullptr);
171 ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
172 struct StringToName {
174 standardComp CompName;
176 const StringToName kStringToName[] = {
177 {"h263", h263}, {"avc", avc}, {"mpeg2", mpeg2}, {"mpeg4", mpeg4},
178 {"hevc", hevc}, {"vp8", vp8}, {"vp9", vp9},
180 const size_t kNumStringToName =
181 sizeof(kStringToName) / sizeof(kStringToName[0]);
183 char substring[OMX_MAX_STRINGNAME_SIZE];
184 strcpy(substring, gEnv->getRole().c_str());
185 pch = strchr(substring, '.');
186 ASSERT_NE(pch, nullptr);
187 compName = unknown_comp;
188 for (size_t i = 0; i < kNumStringToName; ++i) {
189 if (!strcasecmp(pch + 1, kStringToName[i].Name)) {
190 compName = kStringToName[i].CompName;
194 if (compName == unknown_comp) disableTest = true;
195 struct CompToCompression {
196 standardComp CompName;
197 OMX_VIDEO_CODINGTYPE eCompressionFormat;
199 static const CompToCompression kCompToCompression[] = {
200 {h263, OMX_VIDEO_CodingH263}, {avc, OMX_VIDEO_CodingAVC},
201 {mpeg2, OMX_VIDEO_CodingMPEG2}, {mpeg4, OMX_VIDEO_CodingMPEG4},
202 {hevc, OMX_VIDEO_CodingHEVC}, {vp8, OMX_VIDEO_CodingVP8},
203 {vp9, OMX_VIDEO_CodingVP9},
205 static const size_t kNumCompToCompression =
206 sizeof(kCompToCompression) / sizeof(kCompToCompression[0]);
208 for (i = 0; i < kNumCompToCompression; ++i) {
209 if (kCompToCompression[i].CompName == compName) {
210 eCompressionFormat = kCompToCompression[i].eCompressionFormat;
214 if (i == kNumCompToCompression) disableTest = true;
215 portMode[0] = portMode[1] = PortMode::PRESET_BYTE_BUFFER;
219 timestampDevTest = false;
221 portSettingsChange = false;
222 size_t suffixLen = strlen(".secure");
223 if (strlen(gEnv->getComponent().c_str()) >= suffixLen) {
225 !strcmp(gEnv->getComponent().c_str() +
226 strlen(gEnv->getComponent().c_str()) - suffixLen,
229 if (isSecure) disableTest = true;
230 if (disableTest) std::cout << "[ WARN ] Test Disabled \n";
233 virtual void TearDown() override {
234 if (omxNode != nullptr) {
235 // If you have encountered a fatal failure, it is possible that
236 // freeNode() will not go through. Instead of hanging the app.
237 // let it pass through and report errors
238 if (::testing::Test::HasFatalFailure()) return;
239 EXPECT_TRUE((omxNode->freeNode()).isOk());
245 // callback function to process messages received by onMessages() from IL
247 void handleMessage(Message msg, const BufferInfo* buffer) {
249 if (msg.type == Message::Type::FILL_BUFFER_DONE) {
250 if (msg.data.extendedBufferData.flags & OMX_BUFFERFLAG_EOS) {
253 if (msg.data.extendedBufferData.rangeLength != 0) {
255 // For decoder components current timestamp always exceeds
256 // previous timestamp
257 EXPECT_GE(msg.data.extendedBufferData.timestampUs, timestampUs);
258 timestampUs = msg.data.extendedBufferData.timestampUs;
259 // Test if current timestamp is among the list of queued
261 if (timestampDevTest) {
263 android::List<uint64_t>::iterator it =
264 timestampUslist.begin();
265 while (it != timestampUslist.end()) {
266 if (*it == timestampUs) {
267 timestampUslist.erase(it);
273 if (tsHit == false) {
274 if (timestampUslist.empty() == false) {
275 EXPECT_EQ(tsHit, true)
276 << "TimeStamp not recognized";
278 std::cout << "[ INFO ] Received non-zero "
279 "output / TimeStamp not recognized \n";
283 #define WRITE_OUTPUT 0
285 static int count = 0;
288 ofp = fopen("out.bin", "ab");
290 ofp = fopen("out.bin", "wb");
291 if (ofp != nullptr &&
292 portMode[1] == PortMode::PRESET_BYTE_BUFFER) {
293 fwrite(static_cast<void*>(buffer->mMemory->getPointer()),
295 msg.data.extendedBufferData.rangeLength, ofp);
301 } else if (msg.type == Message::Type::EVENT) {
302 if (msg.data.eventData.event == OMX_EventPortSettingsChanged) {
303 if ((msg.data.eventData.data2 == OMX_IndexParamPortDefinition ||
304 msg.data.eventData.data2 == 0)) {
305 portSettingsChange = true;
323 sp<CodecObserver> observer;
324 sp<IOmxNode> omxNode;
325 standardComp compName;
326 OMX_VIDEO_CODINGTYPE eCompressionFormat;
328 PortMode portMode[2];
330 uint32_t framesReceived;
331 uint64_t timestampUs;
332 ::android::List<uint64_t> timestampUslist;
333 bool timestampDevTest;
335 bool portSettingsChange;
338 static void description(const std::string& description) {
339 RecordProperty("description", description);
343 // Set Default port param.
344 void setDefaultPortParam(sp<IOmxNode> omxNode, OMX_U32 portIndex,
345 OMX_VIDEO_CODINGTYPE eCompressionFormat,
346 OMX_COLOR_FORMATTYPE eColorFormat,
347 OMX_U32 nFrameWidth = 352, OMX_U32 nFrameHeight = 288,
348 OMX_U32 nBitrate = 0,
349 OMX_U32 xFramerate = (24U << 16)) {
350 switch ((int)eCompressionFormat) {
351 case OMX_VIDEO_CodingUnused:
352 setupRAWPort(omxNode, portIndex, nFrameWidth, nFrameHeight,
353 nBitrate, xFramerate, eColorFormat);
360 // In decoder components, often the input port parameters get updated upon
361 // parsing the header of elementary stream. Client needs to collect this
362 // information to reconfigure other ports that share data with this input
364 void getInputChannelInfo(sp<IOmxNode> omxNode, OMX_U32 kPortIndexInput,
365 uint32_t* nFrameWidth, uint32_t* nFrameHeight,
366 uint32_t* xFramerate) {
367 android::hardware::media::omx::V1_0::Status status;
370 *xFramerate = (24U << 16);
372 OMX_PARAM_PORTDEFINITIONTYPE portDef;
373 status = getPortParam(omxNode, OMX_IndexParamPortDefinition,
374 kPortIndexInput, &portDef);
375 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
376 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
377 *nFrameWidth = portDef.format.video.nFrameWidth;
378 *nFrameHeight = portDef.format.video.nFrameHeight;
379 *xFramerate = portDef.format.video.xFramerate;
383 // number of elementary streams per component
384 #define STREAM_COUNT 2
385 // LookUpTable of clips and metadata for component testing
386 void GetURLForComponent(VideoDecHidlTest::standardComp comp, char* mURL,
387 char* info, size_t streamIndex = 1) {
389 VideoDecHidlTest::standardComp comp;
390 const char mURL[STREAM_COUNT][512];
391 const char info[STREAM_COUNT][512];
393 ASSERT_TRUE(streamIndex < STREAM_COUNT);
395 static const CompToURL kCompToURL[] = {
396 {VideoDecHidlTest::standardComp::avc,
397 {"bbb_avc_176x144_300kbps_60fps.h264",
398 "bbb_avc_1920x1080_5000kbps_30fps.h264"},
399 {"bbb_avc_176x144_300kbps_60fps.info",
400 "bbb_avc_1920x1080_5000kbps_30fps.info"}},
401 {VideoDecHidlTest::standardComp::hevc,
402 {"bbb_hevc_176x144_176kbps_60fps.hevc",
403 "bbb_hevc_640x360_1600kbps_30fps.hevc"},
404 {"bbb_hevc_176x144_176kbps_60fps.info",
405 "bbb_hevc_640x360_1600kbps_30fps.info"}},
406 {VideoDecHidlTest::standardComp::mpeg2,
407 {"bbb_mpeg2_176x144_105kbps_25fps.m2v",
408 "bbb_mpeg2_352x288_1mbps_60fps.m2v"},
409 {"bbb_mpeg2_176x144_105kbps_25fps.info",
410 "bbb_mpeg2_352x288_1mbps_60fps.info"}},
411 {VideoDecHidlTest::standardComp::h263,
412 {"", "bbb_h263_352x288_300kbps_12fps.h263"},
413 {"", "bbb_h263_352x288_300kbps_12fps.info"}},
414 {VideoDecHidlTest::standardComp::mpeg4,
415 {"", "bbb_mpeg4_1280x720_1000kbps_25fps.m4v"},
416 {"", "bbb_mpeg4_1280x720_1000kbps_25fps.info"}},
417 {VideoDecHidlTest::standardComp::vp8,
418 {"bbb_vp8_176x144_240kbps_60fps.vp8",
419 "bbb_vp8_640x360_2mbps_30fps.vp8"},
420 {"bbb_vp8_176x144_240kbps_60fps.info",
421 "bbb_vp8_640x360_2mbps_30fps.info"}},
422 {VideoDecHidlTest::standardComp::vp9,
423 {"bbb_vp9_176x144_285kbps_60fps.vp9",
424 "bbb_vp9_640x360_1600kbps_30fps.vp9"},
425 {"bbb_vp9_176x144_285kbps_60fps.info",
426 "bbb_vp9_640x360_1600kbps_30fps.info"}},
429 for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
430 if (kCompToURL[i].comp == comp) {
431 strcat(mURL, kCompToURL[i].mURL[streamIndex]);
432 strcat(info, kCompToURL[i].info[streamIndex]);
438 // port settings reconfiguration during runtime. reconfigures frame dimensions
439 void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
440 android::Vector<BufferInfo>* iBuffer,
441 android::Vector<BufferInfo>* oBuffer,
442 OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
443 Message msg, PortMode oPortMode, void* args) {
444 android::hardware::media::omx::V1_0::Status status;
447 if (msg.data.eventData.event == OMX_EventPortSettingsChanged) {
448 ASSERT_EQ(msg.data.eventData.data1, kPortIndexOutput);
449 if (msg.data.eventData.data2 == OMX_IndexParamPortDefinition ||
450 msg.data.eventData.data2 == 0) {
451 // Components can send various kinds of port settings changed events
452 // all at once. Before committing to a full port reconfiguration,
453 // defer any events waiting in the queue to be addressed to a later
455 android::List<Message> msgQueueDefer;
457 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
460 android::hardware::media::omx::V1_0::Status::TIMED_OUT) {
461 msgQueueDefer.push_back(msg);
466 status = omxNode->sendCommand(
467 toRawCommandType(OMX_CommandPortDisable), kPortIndexOutput);
468 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
470 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer,
473 android::hardware::media::omx::V1_0::Status::TIMED_OUT) {
474 for (size_t i = 0; i < oBuffer->size(); ++i) {
475 // test if client got all its buffers back
476 EXPECT_EQ((*oBuffer)[i].owner, client);
479 omxNode->freeBuffer(kPortIndexOutput, (*oBuffer)[i].id);
481 android::hardware::media::omx::V1_0::Status::OK);
483 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
486 android::hardware::media::omx::V1_0::Status::OK);
487 ASSERT_EQ(msg.type, Message::Type::EVENT);
488 ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
489 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortDisable);
490 ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
493 uint32_t nFrameWidth, nFrameHeight, xFramerate;
494 getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth,
495 &nFrameHeight, &xFramerate);
496 // get configured color format
497 OMX_PARAM_PORTDEFINITIONTYPE portDef;
498 status = getPortParam(omxNode, OMX_IndexParamPortDefinition,
499 kPortIndexOutput, &portDef);
500 setDefaultPortParam(omxNode, kPortIndexOutput,
501 OMX_VIDEO_CodingUnused,
502 portDef.format.video.eColorFormat,
503 nFrameWidth, nFrameHeight, 0, xFramerate);
505 // If you can disable a port, then you should be able to
507 status = omxNode->sendCommand(
508 toRawCommandType(OMX_CommandPortEnable), kPortIndexOutput);
510 android::hardware::media::omx::V1_0::Status::OK);
512 // do not enable the port until all the buffers are supplied
513 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
517 android::hardware::media::omx::V1_0::Status::TIMED_OUT);
519 ASSERT_NO_FATAL_FAILURE(allocatePortBuffers(
520 omxNode, oBuffer, kPortIndexOutput, oPortMode, true));
521 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
524 android::hardware::media::omx::V1_0::Status::OK);
525 ASSERT_EQ(msg.type, Message::Type::EVENT);
526 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortEnable);
527 ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
529 // Push back deferred messages to the list
530 android::List<Message>::iterator it = msgQueueDefer.begin();
531 while (it != msgQueueDefer.end()) {
532 status = omxNode->dispatchMessage(*it);
535 ::android::hardware::media::omx::V1_0::Status::OK);
539 // dispatch output buffers
540 for (size_t i = 0; i < oBuffer->size(); i++) {
541 ASSERT_NO_FATAL_FAILURE(
542 dispatchOutputBuffer(omxNode, oBuffer, i, oPortMode));
547 } else if (msg.data.eventData.data2 ==
548 OMX_IndexConfigCommonOutputCrop) {
549 std::cout << "[ INFO ] OMX_EventPortSettingsChanged/ "
550 "OMX_IndexConfigCommonOutputCrop not handled \n";
551 } else if (msg.data.eventData.data2 == OMX_IndexVendorStartUnused + 3) {
552 std::cout << "[ INFO ] OMX_EventPortSettingsChanged/ "
553 "kDescribeColorAspectsIndex not handled \n";
555 } else if (msg.data.eventData.event == OMX_EventError) {
556 std::cerr << "[ ERROR ] OMX_EventError/ "
557 "Decode Frame Call might be failed \n";
560 // something unexpected happened
565 // blocking call to ensures application to Wait till all the inputs are consumed
566 void waitOnInputConsumption(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
567 android::Vector<BufferInfo>* iBuffer,
568 android::Vector<BufferInfo>* oBuffer,
569 OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
570 PortMode oPortMode) {
571 android::hardware::media::omx::V1_0::Status status;
573 int timeOut = TIMEOUT_COUNTER_Q;
578 observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
579 if (status == android::hardware::media::omx::V1_0::Status::OK) {
580 ASSERT_EQ(msg.type, Message::Type::EVENT);
581 ASSERT_NO_FATAL_FAILURE(portReconfiguration(
582 omxNode, observer, iBuffer, oBuffer, kPortIndexInput,
583 kPortIndexOutput, msg, oPortMode, nullptr));
585 // status == TIMED_OUT, it could be due to process time being large
586 // than DEFAULT_TIMEOUT or component needs output buffers to start
588 for (; i < iBuffer->size(); i++) {
589 if ((*iBuffer)[i].owner != client) break;
591 if (i == iBuffer->size()) break;
593 // Dispatch an output buffer assuming outQueue.empty() is true
595 if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
596 ASSERT_NO_FATAL_FAILURE(
597 dispatchOutputBuffer(omxNode, oBuffer, index, oPortMode));
598 timeOut = TIMEOUT_COUNTER_Q;
604 void decodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
605 android::Vector<BufferInfo>* iBuffer,
606 android::Vector<BufferInfo>* oBuffer,
607 OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
608 std::ifstream& eleStream, android::Vector<FrameData>* Info,
609 int offset, int range, PortMode oPortMode,
610 bool signalEOS = true) {
611 android::hardware::media::omx::V1_0::Status status;
615 int frameID = offset;
616 int timeOut = TIMEOUT_COUNTER_Q;
617 bool iQueued, oQueued;
620 iQueued = oQueued = false;
622 observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
623 // Port Reconfiguration
624 if (status == android::hardware::media::omx::V1_0::Status::OK &&
625 msg.type == Message::Type::EVENT) {
626 ASSERT_NO_FATAL_FAILURE(portReconfiguration(
627 omxNode, observer, iBuffer, oBuffer, kPortIndexInput,
628 kPortIndexOutput, msg, oPortMode, nullptr));
631 if (frameID == (int)Info->size() || frameID == (offset + range)) break;
633 // Dispatch input buffer
634 if ((index = getEmptyBufferID(iBuffer)) < iBuffer->size()) {
635 char* ipBuffer = static_cast<char*>(
636 static_cast<void*>((*iBuffer)[index].mMemory->getPointer()));
637 ASSERT_LE((*Info)[frameID].bytesCount,
638 static_cast<int>((*iBuffer)[index].mMemory->getSize()));
639 eleStream.read(ipBuffer, (*Info)[frameID].bytesCount);
640 ASSERT_EQ(eleStream.gcount(), (*Info)[frameID].bytesCount);
641 flags = (*Info)[frameID].flags;
642 // Indicate to omx core that the buffer contains a full frame worth
644 flags |= OMX_BUFFERFLAG_ENDOFFRAME;
645 // Indicate the omx core that this is the last buffer it needs to
647 if (signalEOS && ((frameID == (int)Info->size() - 1) ||
648 (frameID == (offset + range - 1))))
649 flags |= OMX_BUFFERFLAG_EOS;
650 ASSERT_NO_FATAL_FAILURE(dispatchInputBuffer(
651 omxNode, iBuffer, index, (*Info)[frameID].bytesCount, flags,
652 (*Info)[frameID].timestamp));
656 // Dispatch output buffer
657 if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
658 ASSERT_NO_FATAL_FAILURE(
659 dispatchOutputBuffer(omxNode, oBuffer, index, oPortMode));
662 // Reset Counters when either input or output buffer is dispatched
663 if (iQueued || oQueued)
664 timeOut = TIMEOUT_COUNTER_Q;
668 ASSERT_TRUE(false) << "Wait on Input/Output is found indefinite";
673 // DescribeColorFormatParams Copy Constructor (Borrowed from OMXUtils.cpp)
674 android::DescribeColorFormatParams::DescribeColorFormatParams(
675 const android::DescribeColorFormat2Params& params) {
676 eColorFormat = params.eColorFormat;
677 nFrameWidth = params.nFrameWidth;
678 nFrameHeight = params.nFrameHeight;
679 nStride = params.nStride;
680 nSliceHeight = params.nSliceHeight;
681 bUsingNativeBuffers = params.bUsingNativeBuffers;
684 bool isColorFormatFlexibleYUV(sp<IOmxNode> omxNode,
685 OMX_COLOR_FORMATTYPE eColorFormat) {
686 android::hardware::media::omx::V1_0::Status status;
687 unsigned int index = OMX_IndexMax, index2 = OMX_IndexMax;
688 omxNode->getExtensionIndex(
689 "OMX.google.android.index.describeColorFormat",
690 [&index](android::hardware::media::omx::V1_0::Status _s,
692 if (_s == ::android::hardware::media::omx::V1_0::Status::OK)
695 omxNode->getExtensionIndex(
696 "OMX.google.android.index.describeColorFormat2",
697 [&index2](android::hardware::media::omx::V1_0::Status _s,
699 if (_s == ::android::hardware::media::omx::V1_0::Status::OK)
703 android::DescribeColorFormat2Params describeParams;
704 describeParams.eColorFormat = eColorFormat;
705 describeParams.nFrameWidth = 128;
706 describeParams.nFrameHeight = 128;
707 describeParams.nStride = 128;
708 describeParams.nSliceHeight = 128;
709 describeParams.bUsingNativeBuffers = OMX_FALSE;
710 if (index != OMX_IndexMax) {
711 android::DescribeColorFormatParams describeParamsV1(describeParams);
712 status = getParam(omxNode, static_cast<OMX_INDEXTYPE>(index),
714 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
715 android::MediaImage& img = describeParamsV1.sMediaImage;
716 if (img.mType == android::MediaImage::MEDIA_IMAGE_TYPE_YUV) {
717 if (img.mNumPlanes == 3 &&
718 img.mPlane[img.Y].mHorizSubsampling == 1 &&
719 img.mPlane[img.Y].mVertSubsampling == 1) {
720 if (img.mPlane[img.U].mHorizSubsampling == 2 &&
721 img.mPlane[img.U].mVertSubsampling == 2 &&
722 img.mPlane[img.V].mHorizSubsampling == 2 &&
723 img.mPlane[img.V].mVertSubsampling == 2) {
724 if (img.mBitDepth <= 8) {
731 } else if (index2 != OMX_IndexMax) {
732 status = getParam(omxNode, static_cast<OMX_INDEXTYPE>(index2),
734 android::MediaImage2& img = describeParams.sMediaImage;
735 if (img.mType == android::MediaImage2::MEDIA_IMAGE_TYPE_YUV) {
736 if (img.mNumPlanes == 3 &&
737 img.mPlane[img.Y].mHorizSubsampling == 1 &&
738 img.mPlane[img.Y].mVertSubsampling == 1) {
739 if (img.mPlane[img.U].mHorizSubsampling == 2 &&
740 img.mPlane[img.U].mVertSubsampling == 2 &&
741 img.mPlane[img.V].mHorizSubsampling == 2 &&
742 img.mPlane[img.V].mVertSubsampling == 2) {
743 if (img.mBitDepth <= 8) {
753 // get default color format for output port
754 void getDefaultColorFormat(sp<IOmxNode> omxNode, OMX_U32 kPortIndexOutput,
756 OMX_COLOR_FORMATTYPE* eColorFormat) {
757 android::hardware::media::omx::V1_0::Status status;
758 OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
759 *eColorFormat = OMX_COLOR_FormatUnused;
760 portFormat.nIndex = 0;
761 while (portFormat.nIndex < 512) {
762 status = getPortParam(omxNode, OMX_IndexParamVideoPortFormat,
763 kPortIndexOutput, &portFormat);
764 if (status != ::android::hardware::media::omx::V1_0::Status::OK) break;
765 EXPECT_EQ(portFormat.eCompressionFormat, OMX_VIDEO_CodingUnused);
766 if (oPortMode != PortMode::PRESET_BYTE_BUFFER) {
767 *eColorFormat = portFormat.eColorFormat;
770 if (isColorFormatFlexibleYUV(omxNode, portFormat.eColorFormat)) {
771 *eColorFormat = portFormat.eColorFormat;
774 if (OMX_COLOR_FormatYUV420SemiPlanar == portFormat.eColorFormat ||
775 OMX_COLOR_FormatYUV420Planar == portFormat.eColorFormat ||
776 OMX_COLOR_FormatYUV420PackedPlanar == portFormat.eColorFormat ||
777 OMX_COLOR_FormatYUV420PackedSemiPlanar == portFormat.eColorFormat) {
778 *eColorFormat = portFormat.eColorFormat;
785 // set component role
786 TEST_F(VideoDecHidlTest, SetRole) {
787 description("Test Set Component Role");
788 if (disableTest) return;
789 android::hardware::media::omx::V1_0::Status status;
790 status = setRole(omxNode, gEnv->getRole().c_str());
791 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
794 // port format enumeration
795 TEST_F(VideoDecHidlTest, EnumeratePortFormat) {
796 description("Test Component on Mandatory Port Parameters (Port Format)");
797 if (disableTest) return;
798 android::hardware::media::omx::V1_0::Status status;
799 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
800 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatYUV420Planar;
801 OMX_U32 xFramerate = (24U << 16);
802 status = setRole(omxNode, gEnv->getRole().c_str());
803 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
804 OMX_PORT_PARAM_TYPE params;
805 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
806 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
807 ASSERT_EQ(params.nPorts, 2U);
808 kPortIndexInput = params.nStartPortNumber;
809 kPortIndexOutput = kPortIndexInput + 1;
811 status = setVideoPortFormat(omxNode, kPortIndexInput, eCompressionFormat,
812 OMX_COLOR_FormatUnused, 0U);
813 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
815 setVideoPortFormat(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
816 eColorFormat, xFramerate);
817 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
820 // test port settings reconfiguration, elementary stream decode and timestamp
822 TEST_F(VideoDecHidlTest, DecodeTest) {
823 description("Tests Port Reconfiguration, Decode and timestamp deviation");
824 if (disableTest) return;
825 android::hardware::media::omx::V1_0::Status status;
826 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
827 status = setRole(omxNode, gEnv->getRole().c_str());
828 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
829 OMX_PORT_PARAM_TYPE params;
830 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
831 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
832 ASSERT_EQ(params.nPorts, 2U);
833 kPortIndexInput = params.nStartPortNumber;
834 kPortIndexOutput = kPortIndexInput + 1;
836 char mURL[512], info[512];
837 strcpy(mURL, gEnv->getRes().c_str());
838 strcpy(info, gEnv->getRes().c_str());
839 GetURLForComponent(compName, mURL, info);
841 std::ifstream eleStream, eleInfo;
844 ASSERT_EQ(eleInfo.is_open(), true);
845 android::Vector<FrameData> Info;
846 int bytesCount = 0, maxBytesCount = 0;
848 uint32_t timestamp = 0;
849 timestampDevTest = true;
851 if (!(eleInfo >> bytesCount)) break;
853 eleInfo >> timestamp;
854 Info.push_back({bytesCount, flags, timestamp});
855 if (timestampDevTest && (flags != OMX_BUFFERFLAG_CODECCONFIG))
856 timestampUslist.push_back(timestamp);
857 if (maxBytesCount < bytesCount) maxBytesCount = bytesCount;
861 // As the frame sizes are known ahead, use it to configure i/p buffer size
862 maxBytesCount = ALIGN_POWER_OF_TWO(maxBytesCount, 10);
863 status = setPortBufferSize(omxNode, kPortIndexInput, maxBytesCount);
864 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
867 portMode[0] = PortMode::PRESET_BYTE_BUFFER;
868 portMode[1] = PortMode::DYNAMIC_ANW_BUFFER;
869 status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
870 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
871 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
872 if (status != ::android::hardware::media::omx::V1_0::Status::OK) {
873 portMode[1] = PortMode::PRESET_BYTE_BUFFER;
874 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
875 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
879 uint32_t nFrameWidth, nFrameHeight, xFramerate;
880 getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight,
882 // get default color format
883 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused;
884 getDefaultColorFormat(omxNode, kPortIndexOutput, portMode[1],
886 ASSERT_NE(eColorFormat, OMX_COLOR_FormatUnused);
888 setVideoPortFormat(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
889 eColorFormat, xFramerate);
890 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
891 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
892 eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
894 android::Vector<BufferInfo> iBuffer, oBuffer;
897 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(
898 omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
899 kPortIndexOutput, portMode, true));
900 // set state to executing
901 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
903 // Port Reconfiguration
904 eleStream.open(mURL, std::ifstream::binary);
905 ASSERT_EQ(eleStream.is_open(), true);
906 ASSERT_NO_FATAL_FAILURE(decodeNFrames(
907 omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
908 kPortIndexOutput, eleStream, &Info, 0, (int)Info.size(), portMode[1]));
910 ASSERT_NO_FATAL_FAILURE(
911 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
912 kPortIndexInput, kPortIndexOutput, portMode[1]));
913 ASSERT_NO_FATAL_FAILURE(testEOS(
914 omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, portMode,
915 portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr));
916 if (timestampDevTest) EXPECT_EQ(timestampUslist.empty(), true);
918 ASSERT_NO_FATAL_FAILURE(
919 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
920 // set state to executing
921 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
922 &oBuffer, kPortIndexInput,
926 // Test for adaptive playback support
927 TEST_F(VideoDecHidlTest, AdaptivePlaybackTest) {
928 description("Tests for Adaptive Playback support");
929 if (disableTest) return;
930 if (!(compName == avc || compName == hevc || compName == vp8 ||
931 compName == vp9 || compName == mpeg2))
933 android::hardware::media::omx::V1_0::Status status;
934 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
935 status = setRole(omxNode, gEnv->getRole().c_str());
936 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
937 OMX_PORT_PARAM_TYPE params;
938 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
939 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
940 ASSERT_EQ(params.nPorts, 2U);
941 kPortIndexInput = params.nStartPortNumber;
942 kPortIndexOutput = kPortIndexInput + 1;
946 portMode[0] = PortMode::PRESET_BYTE_BUFFER;
947 portMode[1] = PortMode::DYNAMIC_ANW_BUFFER;
948 status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
949 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
950 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
951 if (status != ::android::hardware::media::omx::V1_0::Status::OK) {
952 portMode[1] = PortMode::PRESET_BYTE_BUFFER;
953 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
954 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
957 // prepare for adaptive playback
958 uint32_t adaptiveMaxWidth = 320;
959 uint32_t adaptiveMaxHeight = 240;
960 status = omxNode->prepareForAdaptivePlayback(
961 kPortIndexOutput, true, adaptiveMaxWidth, adaptiveMaxHeight);
962 if (strncmp(gEnv->getComponent().c_str(), "OMX.google.", 11) == 0) {
963 // SoftOMX Decoders donot support graphic buffer modes. So for them
964 // support for adaptive play back is mandatory in Byte Buffer mode
965 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
967 // for vendor codecs, support for adaptive play back is optional
968 // in byte buffer mode.
969 if (portMode[1] == PortMode::PRESET_BYTE_BUFFER) return;
970 if (status != ::android::hardware::media::omx::V1_0::Status::OK) return;
973 // TODO: Handle this better !!!
974 // Without the knowledge of the maximum resolution of the frame to be
975 // decoded it is not possible to choose the size of the input buffer.
976 // The value below is based on the info. files of clips in res folder.
977 status = setPortBufferSize(omxNode, kPortIndexInput, 482304);
978 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
981 uint32_t nFrameWidth, nFrameHeight, xFramerate;
982 getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight,
984 // get default color format
985 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused;
986 getDefaultColorFormat(omxNode, kPortIndexOutput, portMode[1],
988 ASSERT_NE(eColorFormat, OMX_COLOR_FormatUnused);
990 setVideoPortFormat(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
991 eColorFormat, xFramerate);
992 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
993 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
994 eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
996 android::Vector<BufferInfo> iBuffer, oBuffer;
999 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(
1000 omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1001 kPortIndexOutput, portMode, true));
1002 // set state to executing
1003 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
1005 timestampDevTest = true;
1006 uint32_t timestampOffset = 0;
1007 for (uint32_t i = 0; i < STREAM_COUNT * 2; i++) {
1008 std::ifstream eleStream, eleInfo;
1009 char mURL[512], info[512];
1010 android::Vector<FrameData> Info;
1011 strcpy(mURL, gEnv->getRes().c_str());
1012 strcpy(info, gEnv->getRes().c_str());
1013 GetURLForComponent(compName, mURL, info, i % STREAM_COUNT);
1015 ASSERT_EQ(eleInfo.is_open(), true);
1018 uint32_t timestamp = 0;
1019 uint32_t timestampMax = 0;
1021 if (!(eleInfo >> bytesCount)) break;
1023 eleInfo >> timestamp;
1024 timestamp += timestampOffset;
1025 Info.push_back({bytesCount, flags, timestamp});
1026 if (timestampDevTest && (flags != OMX_BUFFERFLAG_CODECCONFIG))
1027 timestampUslist.push_back(timestamp);
1028 if (timestampMax < timestamp) timestampMax = timestamp;
1030 timestampOffset = timestampMax;
1033 // Port Reconfiguration
1034 eleStream.open(mURL, std::ifstream::binary);
1035 ASSERT_EQ(eleStream.is_open(), true);
1036 ASSERT_NO_FATAL_FAILURE(
1037 decodeNFrames(omxNode, observer, &iBuffer, &oBuffer,
1038 kPortIndexInput, kPortIndexOutput, eleStream, &Info,
1039 0, (int)Info.size(), portMode[1], false));
1042 getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth,
1043 &nFrameHeight, &xFramerate);
1044 if ((nFrameWidth > adaptiveMaxWidth) ||
1045 (nFrameHeight > adaptiveMaxHeight)) {
1046 if (nFrameWidth > adaptiveMaxWidth) adaptiveMaxWidth = nFrameWidth;
1047 if (nFrameHeight > adaptiveMaxHeight)
1048 adaptiveMaxHeight = nFrameHeight;
1049 EXPECT_TRUE(portSettingsChange);
1051 // In DynamicANW Buffer mode, its ok to do a complete
1052 // reconfiguration even if a partial reconfiguration is sufficient.
1053 if (portMode[1] != PortMode::DYNAMIC_ANW_BUFFER)
1054 EXPECT_FALSE(portSettingsChange);
1056 portSettingsChange = false;
1058 ASSERT_NO_FATAL_FAILURE(
1059 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
1060 kPortIndexInput, kPortIndexOutput, portMode[1]));
1061 ASSERT_NO_FATAL_FAILURE(testEOS(
1062 omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, portMode,
1063 portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr));
1064 if (timestampDevTest) EXPECT_EQ(timestampUslist.empty(), true);
1065 // set state to idle
1066 ASSERT_NO_FATAL_FAILURE(
1067 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
1068 // set state to executing
1069 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
1070 &oBuffer, kPortIndexInput,
1074 // end of sequence test
1075 TEST_F(VideoDecHidlTest, EOSTest_M) {
1076 description("Test End of stream monkeying");
1077 if (disableTest) return;
1078 android::hardware::media::omx::V1_0::Status status;
1079 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1080 status = setRole(omxNode, gEnv->getRole().c_str());
1081 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1082 OMX_PORT_PARAM_TYPE params;
1083 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
1084 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1085 ASSERT_EQ(params.nPorts, 2U);
1086 kPortIndexInput = params.nStartPortNumber;
1087 kPortIndexOutput = kPortIndexInput + 1;
1091 status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
1092 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1093 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
1094 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1097 uint32_t nFrameWidth, nFrameHeight, xFramerate;
1098 getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight,
1100 // get default color format
1101 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused;
1102 getDefaultColorFormat(omxNode, kPortIndexOutput, portMode[1],
1104 ASSERT_NE(eColorFormat, OMX_COLOR_FormatUnused);
1106 setVideoPortFormat(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
1107 eColorFormat, xFramerate);
1108 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1109 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
1110 eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
1112 android::Vector<BufferInfo> iBuffer, oBuffer;
1114 // set state to idle
1115 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(
1116 omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1117 kPortIndexOutput, portMode, true));
1118 // set state to executing
1119 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
1121 // request EOS at the start
1122 ASSERT_NO_FATAL_FAILURE(testEOS(
1123 omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, portMode,
1124 portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr));
1125 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
1126 kPortIndexInput, kPortIndexOutput));
1127 EXPECT_GE(framesReceived, 0U);
1131 // set state to idle
1132 ASSERT_NO_FATAL_FAILURE(
1133 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
1134 // set state to executing
1135 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
1136 &oBuffer, kPortIndexInput,
1140 // end of sequence test
1141 TEST_F(VideoDecHidlTest, ThumbnailTest) {
1142 description("Test Request for thumbnail");
1143 if (disableTest) return;
1144 android::hardware::media::omx::V1_0::Status status;
1145 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1146 status = setRole(omxNode, gEnv->getRole().c_str());
1147 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1148 OMX_PORT_PARAM_TYPE params;
1149 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
1150 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1151 ASSERT_EQ(params.nPorts, 2U);
1152 kPortIndexInput = params.nStartPortNumber;
1153 kPortIndexOutput = kPortIndexInput + 1;
1155 char mURL[512], info[512];
1156 strcpy(mURL, gEnv->getRes().c_str());
1157 strcpy(info, gEnv->getRes().c_str());
1158 GetURLForComponent(compName, mURL, info);
1160 std::ifstream eleStream, eleInfo;
1163 ASSERT_EQ(eleInfo.is_open(), true);
1164 android::Vector<FrameData> Info;
1165 int bytesCount = 0, maxBytesCount = 0;
1167 uint32_t timestamp = 0;
1169 if (!(eleInfo >> bytesCount)) break;
1171 eleInfo >> timestamp;
1172 Info.push_back({bytesCount, flags, timestamp});
1173 if (maxBytesCount < bytesCount) maxBytesCount = bytesCount;
1177 // As the frame sizes are known ahead, use it to configure i/p buffer size
1178 maxBytesCount = ALIGN_POWER_OF_TWO(maxBytesCount, 10);
1179 status = setPortBufferSize(omxNode, kPortIndexInput, maxBytesCount);
1180 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1183 status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
1184 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1185 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
1186 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1189 uint32_t nFrameWidth, nFrameHeight, xFramerate;
1190 getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight,
1192 // get default color format
1193 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused;
1194 getDefaultColorFormat(omxNode, kPortIndexOutput, portMode[1],
1196 ASSERT_NE(eColorFormat, OMX_COLOR_FormatUnused);
1198 setVideoPortFormat(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
1199 eColorFormat, xFramerate);
1200 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1201 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
1202 eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
1204 android::Vector<BufferInfo> iBuffer, oBuffer;
1206 // set state to idle
1207 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(
1208 omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1209 kPortIndexOutput, portMode, true));
1210 // set state to executing
1211 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
1213 // request EOS for thumbnail
1215 while (!(Info[i].flags & OMX_BUFFERFLAG_SYNCFRAME)) i++;
1216 eleStream.open(mURL, std::ifstream::binary);
1217 ASSERT_EQ(eleStream.is_open(), true);
1218 ASSERT_NO_FATAL_FAILURE(decodeNFrames(
1219 omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1220 kPortIndexOutput, eleStream, &Info, 0, i + 1, portMode[1]));
1222 ASSERT_NO_FATAL_FAILURE(
1223 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
1224 kPortIndexInput, kPortIndexOutput, portMode[1]));
1225 ASSERT_NO_FATAL_FAILURE(testEOS(
1226 omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, portMode,
1227 portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr));
1228 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
1229 kPortIndexInput, kPortIndexOutput));
1230 EXPECT_GE(framesReceived, 1U);
1234 eleStream.open(mURL, std::ifstream::binary);
1235 ASSERT_EQ(eleStream.is_open(), true);
1236 ASSERT_NO_FATAL_FAILURE(decodeNFrames(
1237 omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1238 kPortIndexOutput, eleStream, &Info, 0, i + 1, portMode[1], false));
1240 ASSERT_NO_FATAL_FAILURE(
1241 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
1242 kPortIndexInput, kPortIndexOutput, portMode[1]));
1243 ASSERT_NO_FATAL_FAILURE(testEOS(
1244 omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, portMode,
1245 portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr));
1246 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
1247 kPortIndexInput, kPortIndexOutput));
1248 EXPECT_GE(framesReceived, 1U);
1252 // set state to idle
1253 ASSERT_NO_FATAL_FAILURE(
1254 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
1255 // set state to executing
1256 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
1257 &oBuffer, kPortIndexInput,
1261 // end of sequence test
1262 TEST_F(VideoDecHidlTest, SimpleEOSTest) {
1263 description("Test End of stream");
1264 if (disableTest) return;
1265 android::hardware::media::omx::V1_0::Status status;
1266 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1267 status = setRole(omxNode, gEnv->getRole().c_str());
1268 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1269 OMX_PORT_PARAM_TYPE params;
1270 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
1271 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1272 ASSERT_EQ(params.nPorts, 2U);
1273 kPortIndexInput = params.nStartPortNumber;
1274 kPortIndexOutput = kPortIndexInput + 1;
1276 char mURL[512], info[512];
1277 strcpy(mURL, gEnv->getRes().c_str());
1278 strcpy(info, gEnv->getRes().c_str());
1279 GetURLForComponent(compName, mURL, info);
1281 std::ifstream eleStream, eleInfo;
1284 ASSERT_EQ(eleInfo.is_open(), true);
1285 android::Vector<FrameData> Info;
1286 int bytesCount = 0, maxBytesCount = 0;
1288 uint32_t timestamp = 0;
1290 if (!(eleInfo >> bytesCount)) break;
1292 eleInfo >> timestamp;
1293 Info.push_back({bytesCount, flags, timestamp});
1294 if (maxBytesCount < bytesCount) maxBytesCount = bytesCount;
1298 // As the frame sizes are known ahead, use it to configure i/p buffer size
1299 maxBytesCount = ALIGN_POWER_OF_TWO(maxBytesCount, 10);
1300 status = setPortBufferSize(omxNode, kPortIndexInput, maxBytesCount);
1301 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1304 portMode[0] = PortMode::PRESET_BYTE_BUFFER;
1305 portMode[1] = PortMode::PRESET_ANW_BUFFER;
1306 status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
1307 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1308 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
1309 if (status != ::android::hardware::media::omx::V1_0::Status::OK) {
1310 portMode[1] = PortMode::PRESET_BYTE_BUFFER;
1311 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
1312 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1316 uint32_t nFrameWidth, nFrameHeight, xFramerate;
1317 getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight,
1319 // get default color format
1320 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused;
1321 getDefaultColorFormat(omxNode, kPortIndexOutput, portMode[1],
1323 ASSERT_NE(eColorFormat, OMX_COLOR_FormatUnused);
1325 setVideoPortFormat(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
1326 eColorFormat, xFramerate);
1327 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1328 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
1329 eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
1331 android::Vector<BufferInfo> iBuffer, oBuffer;
1333 // set state to idle
1334 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(
1335 omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1336 kPortIndexOutput, portMode, true));
1337 // set state to executing
1338 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
1340 // request EOS at the end
1341 eleStream.open(mURL, std::ifstream::binary);
1342 ASSERT_EQ(eleStream.is_open(), true);
1343 ASSERT_NO_FATAL_FAILURE(decodeNFrames(omxNode, observer, &iBuffer, &oBuffer,
1344 kPortIndexInput, kPortIndexOutput,
1345 eleStream, &Info, 0, (int)Info.size(),
1346 portMode[1], false));
1348 ASSERT_NO_FATAL_FAILURE(
1349 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer,
1350 kPortIndexInput, kPortIndexOutput, portMode[1]));
1351 ASSERT_NO_FATAL_FAILURE(testEOS(
1352 omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, portMode,
1353 portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr));
1354 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
1355 kPortIndexInput, kPortIndexOutput));
1359 // set state to idle
1360 ASSERT_NO_FATAL_FAILURE(
1361 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
1362 // set state to executing
1363 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
1364 &oBuffer, kPortIndexInput,
1368 // test input/output port flush
1369 TEST_F(VideoDecHidlTest, FlushTest) {
1370 description("Test Flush");
1371 if (disableTest) return;
1372 android::hardware::media::omx::V1_0::Status status;
1373 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1374 status = setRole(omxNode, gEnv->getRole().c_str());
1375 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1376 OMX_PORT_PARAM_TYPE params;
1377 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
1378 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1379 ASSERT_EQ(params.nPorts, 2U);
1380 kPortIndexInput = params.nStartPortNumber;
1381 kPortIndexOutput = kPortIndexInput + 1;
1383 char mURL[512], info[512];
1384 strcpy(mURL, gEnv->getRes().c_str());
1385 strcpy(info, gEnv->getRes().c_str());
1386 GetURLForComponent(compName, mURL, info);
1388 std::ifstream eleStream, eleInfo;
1391 ASSERT_EQ(eleInfo.is_open(), true);
1392 android::Vector<FrameData> Info;
1393 int bytesCount = 0, maxBytesCount = 0;
1395 uint32_t timestamp = 0;
1397 if (!(eleInfo >> bytesCount)) break;
1399 eleInfo >> timestamp;
1400 Info.push_back({bytesCount, flags, timestamp});
1401 if (maxBytesCount < bytesCount) maxBytesCount = bytesCount;
1405 // As the frame sizes are known ahead, use it to configure i/p buffer size
1406 maxBytesCount = ALIGN_POWER_OF_TWO(maxBytesCount, 10);
1407 status = setPortBufferSize(omxNode, kPortIndexInput, maxBytesCount);
1408 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1411 status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
1412 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1413 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
1414 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1417 uint32_t nFrameWidth, nFrameHeight, xFramerate;
1418 getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight,
1420 // get default color format
1421 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused;
1422 getDefaultColorFormat(omxNode, kPortIndexOutput, portMode[1],
1424 ASSERT_NE(eColorFormat, OMX_COLOR_FormatUnused);
1426 setVideoPortFormat(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
1427 eColorFormat, xFramerate);
1428 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1429 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused,
1430 eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate);
1432 android::Vector<BufferInfo> iBuffer, oBuffer;
1434 // set state to idle
1435 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(
1436 omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1437 kPortIndexOutput, portMode, true));
1438 // set state to executing
1439 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
1441 // Decode 128 frames and flush. here 128 is chosen to ensure there is a key
1442 // frame after this so that the below section can be convered for all
1445 eleStream.open(mURL, std::ifstream::binary);
1446 ASSERT_EQ(eleStream.is_open(), true);
1447 ASSERT_NO_FATAL_FAILURE(decodeNFrames(
1448 omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1449 kPortIndexOutput, eleStream, &Info, 0, nFrames, portMode[1], false));
1450 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
1451 kPortIndexInput, kPortIndexOutput));
1454 // Seek to next key frame and start decoding till the end
1455 int index = nFrames;
1456 bool keyFrame = false;
1457 while (index < (int)Info.size()) {
1458 if ((Info[index].flags & OMX_BUFFERFLAG_SYNCFRAME) ==
1459 OMX_BUFFERFLAG_SYNCFRAME) {
1460 timestampUs = Info[index - 1].timestamp;
1464 eleStream.ignore(Info[index].bytesCount);
1468 ASSERT_NO_FATAL_FAILURE(
1469 decodeNFrames(omxNode, observer, &iBuffer, &oBuffer,
1470 kPortIndexInput, kPortIndexOutput, eleStream, &Info,
1471 index, Info.size() - index, portMode[1], false));
1474 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
1475 kPortIndexInput, kPortIndexOutput));
1478 // set state to idle
1479 ASSERT_NO_FATAL_FAILURE(
1480 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
1481 // set state to executing
1482 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
1483 &oBuffer, kPortIndexInput,
1487 int main(int argc, char** argv) {
1488 gEnv = new ComponentTestEnvironment();
1489 ::testing::AddGlobalTestEnvironment(gEnv);
1490 ::testing::InitGoogleTest(&argc, argv);
1491 int status = gEnv->initFromOptions(argc, argv);
1493 status = RUN_ALL_TESTS();
1494 ALOGI("Test result = %d", status);