[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 if (disableTest) std::cout << "[ WARN ] Test Disabled \n";
229 }
231 virtual void TearDown() override {
232 if (omxNode != nullptr) {
233 // If you have encountered a fatal failure, it is possible that
234 // freeNode() will not go through. Instead of hanging the app.
235 // let it pass through and report errors
236 if (::testing::Test::HasFatalFailure()) return;
237 EXPECT_TRUE((omxNode->freeNode()).isOk());
238 omxNode = nullptr;
239 }
240 Super::TearDown();
241 }
243 // callback function to process messages received by onMessages() from IL
244 // client.
245 void handleMessage(Message msg, const BufferInfo* buffer) {
246 (void)buffer;
247 if (msg.type == Message::Type::FILL_BUFFER_DONE) {
248 if (msg.data.extendedBufferData.flags & OMX_BUFFERFLAG_EOS) {
249 eosFlag = true;
250 }
251 if (msg.data.extendedBufferData.rangeLength != 0) {
252 framesReceived += 1;
253 // For decoder components current timestamp always exceeds
254 // previous timestamp
255 EXPECT_GE(msg.data.extendedBufferData.timestampUs, timestampUs);
256 timestampUs = msg.data.extendedBufferData.timestampUs;
257 // Test if current timestamp is among the list of queued
258 // timestamps
259 if (timestampDevTest) {
260 bool tsHit = false;
261 android::List<uint64_t>::iterator it =
262 timestampUslist.begin();
263 while (it != timestampUslist.end()) {
264 if (*it == timestampUs) {
265 timestampUslist.erase(it);
266 tsHit = true;
267 break;
268 }
269 it++;
270 }
271 if (tsHit == false) {
272 if (timestampUslist.empty() == false) {
273 EXPECT_EQ(tsHit, true)
274 << "TimeStamp not recognized";
275 } else {
276 std::cout << "[ INFO ] Received non-zero "
277 "output / TimeStamp not recognized \n";
278 }
279 }
280 }
281 #define WRITE_OUTPUT 0
282 #if WRITE_OUTPUT
283 static int count = 0;
284 FILE* ofp = nullptr;
285 if (count)
286 ofp = fopen("out.bin", "ab");
287 else
288 ofp = fopen("out.bin", "wb");
289 if (ofp != nullptr) {
290 fwrite(static_cast<void*>(buffer->mMemory->getPointer()),
291 sizeof(char),
292 msg.data.extendedBufferData.rangeLength, ofp);
293 fclose(ofp);
294 count++;
295 }
296 #endif
297 }
298 }
299 }
301 enum standardComp {
302 mp3,
303 amrnb,
304 amrwb,
305 aac,
306 vorbis,
307 opus,
308 pcm,
309 g711alaw,
310 g711mlaw,
311 gsm,
312 raw,
313 flac,
314 unknown_comp,
315 };
317 sp<IOmx> omx;
318 sp<CodecObserver> observer;
319 sp<IOmxNode> omxNode;
320 standardComp compName;
321 OMX_AUDIO_CODINGTYPE eEncoding;
322 bool disableTest;
323 bool eosFlag;
324 uint32_t framesReceived;
325 uint64_t timestampUs;
326 ::android::List<uint64_t> timestampUslist;
327 bool timestampDevTest;
329 protected:
330 static void description(const std::string& description) {
331 RecordProperty("description", description);
332 }
333 };
335 // Set Default port param.
336 void setDefaultPortParam(
337 sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE eEncoding,
338 int32_t nChannels = 2, int32_t nSampleRate = 44100,
339 OMX_AUDIO_PCMMODETYPE ePCMMode = OMX_AUDIO_PCMModeLinear,
340 OMX_NUMERICALDATATYPE eNumData = OMX_NumericalDataSigned,
341 int32_t nBitPerSample = 16) {
342 android::hardware::media::omx::V1_0::Status status;
344 OMX_PARAM_PORTDEFINITIONTYPE portDef;
345 status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
346 &portDef);
347 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
349 portDef.format.audio.bFlagErrorConcealment = OMX_TRUE;
350 portDef.format.audio.eEncoding = eEncoding;
351 status = setPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
352 &portDef);
353 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
355 switch ((int)eEncoding) {
356 case OMX_AUDIO_CodingPCM:
357 setupPCMPort(omxNode, portIndex, nChannels, eNumData, nBitPerSample,
358 nSampleRate, ePCMMode);
359 break;
360 case OMX_AUDIO_CodingAAC:
361 setupAACPort(omxNode, portIndex, OMX_AUDIO_AACObjectNull,
362 OMX_AUDIO_AACStreamFormatMP4FF, nChannels, 0,
363 nSampleRate);
364 default:
365 break;
366 }
367 }
369 // In decoder components, often the input port parameters get updated upon
370 // parsing the header of elementary stream. Client needs to collect this
371 // information to reconfigure other ports that share data with this input
372 // port.
373 void getInputChannelInfo(sp<IOmxNode> omxNode, OMX_U32 kPortIndexInput,
374 OMX_AUDIO_CODINGTYPE eEncoding, int32_t* nChannels,
375 int32_t* nSampleRate) {
376 android::hardware::media::omx::V1_0::Status status;
377 *nChannels = 0;
378 *nSampleRate = 0;
380 switch ((int)eEncoding) {
381 case OMX_AUDIO_CodingGSMFR:
382 case OMX_AUDIO_CodingG711:
383 case OMX_AUDIO_CodingPCM: {
384 OMX_AUDIO_PARAM_PCMMODETYPE param;
385 status = getPortParam(omxNode, OMX_IndexParamAudioPcm,
386 kPortIndexInput, ¶m);
387 ASSERT_EQ(status,
388 ::android::hardware::media::omx::V1_0::Status::OK);
389 *nChannels = param.nChannels;
390 *nSampleRate = param.nSamplingRate;
391 break;
392 }
393 case OMX_AUDIO_CodingMP3: {
394 OMX_AUDIO_PARAM_MP3TYPE param;
395 status = getPortParam(omxNode, OMX_IndexParamAudioMp3,
396 kPortIndexInput, ¶m);
397 ASSERT_EQ(status,
398 ::android::hardware::media::omx::V1_0::Status::OK);
399 *nChannels = param.nChannels;
400 *nSampleRate = param.nSampleRate;
401 break;
402 }
403 case OMX_AUDIO_CodingAndroidOPUS: {
404 OMX_AUDIO_PARAM_ANDROID_OPUSTYPE param;
405 status = getPortParam(omxNode,
406 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
407 kPortIndexInput, ¶m);
408 ASSERT_EQ(status,
409 ::android::hardware::media::omx::V1_0::Status::OK);
410 *nChannels = param.nChannels;
411 *nSampleRate = param.nSampleRate;
412 break;
413 }
414 case OMX_AUDIO_CodingVORBIS: {
415 OMX_AUDIO_PARAM_VORBISTYPE param;
416 status = getPortParam(omxNode, OMX_IndexParamAudioVorbis,
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_CodingAMR: {
425 OMX_AUDIO_PARAM_AMRTYPE param;
426 status = getPortParam(omxNode, OMX_IndexParamAudioAmr,
427 kPortIndexInput, ¶m);
428 ASSERT_EQ(status,
429 ::android::hardware::media::omx::V1_0::Status::OK);
430 *nChannels = param.nChannels;
431 // NOTE: For amrnb sample rate is 8k and amrwb sample rate is 16k.
432 // There is no nSampleRate field in OMX_AUDIO_PARAM_AMRTYPE. Just
433 // return 8k to avoid returning uninit variable.
434 *nSampleRate = 8000;
435 break;
436 }
437 case OMX_AUDIO_CodingAAC: {
438 OMX_AUDIO_PARAM_AACPROFILETYPE param;
439 status = getPortParam(omxNode, OMX_IndexParamAudioAac,
440 kPortIndexInput, ¶m);
441 ASSERT_EQ(status,
442 ::android::hardware::media::omx::V1_0::Status::OK);
443 *nChannels = param.nChannels;
444 *nSampleRate = param.nSampleRate;
445 break;
446 }
447 case OMX_AUDIO_CodingFLAC: {
448 OMX_AUDIO_PARAM_FLACTYPE param;
449 status = getPortParam(omxNode, OMX_IndexParamAudioFlac,
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 default:
458 ASSERT_TRUE(false);
459 break;
460 }
461 }
463 // LookUpTable of clips and metadata for component testing
464 void GetURLForComponent(AudioDecHidlTest::standardComp comp, char* mURL,
465 char* info) {
466 struct CompToURL {
467 AudioDecHidlTest::standardComp comp;
468 const char* mURL;
469 const char* info;
470 };
471 static const CompToURL kCompToURL[] = {
472 {AudioDecHidlTest::standardComp::mp3,
473 "bbb_mp3_stereo_192kbps_48000hz.mp3",
474 "bbb_mp3_stereo_192kbps_48000hz.info"},
475 {AudioDecHidlTest::standardComp::aac,
476 "bbb_aac_stereo_128kbps_48000hz.aac",
477 "bbb_aac_stereo_128kbps_48000hz.info"},
478 {AudioDecHidlTest::standardComp::amrnb,
479 "sine_amrnb_1ch_12kbps_8000hz.amrnb",
480 "sine_amrnb_1ch_12kbps_8000hz.info"},
481 {AudioDecHidlTest::standardComp::amrwb,
482 "bbb_amrwb_1ch_14kbps_16000hz.amrwb",
483 "bbb_amrwb_1ch_14kbps_16000hz.info"},
484 {AudioDecHidlTest::standardComp::vorbis,
485 "bbb_vorbis_stereo_128kbps_48000hz.vorbis",
486 "bbb_vorbis_stereo_128kbps_48000hz.info"},
487 {AudioDecHidlTest::standardComp::opus,
488 "bbb_opus_stereo_128kbps_48000hz.opus",
489 "bbb_opus_stereo_128kbps_48000hz.info"},
490 {AudioDecHidlTest::standardComp::g711alaw, "bbb_g711alaw_1ch_8khz.raw",
491 "bbb_g711alaw_1ch_8khz.info"},
492 {AudioDecHidlTest::standardComp::g711mlaw, "bbb_g711mulaw_1ch_8khz.raw",
493 "bbb_g711mulaw_1ch_8khz.info"},
494 {AudioDecHidlTest::standardComp::gsm, "bbb_gsm_1ch_8khz_13kbps.raw",
495 "bbb_gsm_1ch_8khz_13kbps.info"},
496 {AudioDecHidlTest::standardComp::raw, "bbb_raw_1ch_8khz_s32le.raw",
497 "bbb_raw_1ch_8khz_s32le.info"},
498 {AudioDecHidlTest::standardComp::flac,
499 "bbb_flac_stereo_680kbps_48000hz.flac",
500 "bbb_flac_stereo_680kbps_48000hz.info"},
501 };
503 for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
504 if (kCompToURL[i].comp == comp) {
505 strcat(mURL, kCompToURL[i].mURL);
506 strcat(info, kCompToURL[i].info);
507 return;
508 }
509 }
510 }
512 // port settings reconfiguration during runtime. reconfigures sample rate and
513 // number
514 typedef struct {
515 OMX_AUDIO_CODINGTYPE eEncoding;
516 AudioDecHidlTest::standardComp comp;
517 } packedArgs;
518 void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
519 android::Vector<BufferInfo>* iBuffer,
520 android::Vector<BufferInfo>* oBuffer,
521 OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
522 Message msg, PortMode oPortMode, void* args) {
523 android::hardware::media::omx::V1_0::Status status;
524 packedArgs* audioArgs = static_cast<packedArgs*>(args);
525 OMX_AUDIO_CODINGTYPE eEncoding = audioArgs->eEncoding;
526 AudioDecHidlTest::standardComp comp = audioArgs->comp;
527 (void)oPortMode;
529 if (msg.data.eventData.event == OMX_EventPortSettingsChanged) {
530 ASSERT_EQ(msg.data.eventData.data1, kPortIndexOutput);
532 status = omxNode->sendCommand(toRawCommandType(OMX_CommandPortDisable),
533 kPortIndexOutput);
534 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
536 status =
537 observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
538 if (status == android::hardware::media::omx::V1_0::Status::TIMED_OUT) {
539 for (size_t i = 0; i < oBuffer->size(); ++i) {
540 // test if client got all its buffers back
541 EXPECT_EQ((*oBuffer)[i].owner, client);
542 // free the buffers
543 status =
544 omxNode->freeBuffer(kPortIndexOutput, (*oBuffer)[i].id);
545 ASSERT_EQ(status,
546 android::hardware::media::omx::V1_0::Status::OK);
547 }
548 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer,
549 oBuffer);
550 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
551 ASSERT_EQ(msg.type, Message::Type::EVENT);
552 ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
553 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortDisable);
554 ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
556 // set Port Params
557 int32_t nChannels;
558 int32_t nSampleRate;
559 ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
560 omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
561 // Configure output port
562 // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way
563 // to configure output PCM port. The port undergoes auto
564 // configuration internally basing on parsed elementary stream
565 // information.
566 if (comp != AudioDecHidlTest::standardComp::vorbis &&
567 comp != AudioDecHidlTest::standardComp::opus &&
568 comp != AudioDecHidlTest::standardComp::raw) {
569 setDefaultPortParam(omxNode, kPortIndexOutput,
570 OMX_AUDIO_CodingPCM, nChannels,
571 nSampleRate);
572 }
574 // If you can disable a port, then you should be able to enable it
575 // as well
576 status = omxNode->sendCommand(
577 toRawCommandType(OMX_CommandPortEnable), kPortIndexOutput);
578 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
580 // do not enable the port until all the buffers are supplied
581 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer,
582 oBuffer);
583 ASSERT_EQ(status,
584 android::hardware::media::omx::V1_0::Status::TIMED_OUT);
586 ASSERT_NO_FATAL_FAILURE(
587 allocatePortBuffers(omxNode, oBuffer, kPortIndexOutput));
588 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer,
589 oBuffer);
590 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
591 ASSERT_EQ(msg.type, Message::Type::EVENT);
592 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortEnable);
593 ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
595 // dispatch output buffers
596 for (size_t i = 0; i < oBuffer->size(); i++) {
597 ASSERT_NO_FATAL_FAILURE(
598 dispatchOutputBuffer(omxNode, oBuffer, i));
599 }
600 } else {
601 ASSERT_TRUE(false);
602 }
603 } else {
604 ASSERT_TRUE(false);
605 }
606 }
608 // blocking call to ensures application to Wait till all the inputs are consumed
609 void waitOnInputConsumption(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
610 android::Vector<BufferInfo>* iBuffer,
611 android::Vector<BufferInfo>* oBuffer,
612 OMX_AUDIO_CODINGTYPE eEncoding,
613 OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
614 AudioDecHidlTest::standardComp comp) {
615 android::hardware::media::omx::V1_0::Status status;
616 Message msg;
617 int timeOut = TIMEOUT_COUNTER_Q;
619 while (timeOut--) {
620 size_t i = 0;
621 status =
622 observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
623 if (status == android::hardware::media::omx::V1_0::Status::OK) {
624 ASSERT_EQ(msg.type, Message::Type::EVENT);
625 packedArgs audioArgs = {eEncoding, comp};
626 ASSERT_NO_FATAL_FAILURE(
627 portReconfiguration(omxNode, observer, iBuffer, oBuffer,
628 kPortIndexInput, kPortIndexOutput, msg,
629 PortMode::PRESET_BYTE_BUFFER, &audioArgs));
630 }
631 // status == TIMED_OUT, it could be due to process time being large
632 // than DEFAULT_TIMEOUT or component needs output buffers to start
633 // processing.
634 for (; i < iBuffer->size(); i++) {
635 if ((*iBuffer)[i].owner != client) break;
636 }
637 if (i == iBuffer->size()) break;
639 // Dispatch an output buffer assuming outQueue.empty() is true
640 size_t index;
641 if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
642 ASSERT_NO_FATAL_FAILURE(
643 dispatchOutputBuffer(omxNode, oBuffer, index));
644 timeOut = TIMEOUT_COUNTER_Q;
645 }
646 }
647 }
649 // Decode N Frames
650 void decodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
651 android::Vector<BufferInfo>* iBuffer,
652 android::Vector<BufferInfo>* oBuffer,
653 OMX_AUDIO_CODINGTYPE eEncoding, OMX_U32 kPortIndexInput,
654 OMX_U32 kPortIndexOutput, std::ifstream& eleStream,
655 android::Vector<FrameData>* Info, int offset, int range,
656 AudioDecHidlTest::standardComp comp, bool signalEOS = true) {
657 android::hardware::media::omx::V1_0::Status status;
658 Message msg;
659 size_t index;
660 uint32_t flags = 0;
661 int frameID = offset;
662 int timeOut = TIMEOUT_COUNTER_Q;
663 bool iQueued, oQueued;
665 while (1) {
666 iQueued = oQueued = false;
667 status =
668 observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
669 // Port Reconfiguration
670 if (status == android::hardware::media::omx::V1_0::Status::OK &&
671 msg.type == Message::Type::EVENT) {
672 packedArgs audioArgs = {eEncoding, comp};
673 ASSERT_NO_FATAL_FAILURE(
674 portReconfiguration(omxNode, observer, iBuffer, oBuffer,
675 kPortIndexInput, kPortIndexOutput, msg,
676 PortMode::PRESET_BYTE_BUFFER, &audioArgs));
677 }
679 if (frameID == (int)Info->size() || frameID == (offset + range)) break;
681 // Dispatch input buffer
682 if ((index = getEmptyBufferID(iBuffer)) < iBuffer->size()) {
683 char* ipBuffer = static_cast<char*>(
684 static_cast<void*>((*iBuffer)[index].mMemory->getPointer()));
685 ASSERT_LE((*Info)[frameID].bytesCount,
686 static_cast<int>((*iBuffer)[index].mMemory->getSize()));
687 eleStream.read(ipBuffer, (*Info)[frameID].bytesCount);
688 ASSERT_EQ(eleStream.gcount(), (*Info)[frameID].bytesCount);
689 flags = (*Info)[frameID].flags;
690 // Indicate to omx core that the buffer contains a full frame worth
691 // of data
692 flags |= OMX_BUFFERFLAG_ENDOFFRAME;
693 // Indicate the omx core that this is the last buffer it needs to
694 // process
695 if (signalEOS && ((frameID == (int)Info->size() - 1) ||
696 (frameID == (offset + range - 1))))
697 flags |= OMX_BUFFERFLAG_EOS;
698 ASSERT_NO_FATAL_FAILURE(dispatchInputBuffer(
699 omxNode, iBuffer, index, (*Info)[frameID].bytesCount, flags,
700 (*Info)[frameID].timestamp));
701 frameID++;
702 iQueued = true;
703 }
704 // Dispatch output buffer
705 if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
706 ASSERT_NO_FATAL_FAILURE(
707 dispatchOutputBuffer(omxNode, oBuffer, index));
708 oQueued = true;
709 }
710 // Reset Counters when either input or output buffer is dispatched
711 if (iQueued || oQueued)
712 timeOut = TIMEOUT_COUNTER_Q;
713 else
714 timeOut--;
715 if (timeOut == 0) {
716 ASSERT_TRUE(false) << "Wait on Input/Output is found indefinite";
717 }
718 }
719 }
721 // set component role
722 TEST_F(AudioDecHidlTest, SetRole) {
723 description("Test Set Component Role");
724 if (disableTest) return;
725 android::hardware::media::omx::V1_0::Status status;
726 status = setRole(omxNode, gEnv->getRole().c_str());
727 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
728 }
730 // port format enumeration
731 TEST_F(AudioDecHidlTest, EnumeratePortFormat) {
732 description("Test Component on Mandatory Port Parameters (Port Format)");
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;
744 }
745 status = setAudioPortFormat(omxNode, kPortIndexInput, eEncoding);
746 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
747 status = setAudioPortFormat(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM);
748 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
749 }
751 // test port settings reconfiguration, elementary stream decode and timestamp
752 // deviation
753 TEST_F(AudioDecHidlTest, DecodeTest) {
754 description("Tests Port Reconfiguration, Decode and timestamp deviation");
755 if (disableTest) return;
756 android::hardware::media::omx::V1_0::Status status;
757 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
758 status = setRole(omxNode, gEnv->getRole().c_str());
759 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
760 OMX_PORT_PARAM_TYPE params;
761 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
762 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
763 ASSERT_EQ(params.nPorts, 2U);
764 kPortIndexInput = params.nStartPortNumber;
765 kPortIndexOutput = kPortIndexInput + 1;
766 }
767 char mURL[512], info[512];
768 strcpy(mURL, gEnv->getRes().c_str());
769 strcpy(info, gEnv->getRes().c_str());
770 GetURLForComponent(compName, mURL, info);
772 std::ifstream eleStream, eleInfo;
774 eleInfo.open(info);
775 ASSERT_EQ(eleInfo.is_open(), true);
776 android::Vector<FrameData> Info;
777 int bytesCount = 0;
778 uint32_t flags = 0;
779 uint32_t timestamp = 0;
780 timestampDevTest = false;
781 while (1) {
782 if (!(eleInfo >> bytesCount)) break;
783 eleInfo >> flags;
784 eleInfo >> timestamp;
785 Info.push_back({bytesCount, flags, timestamp});
786 if (timestampDevTest && (flags != OMX_BUFFERFLAG_CODECCONFIG))
787 timestampUslist.push_back(timestamp);
788 }
789 eleInfo.close();
791 int32_t nChannels, nSampleRate;
792 // Configure input port
793 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
794 if (compName == raw)
795 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
796 OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
797 32);
798 ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
799 omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
800 // Configure output port
801 // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
802 // configure output PCM port. The port undergoes auto configuration
803 // internally basing on parsed elementary stream information.
804 if (compName != vorbis && compName != opus && compName != raw) {
805 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
806 nChannels, nSampleRate);
807 }
809 android::Vector<BufferInfo> iBuffer, oBuffer;
811 // set state to idle
812 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(omxNode, observer, &iBuffer,
813 &oBuffer, kPortIndexInput,
814 kPortIndexOutput));
815 // set state to executing
816 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
817 // Port Reconfiguration
818 eleStream.open(mURL, std::ifstream::binary);
819 ASSERT_EQ(eleStream.is_open(), true);
820 ASSERT_NO_FATAL_FAILURE(decodeNFrames(
821 omxNode, observer, &iBuffer, &oBuffer, eEncoding, kPortIndexInput,
822 kPortIndexOutput, eleStream, &Info, 0, (int)Info.size(), compName));
823 eleStream.close();
824 ASSERT_NO_FATAL_FAILURE(
825 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
826 kPortIndexInput, kPortIndexOutput, compName));
827 packedArgs audioArgs = {eEncoding, compName};
828 ASSERT_NO_FATAL_FAILURE(testEOS(
829 omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, nullptr,
830 portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs));
831 if (timestampDevTest) EXPECT_EQ(timestampUslist.empty(), true);
832 // set state to idle
833 ASSERT_NO_FATAL_FAILURE(
834 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
835 // set state to executing
836 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
837 &oBuffer, kPortIndexInput,
838 kPortIndexOutput));
839 }
841 // end of sequence test
842 TEST_F(AudioDecHidlTest, EOSTest_M) {
843 description("Test end of stream monkeying");
844 if (disableTest) return;
845 android::hardware::media::omx::V1_0::Status status;
846 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
847 status = setRole(omxNode, gEnv->getRole().c_str());
848 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
849 OMX_PORT_PARAM_TYPE params;
850 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
851 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
852 ASSERT_EQ(params.nPorts, 2U);
853 kPortIndexInput = params.nStartPortNumber;
854 kPortIndexOutput = kPortIndexInput + 1;
855 }
857 int32_t nChannels, nSampleRate;
858 // Configure input port
859 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
860 if (compName == raw)
861 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
862 OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
863 32);
864 ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
865 omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
866 // Configure output port
867 // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
868 // configure output PCM port. The port undergoes auto configuration
869 // internally basing on parsed elementary stream information.
870 if (compName != vorbis && compName != opus && compName != raw) {
871 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
872 nChannels, nSampleRate);
873 }
875 android::Vector<BufferInfo> iBuffer, oBuffer;
877 // set state to idle
878 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(omxNode, observer, &iBuffer,
879 &oBuffer, kPortIndexInput,
880 kPortIndexOutput));
881 // set state to executing
882 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
884 // request EOS at the start
885 packedArgs audioArgs = {eEncoding, compName};
886 ASSERT_NO_FATAL_FAILURE(testEOS(
887 omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, nullptr,
888 portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs));
889 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
890 kPortIndexInput, kPortIndexOutput));
891 EXPECT_GE(framesReceived, 0U);
892 framesReceived = 0;
893 timestampUs = 0;
895 // set state to idle
896 ASSERT_NO_FATAL_FAILURE(
897 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
899 // set state to executing
900 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
901 &oBuffer, kPortIndexInput,
902 kPortIndexOutput));
903 }
905 // end of sequence test
906 TEST_F(AudioDecHidlTest, ThumbnailTest) {
907 description("Test Request for thumbnail");
908 if (disableTest) return;
909 android::hardware::media::omx::V1_0::Status status;
910 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
911 status = setRole(omxNode, gEnv->getRole().c_str());
912 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
913 OMX_PORT_PARAM_TYPE params;
914 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
915 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
916 ASSERT_EQ(params.nPorts, 2U);
917 kPortIndexInput = params.nStartPortNumber;
918 kPortIndexOutput = kPortIndexInput + 1;
919 }
920 char mURL[512], info[512];
921 strcpy(mURL, gEnv->getRes().c_str());
922 strcpy(info, gEnv->getRes().c_str());
923 GetURLForComponent(compName, mURL, info);
925 std::ifstream eleStream, eleInfo;
927 eleInfo.open(info);
928 ASSERT_EQ(eleInfo.is_open(), true);
929 android::Vector<FrameData> Info;
930 int bytesCount = 0;
931 uint32_t flags = 0;
932 uint32_t timestamp = 0;
933 while (1) {
934 if (!(eleInfo >> bytesCount)) break;
935 eleInfo >> flags;
936 eleInfo >> timestamp;
937 Info.push_back({bytesCount, flags, timestamp});
938 }
939 eleInfo.close();
941 int32_t nChannels, nSampleRate;
942 // Configure input port
943 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
944 if (compName == raw)
945 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
946 OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
947 32);
948 ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
949 omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
950 // Configure output port
951 // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
952 // configure output PCM port. The port undergoes auto configuration
953 // internally basing on parsed elementary stream information.
954 if (compName != vorbis && compName != opus && compName != raw) {
955 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
956 nChannels, nSampleRate);
957 }
959 android::Vector<BufferInfo> iBuffer, oBuffer;
961 // set state to idle
962 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(omxNode, observer, &iBuffer,
963 &oBuffer, kPortIndexInput,
964 kPortIndexOutput));
965 // set state to executing
966 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
968 // request EOS for thumbnail
969 // signal EOS flag with last frame
970 size_t i = 0;
971 while (!(Info[i].flags & OMX_BUFFERFLAG_SYNCFRAME)) i++;
972 eleStream.open(mURL, std::ifstream::binary);
973 ASSERT_EQ(eleStream.is_open(), true);
974 ASSERT_NO_FATAL_FAILURE(decodeNFrames(
975 omxNode, observer, &iBuffer, &oBuffer, eEncoding, kPortIndexInput,
976 kPortIndexOutput, eleStream, &Info, 0, i + 1, compName));
977 eleStream.close();
978 ASSERT_NO_FATAL_FAILURE(
979 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
980 kPortIndexInput, kPortIndexOutput, compName));
981 packedArgs audioArgs = {eEncoding, compName};
982 ASSERT_NO_FATAL_FAILURE(testEOS(
983 omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, nullptr,
984 portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs));
985 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
986 kPortIndexInput, kPortIndexOutput));
987 EXPECT_GE(framesReceived, 1U);
988 framesReceived = 0;
989 timestampUs = 0;
991 // signal EOS flag after last frame
992 eleStream.open(mURL, std::ifstream::binary);
993 ASSERT_EQ(eleStream.is_open(), true);
994 ASSERT_NO_FATAL_FAILURE(decodeNFrames(
995 omxNode, observer, &iBuffer, &oBuffer, eEncoding, kPortIndexInput,
996 kPortIndexOutput, eleStream, &Info, 0, i + 1, compName, false));
997 eleStream.close();
998 ASSERT_NO_FATAL_FAILURE(
999 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
1000 kPortIndexInput, kPortIndexOutput, compName));
1001 ASSERT_NO_FATAL_FAILURE(testEOS(
1002 omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, nullptr,
1003 portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs));
1004 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
1005 kPortIndexInput, kPortIndexOutput));
1006 EXPECT_GE(framesReceived, 1U);
1007 framesReceived = 0;
1008 timestampUs = 0;
1010 // set state to idle
1011 ASSERT_NO_FATAL_FAILURE(
1012 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
1013 // set state to executing
1014 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
1015 &oBuffer, kPortIndexInput,
1016 kPortIndexOutput));
1017 }
1019 // end of sequence test
1020 TEST_F(AudioDecHidlTest, SimpleEOSTest) {
1021 description("Test end of stream");
1022 if (disableTest) return;
1023 android::hardware::media::omx::V1_0::Status status;
1024 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1025 status = setRole(omxNode, gEnv->getRole().c_str());
1026 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1027 OMX_PORT_PARAM_TYPE params;
1028 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
1029 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1030 ASSERT_EQ(params.nPorts, 2U);
1031 kPortIndexInput = params.nStartPortNumber;
1032 kPortIndexOutput = kPortIndexInput + 1;
1033 }
1034 char mURL[512], info[512];
1035 strcpy(mURL, gEnv->getRes().c_str());
1036 strcpy(info, gEnv->getRes().c_str());
1037 GetURLForComponent(compName, mURL, info);
1039 std::ifstream eleStream, eleInfo;
1041 eleInfo.open(info);
1042 ASSERT_EQ(eleInfo.is_open(), true);
1043 android::Vector<FrameData> Info;
1044 int bytesCount = 0;
1045 uint32_t flags = 0;
1046 uint32_t timestamp = 0;
1047 while (1) {
1048 if (!(eleInfo >> bytesCount)) break;
1049 eleInfo >> flags;
1050 eleInfo >> timestamp;
1051 Info.push_back({bytesCount, flags, timestamp});
1052 }
1053 eleInfo.close();
1055 int32_t nChannels, nSampleRate;
1056 // Configure input port
1057 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
1058 if (compName == raw)
1059 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
1060 OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
1061 32);
1062 ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
1063 omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
1064 // Configure output port
1065 // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
1066 // configure output PCM port. The port undergoes auto configuration
1067 // internally basing on parsed elementary stream information.
1068 if (compName != vorbis && compName != opus && compName != raw) {
1069 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
1070 nChannels, nSampleRate);
1071 }
1073 android::Vector<BufferInfo> iBuffer, oBuffer;
1075 // set state to idle
1076 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(omxNode, observer, &iBuffer,
1077 &oBuffer, kPortIndexInput,
1078 kPortIndexOutput));
1079 // set state to executing
1080 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
1082 // request EOS at the end
1083 eleStream.open(mURL, std::ifstream::binary);
1084 ASSERT_EQ(eleStream.is_open(), true);
1085 ASSERT_NO_FATAL_FAILURE(decodeNFrames(omxNode, observer, &iBuffer, &oBuffer,
1086 eEncoding, kPortIndexInput,
1087 kPortIndexOutput, eleStream, &Info, 0,
1088 (int)Info.size(), compName, false));
1089 eleStream.close();
1090 ASSERT_NO_FATAL_FAILURE(
1091 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
1092 kPortIndexInput, kPortIndexOutput, compName));
1093 packedArgs audioArgs = {eEncoding, compName};
1094 ASSERT_NO_FATAL_FAILURE(testEOS(
1095 omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, nullptr,
1096 portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs));
1097 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
1098 kPortIndexInput, kPortIndexOutput));
1099 framesReceived = 0;
1100 timestampUs = 0;
1102 // set state to idle
1103 ASSERT_NO_FATAL_FAILURE(
1104 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
1105 // set state to executing
1106 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
1107 &oBuffer, kPortIndexInput,
1108 kPortIndexOutput));
1109 }
1111 // test input/output port flush
1112 TEST_F(AudioDecHidlTest, FlushTest) {
1113 description("Test Flush");
1114 if (disableTest) return;
1115 android::hardware::media::omx::V1_0::Status status;
1116 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1117 status = setRole(omxNode, gEnv->getRole().c_str());
1118 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1119 OMX_PORT_PARAM_TYPE params;
1120 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
1121 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1122 ASSERT_EQ(params.nPorts, 2U);
1123 kPortIndexInput = params.nStartPortNumber;
1124 kPortIndexOutput = kPortIndexInput + 1;
1125 }
1126 char mURL[512], info[512];
1127 strcpy(mURL, gEnv->getRes().c_str());
1128 strcpy(info, gEnv->getRes().c_str());
1129 GetURLForComponent(compName, mURL, info);
1131 std::ifstream eleStream, eleInfo;
1133 eleInfo.open(info);
1134 ASSERT_EQ(eleInfo.is_open(), true);
1135 android::Vector<FrameData> Info;
1136 int bytesCount = 0;
1137 uint32_t flags = 0;
1138 uint32_t timestamp = 0;
1139 while (1) {
1140 if (!(eleInfo >> bytesCount)) break;
1141 eleInfo >> flags;
1142 eleInfo >> timestamp;
1143 Info.push_back({bytesCount, flags, timestamp});
1144 }
1145 eleInfo.close();
1147 int32_t nChannels, nSampleRate;
1148 // Configure input port
1149 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
1150 if (compName == raw)
1151 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
1152 OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
1153 32);
1154 ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
1155 omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
1156 // Configure output port
1157 // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
1158 // configure output PCM port. The port undergoes auto configuration
1159 // internally basing on parsed elementary stream information.
1160 if (compName != vorbis && compName != opus && compName != raw) {
1161 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
1162 nChannels, nSampleRate);
1163 }
1165 android::Vector<BufferInfo> iBuffer, oBuffer;
1167 // set state to idle
1168 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(omxNode, observer, &iBuffer,
1169 &oBuffer, kPortIndexInput,
1170 kPortIndexOutput));
1171 // set state to executing
1172 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
1174 // Decode 128 frames and flush. here 128 is chosen to ensure there is a key
1175 // frame after this so that the below section can be convered for all
1176 // components
1177 int nFrames = 128;
1178 eleStream.open(mURL, std::ifstream::binary);
1179 ASSERT_EQ(eleStream.is_open(), true);
1180 ASSERT_NO_FATAL_FAILURE(decodeNFrames(
1181 omxNode, observer, &iBuffer, &oBuffer, eEncoding, kPortIndexInput,
1182 kPortIndexOutput, eleStream, &Info, 0, nFrames, compName, false));
1183 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
1184 kPortIndexInput, kPortIndexOutput));
1185 framesReceived = 0;
1187 // Seek to next key frame and start decoding till the end
1188 int index = nFrames;
1189 bool keyFrame = false;
1190 while (index < (int)Info.size()) {
1191 if ((Info[index].flags & OMX_BUFFERFLAG_SYNCFRAME) ==
1192 OMX_BUFFERFLAG_SYNCFRAME) {
1193 timestampUs = Info[index - 1].timestamp;
1194 keyFrame = true;
1195 break;
1196 }
1197 eleStream.ignore(Info[index].bytesCount);
1198 index++;
1199 }
1200 if (keyFrame) {
1201 ASSERT_NO_FATAL_FAILURE(
1202 decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
1203 kPortIndexInput, kPortIndexOutput, eleStream, &Info,
1204 index, Info.size() - index, compName, false));
1205 }
1206 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
1207 kPortIndexInput, kPortIndexOutput));
1208 framesReceived = 0;
1210 // set state to idle
1211 ASSERT_NO_FATAL_FAILURE(
1212 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
1213 // set state to executing
1214 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
1215 &oBuffer, kPortIndexInput,
1216 kPortIndexOutput));
1217 }
1219 int main(int argc, char** argv) {
1220 gEnv = new ComponentTestEnvironment();
1221 ::testing::AddGlobalTestEnvironment(gEnv);
1222 ::testing::InitGoogleTest(&argc, argv);
1223 int status = gEnv->initFromOptions(argc, argv);
1224 if (status == 0) {
1225 status = RUN_ALL_TESTS();
1226 ALOGI("Test result = %d", status);
1227 }
1228 return status;
1229 }