[android/platform-hardware-interfaces.git] / media / omx / 1.0 / vts / functional / audio / VtsHalMediaOmxV1_0TargetAudioDecTest.cpp
1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
17 #define LOG_TAG "media_omx_hidl_audio_dec_test"
18 #ifdef __LP64__
19 #define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
20 #endif
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;
45 using ::android::sp;
47 #include <VtsHalHidlTargetTestBase.h>
48 #include <getopt.h>
49 #include <media_audio_hidl_test_common.h>
50 #include <media_hidl_test_common.h>
51 #include <fstream>
53 // A class for test environment setup
54 class ComponentTestEnvironment : public ::testing::Environment {
55 public:
56 virtual void SetUp() {}
57 virtual void TearDown() {}
59 ComponentTestEnvironment() : instance("default"), res("/sdcard/media/") {}
61 void setInstance(const char* _instance) { instance = _instance; }
63 void setComponent(const char* _component) { component = _component; }
65 void setRole(const char* _role) { role = _role; }
67 void setRes(const char* _res) { res = _res; }
69 const hidl_string getInstance() const { return instance; }
71 const hidl_string getComponent() const { return component; }
73 const hidl_string getRole() const { return role; }
75 const hidl_string getRes() const { return res; }
77 int initFromOptions(int argc, char** argv) {
78 static struct option options[] = {
79 {"instance", required_argument, 0, 'I'},
80 {"component", required_argument, 0, 'C'},
81 {"role", required_argument, 0, 'R'},
82 {"res", required_argument, 0, 'P'},
83 {0, 0, 0, 0}};
85 while (true) {
86 int index = 0;
87 int c = getopt_long(argc, argv, "I:C:R:P:", options, &index);
88 if (c == -1) {
89 break;
90 }
92 switch (c) {
93 case 'I':
94 setInstance(optarg);
95 break;
96 case 'C':
97 setComponent(optarg);
98 break;
99 case 'R':
100 setRole(optarg);
101 break;
102 case 'P':
103 setRes(optarg);
104 break;
105 case '?':
106 break;
107 }
108 }
110 if (optind < argc) {
111 fprintf(stderr,
112 "unrecognized option: %s\n\n"
113 "usage: %s <gtest options> <test options>\n\n"
114 "test options are:\n\n"
115 "-I, --instance: HAL instance to test\n"
116 "-C, --component: OMX component to test\n"
117 "-R, --role: OMX component Role\n"
118 "-P, --res: Resource files directory location\n",
119 argv[optind ?: 1], argv[0]);
120 return 2;
121 }
122 return 0;
123 }
125 private:
126 hidl_string instance;
127 hidl_string component;
128 hidl_string role;
129 hidl_string res;
130 };
132 static ComponentTestEnvironment* gEnv = nullptr;
134 // audio decoder test fixture class
135 class AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
136 private:
137 typedef ::testing::VtsHalHidlTargetTestBase Super;
138 public:
139 ::std::string getTestCaseInfo() const override {
140 return ::std::string() +
141 "Component: " + gEnv->getComponent().c_str() + " | " +
142 "Role: " + gEnv->getRole().c_str() + " | " +
143 "Instance: " + gEnv->getInstance().c_str() + " | " +
144 "Res: " + gEnv->getRes().c_str();
145 }
147 virtual void SetUp() override {
148 Super::SetUp();
149 disableTest = false;
150 android::hardware::media::omx::V1_0::Status status;
151 omx = Super::getService<IOmx>(gEnv->getInstance());
152 ASSERT_NE(omx, nullptr);
153 observer =
154 new CodecObserver([this](Message msg, const BufferInfo* buffer) {
155 handleMessage(msg, buffer);
156 });
157 ASSERT_NE(observer, nullptr);
158 if (strncmp(gEnv->getComponent().c_str(), "OMX.", 4) != 0)
159 disableTest = true;
160 EXPECT_TRUE(omx->allocateNode(
161 gEnv->getComponent(), observer,
162 [&](android::hardware::media::omx::V1_0::Status _s,
163 sp<IOmxNode> const& _nl) {
164 status = _s;
165 this->omxNode = _nl;
166 })
167 .isOk());
168 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
169 ASSERT_NE(omxNode, nullptr);
170 ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
171 struct StringToName {
172 const char* Name;
173 standardComp CompName;
174 };
175 const StringToName kStringToName[] = {
176 {"mp3", mp3}, {"amrnb", amrnb}, {"amrwb", amrwb},
177 {"aac", aac}, {"vorbis", vorbis}, {"opus", opus},
178 {"pcm", pcm}, {"g711alaw", g711alaw}, {"g711mlaw", g711mlaw},
179 {"gsm", gsm}, {"raw", raw}, {"flac", flac},
180 };
181 const size_t kNumStringToName =
182 sizeof(kStringToName) / sizeof(kStringToName[0]);
183 const char* pch;
184 char substring[OMX_MAX_STRINGNAME_SIZE];
185 strcpy(substring, gEnv->getRole().c_str());
186 pch = strchr(substring, '.');
187 ASSERT_NE(pch, nullptr);
188 compName = unknown_comp;
189 for (size_t i = 0; i < kNumStringToName; ++i) {
190 if (!strcasecmp(pch + 1, kStringToName[i].Name)) {
191 compName = kStringToName[i].CompName;
192 break;
193 }
194 }
195 if (compName == unknown_comp) disableTest = true;
196 struct CompToCoding {
197 standardComp CompName;
198 OMX_AUDIO_CODINGTYPE eEncoding;
199 };
200 static const CompToCoding kCompToCoding[] = {
201 {mp3, OMX_AUDIO_CodingMP3},
202 {amrnb, OMX_AUDIO_CodingAMR},
203 {amrwb, OMX_AUDIO_CodingAMR},
204 {aac, OMX_AUDIO_CodingAAC},
205 {vorbis, OMX_AUDIO_CodingVORBIS},
206 {pcm, OMX_AUDIO_CodingPCM},
207 {opus, (OMX_AUDIO_CODINGTYPE)OMX_AUDIO_CodingAndroidOPUS},
208 {g711alaw, OMX_AUDIO_CodingG711},
209 {g711mlaw, OMX_AUDIO_CodingG711},
210 {gsm, OMX_AUDIO_CodingGSMFR},
211 {raw, OMX_AUDIO_CodingPCM},
212 {flac, OMX_AUDIO_CodingFLAC},
213 };
214 static const size_t kNumCompToCoding =
215 sizeof(kCompToCoding) / sizeof(kCompToCoding[0]);
216 size_t i;
217 for (i = 0; i < kNumCompToCoding; ++i) {
218 if (kCompToCoding[i].CompName == compName) {
219 eEncoding = kCompToCoding[i].eEncoding;
220 break;
221 }
222 }
223 if (i == kNumCompToCoding) disableTest = true;
224 eosFlag = false;
225 framesReceived = 0;
226 timestampUs = 0;
227 timestampDevTest = false;
228 isSecure = false;
229 size_t suffixLen = strlen(".secure");
230 if (strlen(gEnv->getComponent().c_str()) >= suffixLen) {
231 isSecure =
232 !strcmp(gEnv->getComponent().c_str() +
233 strlen(gEnv->getComponent().c_str()) - suffixLen,
234 ".secure");
235 }
236 if (isSecure) disableTest = true;
237 if (disableTest) std::cout << "[ WARN ] Test Disabled \n";
238 }
240 virtual void TearDown() override {
241 if (omxNode != nullptr) {
242 // If you have encountered a fatal failure, it is possible that
243 // freeNode() will not go through. Instead of hanging the app.
244 // let it pass through and report errors
245 if (::testing::Test::HasFatalFailure()) return;
246 EXPECT_TRUE((omxNode->freeNode()).isOk());
247 omxNode = nullptr;
248 }
249 Super::TearDown();
250 }
252 // callback function to process messages received by onMessages() from IL
253 // client.
254 void handleMessage(Message msg, const BufferInfo* buffer) {
255 (void)buffer;
256 if (msg.type == Message::Type::FILL_BUFFER_DONE) {
257 if (msg.data.extendedBufferData.flags & OMX_BUFFERFLAG_EOS) {
258 eosFlag = true;
259 }
260 if (msg.data.extendedBufferData.rangeLength != 0) {
261 framesReceived += 1;
262 // For decoder components current timestamp always exceeds
263 // previous timestamp
264 EXPECT_GE(msg.data.extendedBufferData.timestampUs, timestampUs);
265 timestampUs = msg.data.extendedBufferData.timestampUs;
266 // Test if current timestamp is among the list of queued
267 // timestamps
268 if (timestampDevTest) {
269 bool tsHit = false;
270 android::List<uint64_t>::iterator it =
271 timestampUslist.begin();
272 while (it != timestampUslist.end()) {
273 if (*it == timestampUs) {
274 timestampUslist.erase(it);
275 tsHit = true;
276 break;
277 }
278 it++;
279 }
280 if (tsHit == false) {
281 if (timestampUslist.empty() == false) {
282 EXPECT_EQ(tsHit, true)
283 << "TimeStamp not recognized";
284 } else {
285 std::cout << "[ INFO ] Received non-zero "
286 "output / TimeStamp not recognized \n";
287 }
288 }
289 }
290 #define WRITE_OUTPUT 0
291 #if WRITE_OUTPUT
292 static int count = 0;
293 FILE* ofp = nullptr;
294 if (count)
295 ofp = fopen("out.bin", "ab");
296 else
297 ofp = fopen("out.bin", "wb");
298 if (ofp != nullptr) {
299 fwrite(static_cast<void*>(buffer->mMemory->getPointer()),
300 sizeof(char),
301 msg.data.extendedBufferData.rangeLength, ofp);
302 fclose(ofp);
303 count++;
304 }
305 #endif
306 }
307 }
308 }
310 enum standardComp {
311 mp3,
312 amrnb,
313 amrwb,
314 aac,
315 vorbis,
316 opus,
317 pcm,
318 g711alaw,
319 g711mlaw,
320 gsm,
321 raw,
322 flac,
323 unknown_comp,
324 };
326 sp<IOmx> omx;
327 sp<CodecObserver> observer;
328 sp<IOmxNode> omxNode;
329 standardComp compName;
330 OMX_AUDIO_CODINGTYPE eEncoding;
331 bool disableTest;
332 bool eosFlag;
333 bool isSecure;
334 uint32_t framesReceived;
335 uint64_t timestampUs;
336 ::android::List<uint64_t> timestampUslist;
337 bool timestampDevTest;
339 protected:
340 static void description(const std::string& description) {
341 RecordProperty("description", description);
342 }
343 };
345 // Set Default port param.
346 void setDefaultPortParam(
347 sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE eEncoding,
348 int32_t nChannels = 2, int32_t nSampleRate = 44100,
349 OMX_AUDIO_PCMMODETYPE ePCMMode = OMX_AUDIO_PCMModeLinear,
350 OMX_NUMERICALDATATYPE eNumData = OMX_NumericalDataSigned,
351 int32_t nBitPerSample = 16) {
352 android::hardware::media::omx::V1_0::Status status;
354 OMX_PARAM_PORTDEFINITIONTYPE portDef;
355 status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
356 &portDef);
357 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
359 portDef.format.audio.bFlagErrorConcealment = OMX_TRUE;
360 portDef.format.audio.eEncoding = eEncoding;
361 status = setPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
362 &portDef);
363 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
365 switch ((int)eEncoding) {
366 case OMX_AUDIO_CodingPCM:
367 setupPCMPort(omxNode, portIndex, nChannels, eNumData, nBitPerSample,
368 nSampleRate, ePCMMode);
369 break;
370 case OMX_AUDIO_CodingAAC:
371 setupAACPort(omxNode, portIndex, OMX_AUDIO_AACObjectNull,
372 OMX_AUDIO_AACStreamFormatMP4FF, nChannels, 0,
373 nSampleRate);
374 default:
375 break;
376 }
377 }
379 // In decoder components, often the input port parameters get updated upon
380 // parsing the header of elementary stream. Client needs to collect this
381 // information to reconfigure other ports that share data with this input
382 // port.
383 void getInputChannelInfo(sp<IOmxNode> omxNode, OMX_U32 kPortIndexInput,
384 OMX_AUDIO_CODINGTYPE eEncoding, int32_t* nChannels,
385 int32_t* nSampleRate) {
386 android::hardware::media::omx::V1_0::Status status;
387 *nChannels = 0;
388 *nSampleRate = 0;
390 switch ((int)eEncoding) {
391 case OMX_AUDIO_CodingGSMFR:
392 case OMX_AUDIO_CodingG711:
393 case OMX_AUDIO_CodingPCM: {
394 OMX_AUDIO_PARAM_PCMMODETYPE param;
395 status = getPortParam(omxNode, OMX_IndexParamAudioPcm,
396 kPortIndexInput, ¶m);
397 ASSERT_EQ(status,
398 ::android::hardware::media::omx::V1_0::Status::OK);
399 *nChannels = param.nChannels;
400 *nSampleRate = param.nSamplingRate;
401 break;
402 }
403 case OMX_AUDIO_CodingMP3: {
404 OMX_AUDIO_PARAM_MP3TYPE param;
405 status = getPortParam(omxNode, OMX_IndexParamAudioMp3,
406 kPortIndexInput, ¶m);
407 ASSERT_EQ(status,
408 ::android::hardware::media::omx::V1_0::Status::OK);
409 *nChannels = param.nChannels;
410 *nSampleRate = param.nSampleRate;
411 break;
412 }
413 case OMX_AUDIO_CodingAndroidOPUS: {
414 OMX_AUDIO_PARAM_ANDROID_OPUSTYPE param;
415 status = getPortParam(omxNode,
416 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
417 kPortIndexInput, ¶m);
418 ASSERT_EQ(status,
419 ::android::hardware::media::omx::V1_0::Status::OK);
420 *nChannels = param.nChannels;
421 *nSampleRate = param.nSampleRate;
422 break;
423 }
424 case OMX_AUDIO_CodingVORBIS: {
425 OMX_AUDIO_PARAM_VORBISTYPE param;
426 status = getPortParam(omxNode, OMX_IndexParamAudioVorbis,
427 kPortIndexInput, ¶m);
428 ASSERT_EQ(status,
429 ::android::hardware::media::omx::V1_0::Status::OK);
430 *nChannels = param.nChannels;
431 *nSampleRate = param.nSampleRate;
432 break;
433 }
434 case OMX_AUDIO_CodingAMR: {
435 OMX_AUDIO_PARAM_AMRTYPE param;
436 status = getPortParam(omxNode, OMX_IndexParamAudioAmr,
437 kPortIndexInput, ¶m);
438 ASSERT_EQ(status,
439 ::android::hardware::media::omx::V1_0::Status::OK);
440 *nChannels = param.nChannels;
441 // NOTE: For amrnb sample rate is 8k and amrwb sample rate is 16k.
442 // There is no nSampleRate field in OMX_AUDIO_PARAM_AMRTYPE. Just
443 // return 8k to avoid returning uninit variable.
444 *nSampleRate = 8000;
445 break;
446 }
447 case OMX_AUDIO_CodingAAC: {
448 OMX_AUDIO_PARAM_AACPROFILETYPE param;
449 status = getPortParam(omxNode, OMX_IndexParamAudioAac,
450 kPortIndexInput, ¶m);
451 ASSERT_EQ(status,
452 ::android::hardware::media::omx::V1_0::Status::OK);
453 *nChannels = param.nChannels;
454 *nSampleRate = param.nSampleRate;
455 break;
456 }
457 case OMX_AUDIO_CodingFLAC: {
458 OMX_AUDIO_PARAM_FLACTYPE param;
459 status = getPortParam(omxNode, OMX_IndexParamAudioFlac,
460 kPortIndexInput, ¶m);
461 ASSERT_EQ(status,
462 ::android::hardware::media::omx::V1_0::Status::OK);
463 *nChannels = param.nChannels;
464 *nSampleRate = param.nSampleRate;
465 break;
466 }
467 default:
468 ASSERT_TRUE(false);
469 break;
470 }
471 }
473 // LookUpTable of clips and metadata for component testing
474 void GetURLForComponent(AudioDecHidlTest::standardComp comp, char* mURL,
475 char* info) {
476 struct CompToURL {
477 AudioDecHidlTest::standardComp comp;
478 const char* mURL;
479 const char* info;
480 };
481 static const CompToURL kCompToURL[] = {
482 {AudioDecHidlTest::standardComp::mp3,
483 "bbb_mp3_stereo_192kbps_48000hz.mp3",
484 "bbb_mp3_stereo_192kbps_48000hz.info"},
485 {AudioDecHidlTest::standardComp::aac,
486 "bbb_aac_stereo_128kbps_48000hz.aac",
487 "bbb_aac_stereo_128kbps_48000hz.info"},
488 {AudioDecHidlTest::standardComp::amrnb,
489 "sine_amrnb_1ch_12kbps_8000hz.amrnb",
490 "sine_amrnb_1ch_12kbps_8000hz.info"},
491 {AudioDecHidlTest::standardComp::amrwb,
492 "bbb_amrwb_1ch_14kbps_16000hz.amrwb",
493 "bbb_amrwb_1ch_14kbps_16000hz.info"},
494 {AudioDecHidlTest::standardComp::vorbis,
495 "bbb_vorbis_stereo_128kbps_48000hz.vorbis",
496 "bbb_vorbis_stereo_128kbps_48000hz.info"},
497 {AudioDecHidlTest::standardComp::opus,
498 "bbb_opus_stereo_128kbps_48000hz.opus",
499 "bbb_opus_stereo_128kbps_48000hz.info"},
500 {AudioDecHidlTest::standardComp::g711alaw, "bbb_g711alaw_1ch_8khz.raw",
501 "bbb_g711alaw_1ch_8khz.info"},
502 {AudioDecHidlTest::standardComp::g711mlaw, "bbb_g711mulaw_1ch_8khz.raw",
503 "bbb_g711mulaw_1ch_8khz.info"},
504 {AudioDecHidlTest::standardComp::gsm, "bbb_gsm_1ch_8khz_13kbps.raw",
505 "bbb_gsm_1ch_8khz_13kbps.info"},
506 {AudioDecHidlTest::standardComp::raw, "bbb_raw_1ch_8khz_s32le.raw",
507 "bbb_raw_1ch_8khz_s32le.info"},
508 {AudioDecHidlTest::standardComp::flac,
509 "bbb_flac_stereo_680kbps_48000hz.flac",
510 "bbb_flac_stereo_680kbps_48000hz.info"},
511 };
513 for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
514 if (kCompToURL[i].comp == comp) {
515 strcat(mURL, kCompToURL[i].mURL);
516 strcat(info, kCompToURL[i].info);
517 return;
518 }
519 }
520 }
522 // port settings reconfiguration during runtime. reconfigures sample rate and
523 // number
524 typedef struct {
525 OMX_AUDIO_CODINGTYPE eEncoding;
526 AudioDecHidlTest::standardComp comp;
527 } packedArgs;
528 void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
529 android::Vector<BufferInfo>* iBuffer,
530 android::Vector<BufferInfo>* oBuffer,
531 OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
532 Message msg, PortMode oPortMode, void* args) {
533 android::hardware::media::omx::V1_0::Status status;
534 packedArgs* audioArgs = static_cast<packedArgs*>(args);
535 OMX_AUDIO_CODINGTYPE eEncoding = audioArgs->eEncoding;
536 AudioDecHidlTest::standardComp comp = audioArgs->comp;
537 (void)oPortMode;
539 if (msg.data.eventData.event == OMX_EventPortSettingsChanged) {
540 ASSERT_EQ(msg.data.eventData.data1, kPortIndexOutput);
542 status = omxNode->sendCommand(toRawCommandType(OMX_CommandPortDisable),
543 kPortIndexOutput);
544 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
546 status =
547 observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
548 if (status == android::hardware::media::omx::V1_0::Status::TIMED_OUT) {
549 for (size_t i = 0; i < oBuffer->size(); ++i) {
550 // test if client got all its buffers back
551 EXPECT_EQ((*oBuffer)[i].owner, client);
552 // free the buffers
553 status =
554 omxNode->freeBuffer(kPortIndexOutput, (*oBuffer)[i].id);
555 ASSERT_EQ(status,
556 android::hardware::media::omx::V1_0::Status::OK);
557 }
558 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer,
559 oBuffer);
560 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
561 ASSERT_EQ(msg.type, Message::Type::EVENT);
562 ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
563 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortDisable);
564 ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
566 // set Port Params
567 int32_t nChannels;
568 int32_t nSampleRate;
569 ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
570 omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
571 // Configure output port
572 // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way
573 // to configure output PCM port. The port undergoes auto
574 // configuration internally basing on parsed elementary stream
575 // information.
576 if (comp != AudioDecHidlTest::standardComp::vorbis &&
577 comp != AudioDecHidlTest::standardComp::opus &&
578 comp != AudioDecHidlTest::standardComp::raw) {
579 setDefaultPortParam(omxNode, kPortIndexOutput,
580 OMX_AUDIO_CodingPCM, nChannels,
581 nSampleRate);
582 }
584 // If you can disable a port, then you should be able to enable it
585 // as well
586 status = omxNode->sendCommand(
587 toRawCommandType(OMX_CommandPortEnable), kPortIndexOutput);
588 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
590 // do not enable the port until all the buffers are supplied
591 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer,
592 oBuffer);
593 ASSERT_EQ(status,
594 android::hardware::media::omx::V1_0::Status::TIMED_OUT);
596 ASSERT_NO_FATAL_FAILURE(
597 allocatePortBuffers(omxNode, oBuffer, kPortIndexOutput));
598 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer,
599 oBuffer);
600 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
601 ASSERT_EQ(msg.type, Message::Type::EVENT);
602 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortEnable);
603 ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
605 // dispatch output buffers
606 for (size_t i = 0; i < oBuffer->size(); i++) {
607 ASSERT_NO_FATAL_FAILURE(
608 dispatchOutputBuffer(omxNode, oBuffer, i));
609 }
610 } else {
611 ASSERT_TRUE(false);
612 }
613 } else {
614 ASSERT_TRUE(false);
615 }
616 }
618 // blocking call to ensures application to Wait till all the inputs are consumed
619 void waitOnInputConsumption(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
620 android::Vector<BufferInfo>* iBuffer,
621 android::Vector<BufferInfo>* oBuffer,
622 OMX_AUDIO_CODINGTYPE eEncoding,
623 OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
624 AudioDecHidlTest::standardComp comp) {
625 android::hardware::media::omx::V1_0::Status status;
626 Message msg;
627 int timeOut = TIMEOUT_COUNTER_Q;
629 while (timeOut--) {
630 size_t i = 0;
631 status =
632 observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
633 if (status == android::hardware::media::omx::V1_0::Status::OK) {
634 ASSERT_EQ(msg.type, Message::Type::EVENT);
635 packedArgs audioArgs = {eEncoding, comp};
636 ASSERT_NO_FATAL_FAILURE(
637 portReconfiguration(omxNode, observer, iBuffer, oBuffer,
638 kPortIndexInput, kPortIndexOutput, msg,
639 PortMode::PRESET_BYTE_BUFFER, &audioArgs));
640 }
641 // status == TIMED_OUT, it could be due to process time being large
642 // than DEFAULT_TIMEOUT or component needs output buffers to start
643 // processing.
644 for (; i < iBuffer->size(); i++) {
645 if ((*iBuffer)[i].owner != client) break;
646 }
647 if (i == iBuffer->size()) break;
649 // Dispatch an output buffer assuming outQueue.empty() is true
650 size_t index;
651 if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
652 ASSERT_NO_FATAL_FAILURE(
653 dispatchOutputBuffer(omxNode, oBuffer, index));
654 timeOut = TIMEOUT_COUNTER_Q;
655 }
656 }
657 }
659 // Decode N Frames
660 void decodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
661 android::Vector<BufferInfo>* iBuffer,
662 android::Vector<BufferInfo>* oBuffer,
663 OMX_AUDIO_CODINGTYPE eEncoding, OMX_U32 kPortIndexInput,
664 OMX_U32 kPortIndexOutput, std::ifstream& eleStream,
665 android::Vector<FrameData>* Info, int offset, int range,
666 AudioDecHidlTest::standardComp comp, bool signalEOS = true) {
667 android::hardware::media::omx::V1_0::Status status;
668 Message msg;
669 size_t index;
670 uint32_t flags = 0;
671 int frameID = offset;
672 int timeOut = TIMEOUT_COUNTER_Q;
673 bool iQueued, oQueued;
675 while (1) {
676 iQueued = oQueued = false;
677 status =
678 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 packedArgs audioArgs = {eEncoding, comp};
683 ASSERT_NO_FATAL_FAILURE(
684 portReconfiguration(omxNode, observer, iBuffer, oBuffer,
685 kPortIndexInput, kPortIndexOutput, msg,
686 PortMode::PRESET_BYTE_BUFFER, &audioArgs));
687 }
689 if (frameID == (int)Info->size() || frameID == (offset + range)) break;
691 // Dispatch input buffer
692 if ((index = getEmptyBufferID(iBuffer)) < iBuffer->size()) {
693 char* ipBuffer = static_cast<char*>(
694 static_cast<void*>((*iBuffer)[index].mMemory->getPointer()));
695 ASSERT_LE((*Info)[frameID].bytesCount,
696 static_cast<int>((*iBuffer)[index].mMemory->getSize()));
697 eleStream.read(ipBuffer, (*Info)[frameID].bytesCount);
698 ASSERT_EQ(eleStream.gcount(), (*Info)[frameID].bytesCount);
699 flags = (*Info)[frameID].flags;
700 // Indicate to omx core that the buffer contains a full frame worth
701 // of data
702 flags |= OMX_BUFFERFLAG_ENDOFFRAME;
703 // Indicate the omx core that this is the last buffer it needs to
704 // process
705 if (signalEOS && ((frameID == (int)Info->size() - 1) ||
706 (frameID == (offset + range - 1))))
707 flags |= OMX_BUFFERFLAG_EOS;
708 ASSERT_NO_FATAL_FAILURE(dispatchInputBuffer(
709 omxNode, iBuffer, index, (*Info)[frameID].bytesCount, flags,
710 (*Info)[frameID].timestamp));
711 frameID++;
712 iQueued = true;
713 }
714 // Dispatch output buffer
715 if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
716 ASSERT_NO_FATAL_FAILURE(
717 dispatchOutputBuffer(omxNode, oBuffer, index));
718 oQueued = true;
719 }
720 // Reset Counters when either input or output buffer is dispatched
721 if (iQueued || oQueued)
722 timeOut = TIMEOUT_COUNTER_Q;
723 else
724 timeOut--;
725 if (timeOut == 0) {
726 ASSERT_TRUE(false) << "Wait on Input/Output is found indefinite";
727 }
728 }
729 }
731 // set component role
732 TEST_F(AudioDecHidlTest, SetRole) {
733 description("Test Set Component Role");
734 if (disableTest) return;
735 android::hardware::media::omx::V1_0::Status status;
736 status = setRole(omxNode, gEnv->getRole().c_str());
737 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
738 }
740 // port format enumeration
741 TEST_F(AudioDecHidlTest, EnumeratePortFormat) {
742 description("Test Component on Mandatory Port Parameters (Port Format)");
743 if (disableTest) return;
744 android::hardware::media::omx::V1_0::Status status;
745 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
746 status = setRole(omxNode, gEnv->getRole().c_str());
747 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
748 OMX_PORT_PARAM_TYPE params;
749 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
750 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
751 ASSERT_EQ(params.nPorts, 2U);
752 kPortIndexInput = params.nStartPortNumber;
753 kPortIndexOutput = kPortIndexInput + 1;
754 }
755 status = setAudioPortFormat(omxNode, kPortIndexInput, eEncoding);
756 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
757 status = setAudioPortFormat(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM);
758 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
759 }
761 // test port settings reconfiguration, elementary stream decode and timestamp
762 // deviation
763 TEST_F(AudioDecHidlTest, DecodeTest) {
764 description("Tests Port Reconfiguration, Decode and timestamp deviation");
765 if (disableTest) return;
766 android::hardware::media::omx::V1_0::Status status;
767 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
768 status = setRole(omxNode, gEnv->getRole().c_str());
769 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
770 OMX_PORT_PARAM_TYPE params;
771 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
772 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
773 ASSERT_EQ(params.nPorts, 2U);
774 kPortIndexInput = params.nStartPortNumber;
775 kPortIndexOutput = kPortIndexInput + 1;
776 }
777 char mURL[512], info[512];
778 strcpy(mURL, gEnv->getRes().c_str());
779 strcpy(info, gEnv->getRes().c_str());
780 GetURLForComponent(compName, mURL, info);
782 std::ifstream eleStream, eleInfo;
784 eleInfo.open(info);
785 ASSERT_EQ(eleInfo.is_open(), true);
786 android::Vector<FrameData> Info;
787 int bytesCount = 0;
788 uint32_t flags = 0;
789 uint32_t timestamp = 0;
790 timestampDevTest = false;
791 while (1) {
792 if (!(eleInfo >> bytesCount)) break;
793 eleInfo >> flags;
794 eleInfo >> timestamp;
795 Info.push_back({bytesCount, flags, timestamp});
796 if (timestampDevTest && (flags != OMX_BUFFERFLAG_CODECCONFIG))
797 timestampUslist.push_back(timestamp);
798 }
799 eleInfo.close();
801 int32_t nChannels, nSampleRate;
802 // Configure input port
803 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
804 if (compName == raw)
805 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
806 OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
807 32);
808 ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
809 omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
810 // Configure output port
811 // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
812 // configure output PCM port. The port undergoes auto configuration
813 // internally basing on parsed elementary stream information.
814 if (compName != vorbis && compName != opus && compName != raw) {
815 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
816 nChannels, nSampleRate);
817 }
819 android::Vector<BufferInfo> iBuffer, oBuffer;
821 // set state to idle
822 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(omxNode, observer, &iBuffer,
823 &oBuffer, kPortIndexInput,
824 kPortIndexOutput));
825 // set state to executing
826 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
827 // Port Reconfiguration
828 eleStream.open(mURL, std::ifstream::binary);
829 ASSERT_EQ(eleStream.is_open(), true);
830 ASSERT_NO_FATAL_FAILURE(decodeNFrames(
831 omxNode, observer, &iBuffer, &oBuffer, eEncoding, kPortIndexInput,
832 kPortIndexOutput, eleStream, &Info, 0, (int)Info.size(), compName));
833 eleStream.close();
834 ASSERT_NO_FATAL_FAILURE(
835 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
836 kPortIndexInput, kPortIndexOutput, compName));
837 packedArgs audioArgs = {eEncoding, compName};
838 ASSERT_NO_FATAL_FAILURE(testEOS(
839 omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, nullptr,
840 portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs));
841 if (timestampDevTest) EXPECT_EQ(timestampUslist.empty(), true);
842 // set state to idle
843 ASSERT_NO_FATAL_FAILURE(
844 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
845 // set state to executing
846 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
847 &oBuffer, kPortIndexInput,
848 kPortIndexOutput));
849 }
851 // end of sequence test
852 TEST_F(AudioDecHidlTest, EOSTest_M) {
853 description("Test end of stream monkeying");
854 if (disableTest) return;
855 android::hardware::media::omx::V1_0::Status status;
856 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
857 status = setRole(omxNode, gEnv->getRole().c_str());
858 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
859 OMX_PORT_PARAM_TYPE params;
860 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
861 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
862 ASSERT_EQ(params.nPorts, 2U);
863 kPortIndexInput = params.nStartPortNumber;
864 kPortIndexOutput = kPortIndexInput + 1;
865 }
867 int32_t nChannels, nSampleRate;
868 // Configure input port
869 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
870 if (compName == raw)
871 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
872 OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
873 32);
874 ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
875 omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
876 // Configure output port
877 // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
878 // configure output PCM port. The port undergoes auto configuration
879 // internally basing on parsed elementary stream information.
880 if (compName != vorbis && compName != opus && compName != raw) {
881 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
882 nChannels, nSampleRate);
883 }
885 android::Vector<BufferInfo> iBuffer, oBuffer;
887 // set state to idle
888 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(omxNode, observer, &iBuffer,
889 &oBuffer, kPortIndexInput,
890 kPortIndexOutput));
891 // set state to executing
892 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
894 // request EOS at the start
895 packedArgs audioArgs = {eEncoding, compName};
896 ASSERT_NO_FATAL_FAILURE(testEOS(
897 omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, nullptr,
898 portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs));
899 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
900 kPortIndexInput, kPortIndexOutput));
901 EXPECT_GE(framesReceived, 0U);
902 framesReceived = 0;
903 timestampUs = 0;
905 // set state to idle
906 ASSERT_NO_FATAL_FAILURE(
907 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
909 // set state to executing
910 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
911 &oBuffer, kPortIndexInput,
912 kPortIndexOutput));
913 }
915 // end of sequence test
916 TEST_F(AudioDecHidlTest, ThumbnailTest) {
917 description("Test Request for thumbnail");
918 if (disableTest) return;
919 android::hardware::media::omx::V1_0::Status status;
920 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
921 status = setRole(omxNode, gEnv->getRole().c_str());
922 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
923 OMX_PORT_PARAM_TYPE params;
924 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
925 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
926 ASSERT_EQ(params.nPorts, 2U);
927 kPortIndexInput = params.nStartPortNumber;
928 kPortIndexOutput = kPortIndexInput + 1;
929 }
930 char mURL[512], info[512];
931 strcpy(mURL, gEnv->getRes().c_str());
932 strcpy(info, gEnv->getRes().c_str());
933 GetURLForComponent(compName, mURL, info);
935 std::ifstream eleStream, eleInfo;
937 eleInfo.open(info);
938 ASSERT_EQ(eleInfo.is_open(), true);
939 android::Vector<FrameData> Info;
940 int bytesCount = 0;
941 uint32_t flags = 0;
942 uint32_t timestamp = 0;
943 while (1) {
944 if (!(eleInfo >> bytesCount)) break;
945 eleInfo >> flags;
946 eleInfo >> timestamp;
947 Info.push_back({bytesCount, flags, timestamp});
948 }
949 eleInfo.close();
951 int32_t nChannels, nSampleRate;
952 // Configure input port
953 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
954 if (compName == raw)
955 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
956 OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
957 32);
958 ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
959 omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
960 // Configure output port
961 // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
962 // configure output PCM port. The port undergoes auto configuration
963 // internally basing on parsed elementary stream information.
964 if (compName != vorbis && compName != opus && compName != raw) {
965 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
966 nChannels, nSampleRate);
967 }
969 android::Vector<BufferInfo> iBuffer, oBuffer;
971 // set state to idle
972 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(omxNode, observer, &iBuffer,
973 &oBuffer, kPortIndexInput,
974 kPortIndexOutput));
975 // set state to executing
976 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
978 // request EOS for thumbnail
979 // signal EOS flag with last frame
980 size_t i = 0;
981 while (!(Info[i].flags & OMX_BUFFERFLAG_SYNCFRAME)) i++;
982 eleStream.open(mURL, std::ifstream::binary);
983 ASSERT_EQ(eleStream.is_open(), true);
984 ASSERT_NO_FATAL_FAILURE(decodeNFrames(
985 omxNode, observer, &iBuffer, &oBuffer, eEncoding, kPortIndexInput,
986 kPortIndexOutput, eleStream, &Info, 0, i + 1, compName));
987 eleStream.close();
988 ASSERT_NO_FATAL_FAILURE(
989 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
990 kPortIndexInput, kPortIndexOutput, compName));
991 packedArgs audioArgs = {eEncoding, compName};
992 ASSERT_NO_FATAL_FAILURE(testEOS(
993 omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, nullptr,
994 portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs));
995 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
996 kPortIndexInput, kPortIndexOutput));
997 EXPECT_GE(framesReceived, 1U);
998 framesReceived = 0;
999 timestampUs = 0;
1001 // signal EOS flag after last frame
1002 eleStream.open(mURL, std::ifstream::binary);
1003 ASSERT_EQ(eleStream.is_open(), true);
1004 ASSERT_NO_FATAL_FAILURE(decodeNFrames(
1005 omxNode, observer, &iBuffer, &oBuffer, eEncoding, kPortIndexInput,
1006 kPortIndexOutput, eleStream, &Info, 0, i + 1, compName, false));
1007 eleStream.close();
1008 ASSERT_NO_FATAL_FAILURE(
1009 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
1010 kPortIndexInput, kPortIndexOutput, compName));
1011 ASSERT_NO_FATAL_FAILURE(testEOS(
1012 omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, nullptr,
1013 portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs));
1014 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
1015 kPortIndexInput, kPortIndexOutput));
1016 EXPECT_GE(framesReceived, 1U);
1017 framesReceived = 0;
1018 timestampUs = 0;
1020 // set state to idle
1021 ASSERT_NO_FATAL_FAILURE(
1022 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
1023 // set state to executing
1024 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
1025 &oBuffer, kPortIndexInput,
1026 kPortIndexOutput));
1027 }
1029 // end of sequence test
1030 TEST_F(AudioDecHidlTest, SimpleEOSTest) {
1031 description("Test end of stream");
1032 if (disableTest) return;
1033 android::hardware::media::omx::V1_0::Status status;
1034 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1035 status = setRole(omxNode, gEnv->getRole().c_str());
1036 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1037 OMX_PORT_PARAM_TYPE params;
1038 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
1039 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1040 ASSERT_EQ(params.nPorts, 2U);
1041 kPortIndexInput = params.nStartPortNumber;
1042 kPortIndexOutput = kPortIndexInput + 1;
1043 }
1044 char mURL[512], info[512];
1045 strcpy(mURL, gEnv->getRes().c_str());
1046 strcpy(info, gEnv->getRes().c_str());
1047 GetURLForComponent(compName, mURL, info);
1049 std::ifstream eleStream, eleInfo;
1051 eleInfo.open(info);
1052 ASSERT_EQ(eleInfo.is_open(), true);
1053 android::Vector<FrameData> Info;
1054 int bytesCount = 0;
1055 uint32_t flags = 0;
1056 uint32_t timestamp = 0;
1057 while (1) {
1058 if (!(eleInfo >> bytesCount)) break;
1059 eleInfo >> flags;
1060 eleInfo >> timestamp;
1061 Info.push_back({bytesCount, flags, timestamp});
1062 }
1063 eleInfo.close();
1065 int32_t nChannels, nSampleRate;
1066 // Configure input port
1067 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
1068 if (compName == raw)
1069 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
1070 OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
1071 32);
1072 ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
1073 omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
1074 // Configure output port
1075 // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
1076 // configure output PCM port. The port undergoes auto configuration
1077 // internally basing on parsed elementary stream information.
1078 if (compName != vorbis && compName != opus && compName != raw) {
1079 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
1080 nChannels, nSampleRate);
1081 }
1083 android::Vector<BufferInfo> iBuffer, oBuffer;
1085 // set state to idle
1086 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(omxNode, observer, &iBuffer,
1087 &oBuffer, kPortIndexInput,
1088 kPortIndexOutput));
1089 // set state to executing
1090 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
1092 // request EOS at the end
1093 eleStream.open(mURL, std::ifstream::binary);
1094 ASSERT_EQ(eleStream.is_open(), true);
1095 ASSERT_NO_FATAL_FAILURE(decodeNFrames(omxNode, observer, &iBuffer, &oBuffer,
1096 eEncoding, kPortIndexInput,
1097 kPortIndexOutput, eleStream, &Info, 0,
1098 (int)Info.size(), compName, false));
1099 eleStream.close();
1100 ASSERT_NO_FATAL_FAILURE(
1101 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
1102 kPortIndexInput, kPortIndexOutput, compName));
1103 packedArgs audioArgs = {eEncoding, compName};
1104 ASSERT_NO_FATAL_FAILURE(testEOS(
1105 omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, nullptr,
1106 portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs));
1107 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
1108 kPortIndexInput, kPortIndexOutput));
1109 framesReceived = 0;
1110 timestampUs = 0;
1112 // set state to idle
1113 ASSERT_NO_FATAL_FAILURE(
1114 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
1115 // set state to executing
1116 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
1117 &oBuffer, kPortIndexInput,
1118 kPortIndexOutput));
1119 }
1121 // test input/output port flush
1122 TEST_F(AudioDecHidlTest, FlushTest) {
1123 description("Test Flush");
1124 if (disableTest) return;
1125 android::hardware::media::omx::V1_0::Status status;
1126 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1127 status = setRole(omxNode, gEnv->getRole().c_str());
1128 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1129 OMX_PORT_PARAM_TYPE params;
1130 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
1131 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1132 ASSERT_EQ(params.nPorts, 2U);
1133 kPortIndexInput = params.nStartPortNumber;
1134 kPortIndexOutput = kPortIndexInput + 1;
1135 }
1136 char mURL[512], info[512];
1137 strcpy(mURL, gEnv->getRes().c_str());
1138 strcpy(info, gEnv->getRes().c_str());
1139 GetURLForComponent(compName, mURL, info);
1141 std::ifstream eleStream, eleInfo;
1143 eleInfo.open(info);
1144 ASSERT_EQ(eleInfo.is_open(), true);
1145 android::Vector<FrameData> Info;
1146 int bytesCount = 0;
1147 uint32_t flags = 0;
1148 uint32_t timestamp = 0;
1149 while (1) {
1150 if (!(eleInfo >> bytesCount)) break;
1151 eleInfo >> flags;
1152 eleInfo >> timestamp;
1153 Info.push_back({bytesCount, flags, timestamp});
1154 }
1155 eleInfo.close();
1157 int32_t nChannels, nSampleRate;
1158 // Configure input port
1159 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
1160 if (compName == raw)
1161 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
1162 OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
1163 32);
1164 ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
1165 omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
1166 // Configure output port
1167 // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
1168 // configure output PCM port. The port undergoes auto configuration
1169 // internally basing on parsed elementary stream information.
1170 if (compName != vorbis && compName != opus && compName != raw) {
1171 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
1172 nChannels, nSampleRate);
1173 }
1175 android::Vector<BufferInfo> iBuffer, oBuffer;
1177 // set state to idle
1178 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(omxNode, observer, &iBuffer,
1179 &oBuffer, kPortIndexInput,
1180 kPortIndexOutput));
1181 // set state to executing
1182 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
1184 // Decode 128 frames and flush. here 128 is chosen to ensure there is a key
1185 // frame after this so that the below section can be convered for all
1186 // components
1187 int nFrames = 128;
1188 eleStream.open(mURL, std::ifstream::binary);
1189 ASSERT_EQ(eleStream.is_open(), true);
1190 ASSERT_NO_FATAL_FAILURE(decodeNFrames(
1191 omxNode, observer, &iBuffer, &oBuffer, eEncoding, kPortIndexInput,
1192 kPortIndexOutput, eleStream, &Info, 0, nFrames, compName, false));
1193 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
1194 kPortIndexInput, kPortIndexOutput));
1195 framesReceived = 0;
1197 // Seek to next key frame and start decoding till the end
1198 int index = nFrames;
1199 bool keyFrame = false;
1200 while (index < (int)Info.size()) {
1201 if ((Info[index].flags & OMX_BUFFERFLAG_SYNCFRAME) ==
1202 OMX_BUFFERFLAG_SYNCFRAME) {
1203 timestampUs = Info[index - 1].timestamp;
1204 keyFrame = true;
1205 break;
1206 }
1207 eleStream.ignore(Info[index].bytesCount);
1208 index++;
1209 }
1210 if (keyFrame) {
1211 ASSERT_NO_FATAL_FAILURE(
1212 decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
1213 kPortIndexInput, kPortIndexOutput, eleStream, &Info,
1214 index, Info.size() - index, compName, false));
1215 }
1216 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
1217 kPortIndexInput, kPortIndexOutput));
1218 framesReceived = 0;
1220 // set state to idle
1221 ASSERT_NO_FATAL_FAILURE(
1222 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
1223 // set state to executing
1224 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
1225 &oBuffer, kPortIndexInput,
1226 kPortIndexOutput));
1227 }
1229 int main(int argc, char** argv) {
1230 gEnv = new ComponentTestEnvironment();
1231 ::testing::AddGlobalTestEnvironment(gEnv);
1232 ::testing::InitGoogleTest(&argc, argv);
1233 int status = gEnv->initFromOptions(argc, argv);
1234 if (status == 0) {
1235 status = RUN_ALL_TESTS();
1236 ALOGI("Test result = %d", status);
1237 }
1238 return status;
1239 }