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_audio_dec_test"
18 #include <android-base/logging.h>
20 #include <android/hardware/media/omx/1.0/IOmx.h>
21 #include <android/hardware/media/omx/1.0/IOmxNode.h>
22 #include <android/hardware/media/omx/1.0/IOmxObserver.h>
23 #include <android/hardware/media/omx/1.0/types.h>
24 #include <android/hidl/allocator/1.0/IAllocator.h>
25 #include <android/hidl/memory/1.0/IMapper.h>
26 #include <android/hidl/memory/1.0/IMemory.h>
28 using ::android::hardware::media::omx::V1_0::IOmx;
29 using ::android::hardware::media::omx::V1_0::IOmxObserver;
30 using ::android::hardware::media::omx::V1_0::IOmxNode;
31 using ::android::hardware::media::omx::V1_0::Message;
32 using ::android::hardware::media::omx::V1_0::CodecBuffer;
33 using ::android::hardware::media::omx::V1_0::PortMode;
34 using ::android::hidl::allocator::V1_0::IAllocator;
35 using ::android::hidl::memory::V1_0::IMemory;
36 using ::android::hidl::memory::V1_0::IMapper;
37 using ::android::hardware::Return;
38 using ::android::hardware::Void;
39 using ::android::hardware::hidl_vec;
40 using ::android::hardware::hidl_string;
43 #include <VtsHalHidlTargetTestBase.h>
45 #include <media_audio_hidl_test_common.h>
46 #include <media_hidl_test_common.h>
49 // A class for test environment setup
50 class ComponentTestEnvironment : public ::testing::Environment {
52 virtual void SetUp() {}
53 virtual void TearDown() {}
55 ComponentTestEnvironment() : instance("default"), res("/sdcard/media/") {}
57 void setInstance(const char* _instance) { instance = _instance; }
59 void setComponent(const char* _component) { component = _component; }
61 void setRole(const char* _role) { role = _role; }
63 void setRes(const char* _res) { res = _res; }
65 const hidl_string getInstance() const { return instance; }
67 const hidl_string getComponent() const { return component; }
69 const hidl_string getRole() const { return role; }
71 const hidl_string getRes() const { return res; }
73 int initFromOptions(int argc, char** argv) {
74 static struct option options[] = {
75 {"instance", required_argument, 0, 'I'},
76 {"component", required_argument, 0, 'C'},
77 {"role", required_argument, 0, 'R'},
78 {"res", required_argument, 0, 'P'},
83 int c = getopt_long(argc, argv, "I:C:R:P:", options, &index);
108 "unrecognized option: %s\n\n"
109 "usage: %s <gtest options> <test options>\n\n"
110 "test options are:\n\n"
111 "-I, --instance: HAL instance to test\n"
112 "-C, --component: OMX component to test\n"
113 "-R, --role: OMX component Role\n"
114 "-P, --res: Resource files directory location\n",
115 argv[optind ?: 1], argv[0]);
122 hidl_string instance;
123 hidl_string component;
128 static ComponentTestEnvironment* gEnv = nullptr;
130 // audio decoder test fixture class
131 class AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
133 virtual void SetUp() override {
135 android::hardware::media::omx::V1_0::Status status;
136 omx = ::testing::VtsHalHidlTargetTestBase::getService<IOmx>(
137 gEnv->getInstance());
138 ASSERT_NE(omx, nullptr);
140 new CodecObserver([this](Message msg, const BufferInfo* buffer) {
141 handleMessage(msg, buffer);
143 ASSERT_NE(observer, nullptr);
144 if (strncmp(gEnv->getComponent().c_str(), "OMX.", 4) != 0)
146 EXPECT_TRUE(omx->allocateNode(
147 gEnv->getComponent(), observer,
148 [&](android::hardware::media::omx::V1_0::Status _s,
149 sp<IOmxNode> const& _nl) {
154 ASSERT_NE(omxNode, nullptr);
155 ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
156 struct StringToName {
158 standardComp CompName;
160 const StringToName kStringToName[] = {
161 {"mp3", mp3}, {"amrnb", amrnb}, {"amrwb", amrwb},
162 {"aac", aac}, {"vorbis", vorbis}, {"opus", opus},
163 {"pcm", pcm}, {"g711alaw", g711alaw}, {"g711mlaw", g711mlaw},
164 {"gsm", gsm}, {"raw", raw},
166 const size_t kNumStringToName =
167 sizeof(kStringToName) / sizeof(kStringToName[0]);
169 char substring[OMX_MAX_STRINGNAME_SIZE];
170 strcpy(substring, gEnv->getRole().c_str());
171 pch = strchr(substring, '.');
172 ASSERT_NE(pch, nullptr);
173 compName = unknown_comp;
174 for (size_t i = 0; i < kNumStringToName; ++i) {
175 if (!strcasecmp(pch + 1, kStringToName[i].Name)) {
176 compName = kStringToName[i].CompName;
180 if (compName == unknown_comp) disableTest = true;
181 struct CompToCoding {
182 standardComp CompName;
183 OMX_AUDIO_CODINGTYPE eEncoding;
185 static const CompToCoding kCompToCoding[] = {
186 {mp3, OMX_AUDIO_CodingMP3},
187 {amrnb, OMX_AUDIO_CodingAMR},
188 {amrwb, OMX_AUDIO_CodingAMR},
189 {aac, OMX_AUDIO_CodingAAC},
190 {vorbis, OMX_AUDIO_CodingVORBIS},
191 {pcm, OMX_AUDIO_CodingPCM},
192 {opus, (OMX_AUDIO_CODINGTYPE)OMX_AUDIO_CodingAndroidOPUS},
193 {g711alaw, OMX_AUDIO_CodingG711},
194 {g711mlaw, OMX_AUDIO_CodingG711},
195 {gsm, OMX_AUDIO_CodingGSMFR},
196 {raw, OMX_AUDIO_CodingPCM},
198 static const size_t kNumCompToCoding =
199 sizeof(kCompToCoding) / sizeof(kCompToCoding[0]);
201 for (i = 0; i < kNumCompToCoding; ++i) {
202 if (kCompToCoding[i].CompName == compName) {
203 eEncoding = kCompToCoding[i].eEncoding;
207 if (i == kNumCompToCoding) disableTest = true;
211 timestampDevTest = false;
212 if (disableTest) std::cerr << "[ ] Warning ! Test Disabled\n";
215 virtual void TearDown() override {
216 if (omxNode != nullptr) {
217 EXPECT_TRUE((omxNode->freeNode()).isOk());
222 // callback function to process messages received by onMessages() from IL
224 void handleMessage(Message msg, const BufferInfo* buffer) {
226 if (msg.type == Message::Type::FILL_BUFFER_DONE) {
227 if (msg.data.extendedBufferData.flags & OMX_BUFFERFLAG_EOS) {
230 if (msg.data.extendedBufferData.rangeLength != 0) {
232 // For decoder components current timestamp always exceeds
233 // previous timestamp
234 EXPECT_GE(msg.data.extendedBufferData.timestampUs, timestampUs);
235 timestampUs = msg.data.extendedBufferData.timestampUs;
236 // Test if current timestamp is among the list of queued
238 if (timestampDevTest) {
240 android::List<uint64_t>::iterator it =
241 timestampUslist.begin();
242 while (it != timestampUslist.end()) {
243 if (*it == timestampUs) {
244 timestampUslist.erase(it);
250 if (tsHit == false) {
251 if (timestampUslist.empty() == false) {
252 EXPECT_EQ(tsHit, true)
253 << "TimeStamp not recognized";
256 << "[ ] Warning ! Received non-zero "
257 "output / TimeStamp not recognized \n";
261 #define WRITE_OUTPUT 0
263 static int count = 0;
266 ofp = fopen("out.bin", "ab");
268 ofp = fopen("out.bin", "wb");
269 if (ofp != nullptr) {
270 fwrite(static_cast<void*>(buffer->mMemory->getPointer()),
272 msg.data.extendedBufferData.rangeLength, ofp);
297 sp<CodecObserver> observer;
298 sp<IOmxNode> omxNode;
299 standardComp compName;
300 OMX_AUDIO_CODINGTYPE eEncoding;
303 uint32_t framesReceived;
304 uint64_t timestampUs;
305 ::android::List<uint64_t> timestampUslist;
306 bool timestampDevTest;
309 static void description(const std::string& description) {
310 RecordProperty("description", description);
314 // Set Default port param.
315 void setDefaultPortParam(
316 sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE eEncoding,
317 int32_t nChannels = 2, int32_t nSampleRate = 44100,
318 OMX_AUDIO_PCMMODETYPE ePCMMode = OMX_AUDIO_PCMModeLinear,
319 OMX_NUMERICALDATATYPE eNumData = OMX_NumericalDataSigned,
320 int32_t nBitPerSample = 16) {
321 android::hardware::media::omx::V1_0::Status status;
323 OMX_PARAM_PORTDEFINITIONTYPE portDef;
324 status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
326 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
328 portDef.format.audio.bFlagErrorConcealment = OMX_TRUE;
329 portDef.format.audio.eEncoding = eEncoding;
330 status = setPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
332 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
334 switch ((int)eEncoding) {
335 case OMX_AUDIO_CodingPCM:
336 setupPCMPort(omxNode, portIndex, nChannels, eNumData, nBitPerSample,
337 nSampleRate, ePCMMode);
339 case OMX_AUDIO_CodingAAC:
340 setupAACPort(omxNode, portIndex, OMX_AUDIO_AACObjectNull,
341 OMX_AUDIO_AACStreamFormatMP4FF, nChannels, 0,
348 // In decoder components, often the input port parameters get updated upon
349 // parsing the header of elementary stream. Client needs to collect this
350 // information to reconfigure other ports that share data with this input
352 void getInputChannelInfo(sp<IOmxNode> omxNode, OMX_U32 kPortIndexInput,
353 OMX_AUDIO_CODINGTYPE eEncoding, int32_t* nChannels,
354 int32_t* nSampleRate) {
355 android::hardware::media::omx::V1_0::Status status;
359 switch ((int)eEncoding) {
360 case OMX_AUDIO_CodingGSMFR:
361 case OMX_AUDIO_CodingG711:
362 case OMX_AUDIO_CodingPCM: {
363 OMX_AUDIO_PARAM_PCMMODETYPE param;
364 status = getPortParam(omxNode, OMX_IndexParamAudioPcm,
365 kPortIndexInput, ¶m);
367 ::android::hardware::media::omx::V1_0::Status::OK);
368 *nChannels = param.nChannels;
369 *nSampleRate = param.nSamplingRate;
372 case OMX_AUDIO_CodingMP3: {
373 OMX_AUDIO_PARAM_MP3TYPE param;
374 status = getPortParam(omxNode, OMX_IndexParamAudioMp3,
375 kPortIndexInput, ¶m);
377 ::android::hardware::media::omx::V1_0::Status::OK);
378 *nChannels = param.nChannels;
379 *nSampleRate = param.nSampleRate;
382 case OMX_AUDIO_CodingAndroidOPUS: {
383 OMX_AUDIO_PARAM_ANDROID_OPUSTYPE param;
384 status = getPortParam(omxNode,
385 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
386 kPortIndexInput, ¶m);
388 ::android::hardware::media::omx::V1_0::Status::OK);
389 *nChannels = param.nChannels;
390 *nSampleRate = param.nSampleRate;
393 case OMX_AUDIO_CodingVORBIS: {
394 OMX_AUDIO_PARAM_VORBISTYPE param;
395 status = getPortParam(omxNode, OMX_IndexParamAudioVorbis,
396 kPortIndexInput, ¶m);
398 ::android::hardware::media::omx::V1_0::Status::OK);
399 *nChannels = param.nChannels;
400 *nSampleRate = param.nSampleRate;
403 case OMX_AUDIO_CodingAMR: {
404 OMX_AUDIO_PARAM_AMRTYPE param;
405 status = getPortParam(omxNode, OMX_IndexParamAudioAmr,
406 kPortIndexInput, ¶m);
408 ::android::hardware::media::omx::V1_0::Status::OK);
409 *nChannels = param.nChannels;
413 case OMX_AUDIO_CodingAAC: {
414 OMX_AUDIO_PARAM_AACPROFILETYPE param;
415 status = getPortParam(omxNode, OMX_IndexParamAudioAac,
416 kPortIndexInput, ¶m);
418 ::android::hardware::media::omx::V1_0::Status::OK);
419 *nChannels = param.nChannels;
420 *nSampleRate = param.nSampleRate;
429 // LookUpTable of clips and metadata for component testing
430 void GetURLForComponent(AudioDecHidlTest::standardComp comp, char* mURL,
433 AudioDecHidlTest::standardComp comp;
437 static const CompToURL kCompToURL[] = {
438 {AudioDecHidlTest::standardComp::mp3,
439 "bbb_mp3_stereo_192kbps_48000hz.mp3",
440 "bbb_mp3_stereo_192kbps_48000hz.info"},
441 {AudioDecHidlTest::standardComp::aac,
442 "bbb_aac_stereo_128kbps_48000hz.aac",
443 "bbb_aac_stereo_128kbps_48000hz.info"},
444 {AudioDecHidlTest::standardComp::amrnb,
445 "sine_amrnb_1ch_12kbps_8000hz.amrnb",
446 "sine_amrnb_1ch_12kbps_8000hz.info"},
447 {AudioDecHidlTest::standardComp::amrwb,
448 "bbb_amrwb_1ch_14kbps_16000hz.amrwb",
449 "bbb_amrwb_1ch_14kbps_16000hz.info"},
450 {AudioDecHidlTest::standardComp::vorbis,
451 "bbb_vorbis_stereo_128kbps_48000hz.vorbis",
452 "bbb_vorbis_stereo_128kbps_48000hz.info"},
453 {AudioDecHidlTest::standardComp::opus,
454 "bbb_opus_stereo_128kbps_48000hz.opus",
455 "bbb_opus_stereo_128kbps_48000hz.info"},
456 {AudioDecHidlTest::standardComp::g711alaw, "bbb_g711alaw_1ch_8khz.raw",
457 "bbb_g711alaw_1ch_8khz.info"},
458 {AudioDecHidlTest::standardComp::g711mlaw, "bbb_g711mulaw_1ch_8khz.raw",
459 "bbb_g711mulaw_1ch_8khz.info"},
460 {AudioDecHidlTest::standardComp::gsm, "bbb_gsm_1ch_8khz_13kbps.raw",
461 "bbb_gsm_1ch_8khz_13kbps.info"},
462 {AudioDecHidlTest::standardComp::raw, "bbb_raw_1ch_8khz_s32le.raw",
463 "bbb_raw_1ch_8khz_s32le.info"},
466 for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
467 if (kCompToURL[i].comp == comp) {
468 strcat(mURL, kCompToURL[i].mURL);
469 strcat(info, kCompToURL[i].info);
475 // port settings reconfiguration during runtime. reconfigures sample rate and
478 OMX_AUDIO_CODINGTYPE eEncoding;
479 AudioDecHidlTest::standardComp comp;
481 void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
482 android::Vector<BufferInfo>* iBuffer,
483 android::Vector<BufferInfo>* oBuffer,
484 OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
485 Message msg, PortMode oPortMode, void* args) {
486 android::hardware::media::omx::V1_0::Status status;
487 packedArgs* audioArgs = static_cast<packedArgs*>(args);
488 OMX_AUDIO_CODINGTYPE eEncoding = audioArgs->eEncoding;
489 AudioDecHidlTest::standardComp comp = audioArgs->comp;
492 if (msg.data.eventData.event == OMX_EventPortSettingsChanged) {
493 ASSERT_EQ(msg.data.eventData.data1, kPortIndexOutput);
495 status = omxNode->sendCommand(toRawCommandType(OMX_CommandPortDisable),
497 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
500 observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
501 if (status == android::hardware::media::omx::V1_0::Status::TIMED_OUT) {
502 for (size_t i = 0; i < oBuffer->size(); ++i) {
503 // test if client got all its buffers back
504 EXPECT_EQ((*oBuffer)[i].owner, client);
507 omxNode->freeBuffer(kPortIndexOutput, (*oBuffer)[i].id);
509 android::hardware::media::omx::V1_0::Status::OK);
511 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer,
513 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
514 ASSERT_EQ(msg.type, Message::Type::EVENT);
515 ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
516 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortDisable);
517 ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
522 getInputChannelInfo(omxNode, kPortIndexInput, eEncoding, &nChannels,
524 // Configure output port
525 // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way
527 // configure output PCM port. The port undergoes auto configuration
528 // internally basing on parsed elementary stream information.
529 if (comp != AudioDecHidlTest::standardComp::vorbis &&
530 comp != AudioDecHidlTest::standardComp::opus &&
531 comp != AudioDecHidlTest::standardComp::raw) {
532 setDefaultPortParam(omxNode, kPortIndexOutput,
533 OMX_AUDIO_CodingPCM, nChannels,
537 // If you can disable a port, then you should be able to
540 status = omxNode->sendCommand(
541 toRawCommandType(OMX_CommandPortEnable), kPortIndexOutput);
542 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
544 // do not enable the port until all the buffers are supplied
545 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer,
548 android::hardware::media::omx::V1_0::Status::TIMED_OUT);
550 allocatePortBuffers(omxNode, oBuffer, kPortIndexOutput);
551 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer,
553 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
554 ASSERT_EQ(msg.type, Message::Type::EVENT);
555 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortEnable);
556 ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
558 // dispatch output buffers
559 for (size_t i = 0; i < oBuffer->size(); i++) {
560 dispatchOutputBuffer(omxNode, oBuffer, i);
571 // blocking call to ensures application to Wait till all the inputs are consumed
572 void waitOnInputConsumption(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
573 android::Vector<BufferInfo>* iBuffer,
574 android::Vector<BufferInfo>* oBuffer,
575 OMX_AUDIO_CODINGTYPE eEncoding,
576 OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
577 AudioDecHidlTest::standardComp comp) {
578 android::hardware::media::omx::V1_0::Status status;
580 int timeOut = TIMEOUT_COUNTER;
585 observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
586 if (status == android::hardware::media::omx::V1_0::Status::OK) {
587 EXPECT_EQ(msg.type, Message::Type::EVENT);
588 packedArgs audioArgs = {eEncoding, comp};
589 portReconfiguration(omxNode, observer, iBuffer, oBuffer,
590 kPortIndexInput, kPortIndexOutput, msg,
591 PortMode::PRESET_BYTE_BUFFER, &audioArgs);
593 // status == TIMED_OUT, it could be due to process time being large
594 // than DEFAULT_TIMEOUT or component needs output buffers to start
596 for (; i < iBuffer->size(); i++) {
597 if ((*iBuffer)[i].owner != client) break;
599 if (i == iBuffer->size()) break;
601 // Dispatch an output buffer assuming outQueue.empty() is true
603 if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
604 dispatchOutputBuffer(omxNode, oBuffer, index);
611 void decodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
612 android::Vector<BufferInfo>* iBuffer,
613 android::Vector<BufferInfo>* oBuffer,
614 OMX_AUDIO_CODINGTYPE eEncoding, OMX_U32 kPortIndexInput,
615 OMX_U32 kPortIndexOutput, std::ifstream& eleStream,
616 android::Vector<FrameData>* Info, int offset, int range,
617 AudioDecHidlTest::standardComp comp, bool signalEOS = true) {
618 android::hardware::media::omx::V1_0::Status status;
621 // dispatch output buffers
622 for (size_t i = 0; i < oBuffer->size(); i++) {
623 dispatchOutputBuffer(omxNode, oBuffer, i);
625 // dispatch input buffers
627 int frameID = offset;
628 for (size_t i = 0; (i < iBuffer->size()) && (frameID < (int)Info->size()) &&
629 (frameID < (offset + range));
631 char* ipBuffer = static_cast<char*>(
632 static_cast<void*>((*iBuffer)[i].mMemory->getPointer()));
633 ASSERT_LE((*Info)[frameID].bytesCount,
634 static_cast<int>((*iBuffer)[i].mMemory->getSize()));
635 eleStream.read(ipBuffer, (*Info)[frameID].bytesCount);
636 ASSERT_EQ(eleStream.gcount(), (*Info)[frameID].bytesCount);
637 flags = (*Info)[frameID].flags;
638 if (signalEOS && ((frameID == (int)Info->size() - 1) ||
639 (frameID == (offset + range - 1))))
640 flags |= OMX_BUFFERFLAG_EOS;
641 dispatchInputBuffer(omxNode, iBuffer, i, (*Info)[frameID].bytesCount,
642 flags, (*Info)[frameID].timestamp);
646 int timeOut = TIMEOUT_COUNTER;
650 observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
652 // Port Reconfiguration
653 if (status == android::hardware::media::omx::V1_0::Status::OK &&
654 msg.type == Message::Type::EVENT) {
655 packedArgs audioArgs = {eEncoding, comp};
656 portReconfiguration(omxNode, observer, iBuffer, oBuffer,
657 kPortIndexInput, kPortIndexOutput, msg,
658 PortMode::PRESET_BYTE_BUFFER, &audioArgs);
661 if (frameID == (int)Info->size() || frameID == (offset + range)) break;
663 // Dispatch input buffer
665 if ((index = getEmptyBufferID(iBuffer)) < iBuffer->size()) {
666 char* ipBuffer = static_cast<char*>(
667 static_cast<void*>((*iBuffer)[index].mMemory->getPointer()));
668 ASSERT_LE((*Info)[frameID].bytesCount,
669 static_cast<int>((*iBuffer)[index].mMemory->getSize()));
670 eleStream.read(ipBuffer, (*Info)[frameID].bytesCount);
671 ASSERT_EQ(eleStream.gcount(), (*Info)[frameID].bytesCount);
672 flags = (*Info)[frameID].flags;
673 if (signalEOS && ((frameID == (int)Info->size() - 1) ||
674 (frameID == (offset + range - 1))))
675 flags |= OMX_BUFFERFLAG_EOS;
676 dispatchInputBuffer(omxNode, iBuffer, index,
677 (*Info)[frameID].bytesCount, flags,
678 (*Info)[frameID].timestamp);
683 if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
684 dispatchOutputBuffer(omxNode, oBuffer, index);
691 timeOut = TIMEOUT_COUNTER;
693 EXPECT_TRUE(false) << "Wait on Input/Output is found indefinite";
699 // set component role
700 TEST_F(AudioDecHidlTest, SetRole) {
701 description("Test Set Component Role");
702 if (disableTest) return;
703 android::hardware::media::omx::V1_0::Status status;
704 status = setRole(omxNode, gEnv->getRole().c_str());
705 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
708 // port format enumeration
709 TEST_F(AudioDecHidlTest, DISABLED_EnumeratePortFormat) {
710 description("Test Component on Mandatory Port Parameters (Port Format)");
711 if (disableTest) return;
712 android::hardware::media::omx::V1_0::Status status;
713 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
714 status = setRole(omxNode, gEnv->getRole().c_str());
715 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
716 OMX_PORT_PARAM_TYPE params;
717 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
718 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
719 ASSERT_EQ(params.nPorts, 2U);
720 kPortIndexInput = params.nStartPortNumber;
721 kPortIndexOutput = kPortIndexInput + 1;
723 status = setAudioPortFormat(omxNode, kPortIndexInput, eEncoding);
724 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
725 status = setAudioPortFormat(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM);
726 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
729 // test port settings reconfiguration, elementary stream decode and timestamp
731 TEST_F(AudioDecHidlTest, DecodeTest) {
732 description("Tests Port Reconfiguration, Decode and timestamp deviation");
733 if (disableTest) return;
734 android::hardware::media::omx::V1_0::Status status;
735 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
736 status = setRole(omxNode, gEnv->getRole().c_str());
737 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
738 OMX_PORT_PARAM_TYPE params;
739 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
740 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
741 ASSERT_EQ(params.nPorts, 2U);
742 kPortIndexInput = params.nStartPortNumber;
743 kPortIndexOutput = kPortIndexInput + 1;
745 char mURL[512], info[512];
746 strcpy(mURL, gEnv->getRes().c_str());
747 strcpy(info, gEnv->getRes().c_str());
748 GetURLForComponent(compName, mURL, info);
750 std::ifstream eleStream, eleInfo;
753 ASSERT_EQ(eleInfo.is_open(), true);
754 android::Vector<FrameData> Info;
757 uint32_t timestamp = 0;
758 timestampDevTest = false;
760 if (!(eleInfo >> bytesCount)) break;
762 eleInfo >> timestamp;
763 Info.push_back({bytesCount, flags, timestamp});
764 if (flags != OMX_BUFFERFLAG_CODECCONFIG)
765 timestampUslist.push_back(timestamp);
769 int32_t nChannels, nSampleRate;
770 // Configure input port
771 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
773 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
774 OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
776 getInputChannelInfo(omxNode, kPortIndexInput, eEncoding, &nChannels,
778 // Configure output port
779 // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
780 // configure output PCM port. The port undergoes auto configuration
781 // internally basing on parsed elementary stream information.
782 if (compName != vorbis && compName != opus && compName != raw) {
783 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
784 nChannels, nSampleRate);
787 android::Vector<BufferInfo> iBuffer, oBuffer;
790 changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
791 kPortIndexInput, kPortIndexOutput);
792 // set state to executing
793 changeStateIdletoExecute(omxNode, observer);
794 // Port Reconfiguration
795 eleStream.open(mURL, std::ifstream::binary);
796 ASSERT_EQ(eleStream.is_open(), true);
797 decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
798 kPortIndexInput, kPortIndexOutput, eleStream, &Info, 0,
799 (int)Info.size(), compName);
801 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
802 kPortIndexInput, kPortIndexOutput, compName);
803 packedArgs audioArgs = {eEncoding, compName};
804 testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, nullptr,
805 portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs);
806 EXPECT_EQ(timestampUslist.empty(), true);
808 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
809 // set state to executing
810 changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
811 kPortIndexInput, kPortIndexOutput);
814 // end of sequence test
815 // SPECIAL CASE; Sending Empty input EOS buffer is not supported across all
816 // components. For instance soft vorbis and soft opus expects CSD buffers at
817 // the start. Disabling this test for now. We shall revisit this at a later
819 TEST_F(AudioDecHidlTest, DISABLED_EOSTest_M) {
820 description("Test end of stream monkeying");
821 if (disableTest) return;
822 android::hardware::media::omx::V1_0::Status status;
823 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
824 status = setRole(omxNode, gEnv->getRole().c_str());
825 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
826 OMX_PORT_PARAM_TYPE params;
827 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
828 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
829 ASSERT_EQ(params.nPorts, 2U);
830 kPortIndexInput = params.nStartPortNumber;
831 kPortIndexOutput = kPortIndexInput + 1;
834 int32_t nChannels, nSampleRate;
835 // Configure input port
836 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
838 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
839 OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
841 getInputChannelInfo(omxNode, kPortIndexInput, eEncoding, &nChannels,
843 // Configure output port
844 // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
845 // configure output PCM port. The port undergoes auto configuration
846 // internally basing on parsed elementary stream information.
847 if (compName != vorbis && compName != opus && compName != raw) {
848 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
849 nChannels, nSampleRate);
852 android::Vector<BufferInfo> iBuffer, oBuffer;
855 changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
856 kPortIndexInput, kPortIndexOutput);
857 // set state to executing
858 changeStateIdletoExecute(omxNode, observer);
860 // request EOS at the start
861 packedArgs audioArgs = {eEncoding, compName};
862 testEOS(omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, nullptr,
863 portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs);
864 flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
866 EXPECT_GE(framesReceived, 0U);
871 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
872 // set state to executing
873 changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
874 kPortIndexInput, kPortIndexOutput);
877 // end of sequence test
878 TEST_F(AudioDecHidlTest, ThumbnailTest) {
879 description("Test Request for thumbnail");
880 if (disableTest) return;
881 android::hardware::media::omx::V1_0::Status status;
882 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
883 status = setRole(omxNode, gEnv->getRole().c_str());
884 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
885 OMX_PORT_PARAM_TYPE params;
886 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
887 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
888 ASSERT_EQ(params.nPorts, 2U);
889 kPortIndexInput = params.nStartPortNumber;
890 kPortIndexOutput = kPortIndexInput + 1;
892 char mURL[512], info[512];
893 strcpy(mURL, gEnv->getRes().c_str());
894 strcpy(info, gEnv->getRes().c_str());
895 GetURLForComponent(compName, mURL, info);
897 std::ifstream eleStream, eleInfo;
900 ASSERT_EQ(eleInfo.is_open(), true);
901 android::Vector<FrameData> Info;
904 uint32_t timestamp = 0;
906 if (!(eleInfo >> bytesCount)) break;
908 eleInfo >> timestamp;
909 Info.push_back({bytesCount, flags, timestamp});
913 int32_t nChannels, nSampleRate;
914 // Configure input port
915 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
917 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
918 OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
920 getInputChannelInfo(omxNode, kPortIndexInput, eEncoding, &nChannels,
922 // Configure output port
923 // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
924 // configure output PCM port. The port undergoes auto configuration
925 // internally basing on parsed elementary stream information.
926 if (compName != vorbis && compName != opus && compName != raw) {
927 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
928 nChannels, nSampleRate);
931 android::Vector<BufferInfo> iBuffer, oBuffer;
934 changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
935 kPortIndexInput, kPortIndexOutput);
936 // set state to executing
937 changeStateIdletoExecute(omxNode, observer);
939 // request EOS for thumbnail
940 // signal EOS flag with last frame
942 while (!(Info[i].flags & OMX_BUFFERFLAG_SYNCFRAME)) i++;
943 eleStream.open(mURL, std::ifstream::binary);
944 ASSERT_EQ(eleStream.is_open(), true);
945 decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
946 kPortIndexInput, kPortIndexOutput, eleStream, &Info, 0, i + 1,
949 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
950 kPortIndexInput, kPortIndexOutput, compName);
951 packedArgs audioArgs = {eEncoding, compName};
952 testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, nullptr,
953 portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs);
954 flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
956 EXPECT_GE(framesReceived, 1U);
960 // signal EOS flag after last frame
961 eleStream.open(mURL, std::ifstream::binary);
962 ASSERT_EQ(eleStream.is_open(), true);
963 decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
964 kPortIndexInput, kPortIndexOutput, eleStream, &Info, 0, i + 1,
967 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
968 kPortIndexInput, kPortIndexOutput, compName);
969 testEOS(omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, nullptr,
970 portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs);
971 flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
973 EXPECT_GE(framesReceived, 1U);
978 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
979 // set state to executing
980 changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
981 kPortIndexInput, kPortIndexOutput);
984 // end of sequence test
985 TEST_F(AudioDecHidlTest, SimpleEOSTest) {
986 description("Test end of stream");
987 if (disableTest) return;
988 android::hardware::media::omx::V1_0::Status status;
989 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
990 status = setRole(omxNode, gEnv->getRole().c_str());
991 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
992 OMX_PORT_PARAM_TYPE params;
993 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
994 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
995 ASSERT_EQ(params.nPorts, 2U);
996 kPortIndexInput = params.nStartPortNumber;
997 kPortIndexOutput = kPortIndexInput + 1;
999 char mURL[512], info[512];
1000 strcpy(mURL, gEnv->getRes().c_str());
1001 strcpy(info, gEnv->getRes().c_str());
1002 GetURLForComponent(compName, mURL, info);
1004 std::ifstream eleStream, eleInfo;
1007 ASSERT_EQ(eleInfo.is_open(), true);
1008 android::Vector<FrameData> Info;
1011 uint32_t timestamp = 0;
1013 if (!(eleInfo >> bytesCount)) break;
1015 eleInfo >> timestamp;
1016 Info.push_back({bytesCount, flags, timestamp});
1020 int32_t nChannels, nSampleRate;
1021 // Configure input port
1022 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
1023 if (compName == raw)
1024 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
1025 OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
1027 getInputChannelInfo(omxNode, kPortIndexInput, eEncoding, &nChannels,
1029 // Configure output port
1030 // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
1031 // configure output PCM port. The port undergoes auto configuration
1032 // internally basing on parsed elementary stream information.
1033 if (compName != vorbis && compName != opus && compName != raw) {
1034 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
1035 nChannels, nSampleRate);
1038 android::Vector<BufferInfo> iBuffer, oBuffer;
1040 // set state to idle
1041 changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
1042 kPortIndexInput, kPortIndexOutput);
1043 // set state to executing
1044 changeStateIdletoExecute(omxNode, observer);
1046 // request EOS at the end
1047 eleStream.open(mURL, std::ifstream::binary);
1048 ASSERT_EQ(eleStream.is_open(), true);
1049 decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
1050 kPortIndexInput, kPortIndexOutput, eleStream, &Info, 0,
1051 (int)Info.size(), compName, false);
1053 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
1054 kPortIndexInput, kPortIndexOutput, compName);
1055 packedArgs audioArgs = {eEncoding, compName};
1056 testEOS(omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, nullptr,
1057 portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs);
1058 flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1063 // set state to idle
1064 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
1065 // set state to executing
1066 changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
1067 kPortIndexInput, kPortIndexOutput);
1070 // test input/output port flush
1071 TEST_F(AudioDecHidlTest, FlushTest) {
1072 description("Test Flush");
1073 if (disableTest) return;
1074 android::hardware::media::omx::V1_0::Status status;
1075 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1076 status = setRole(omxNode, gEnv->getRole().c_str());
1077 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1078 OMX_PORT_PARAM_TYPE params;
1079 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
1080 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1081 ASSERT_EQ(params.nPorts, 2U);
1082 kPortIndexInput = params.nStartPortNumber;
1083 kPortIndexOutput = kPortIndexInput + 1;
1085 char mURL[512], info[512];
1086 strcpy(mURL, gEnv->getRes().c_str());
1087 strcpy(info, gEnv->getRes().c_str());
1088 GetURLForComponent(compName, mURL, info);
1090 std::ifstream eleStream, eleInfo;
1093 ASSERT_EQ(eleInfo.is_open(), true);
1094 android::Vector<FrameData> Info;
1097 uint32_t timestamp = 0;
1099 if (!(eleInfo >> bytesCount)) break;
1101 eleInfo >> timestamp;
1102 Info.push_back({bytesCount, flags, timestamp});
1106 int32_t nChannels, nSampleRate;
1107 // Configure input port
1108 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
1109 if (compName == raw)
1110 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
1111 OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
1113 getInputChannelInfo(omxNode, kPortIndexInput, eEncoding, &nChannels,
1115 // Configure output port
1116 // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
1117 // configure output PCM port. The port undergoes auto configuration
1118 // internally basing on parsed elementary stream information.
1119 if (compName != vorbis && compName != opus && compName != raw) {
1120 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
1121 nChannels, nSampleRate);
1124 android::Vector<BufferInfo> iBuffer, oBuffer;
1126 // set state to idle
1127 changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
1128 kPortIndexInput, kPortIndexOutput);
1129 // set state to executing
1130 changeStateIdletoExecute(omxNode, observer);
1132 // Decode 128 frames and flush. here 128 is chosen to ensure there is a key
1133 // frame after this so that the below section can be convered for all
1136 eleStream.open(mURL, std::ifstream::binary);
1137 ASSERT_EQ(eleStream.is_open(), true);
1138 decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
1139 kPortIndexInput, kPortIndexOutput, eleStream, &Info, 0,
1140 nFrames, compName, false);
1141 // Note: Assumes 200 ms is enough to end any decode call that started
1142 flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1143 kPortIndexOutput, 200000);
1146 // Seek to next key frame and start decoding till the end
1147 int index = nFrames;
1148 bool keyFrame = false;
1149 while (index < (int)Info.size()) {
1150 if ((Info[index].flags & OMX_BUFFERFLAG_SYNCFRAME) ==
1151 OMX_BUFFERFLAG_SYNCFRAME) {
1152 timestampUs = Info[index - 1].timestamp;
1156 eleStream.ignore(Info[index].bytesCount);
1160 decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
1161 kPortIndexInput, kPortIndexOutput, eleStream, &Info,
1162 index, Info.size() - index, compName, false);
1164 // Note: Assumes 200 ms is enough to end any decode call that started
1165 flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1166 kPortIndexOutput, 200000);
1169 // set state to idle
1170 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
1171 // set state to executing
1172 changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
1173 kPortIndexInput, kPortIndexOutput);
1176 int main(int argc, char** argv) {
1177 gEnv = new ComponentTestEnvironment();
1178 ::testing::AddGlobalTestEnvironment(gEnv);
1179 ::testing::InitGoogleTest(&argc, argv);
1180 int status = gEnv->initFromOptions(argc, argv);
1182 status = RUN_ALL_TESTS();
1183 ALOGI("Test result = %d", status);