[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 static ComponentTestEnvironment* gEnv = nullptr;
55 // audio decoder test fixture class
56 class AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
57 private:
58 typedef ::testing::VtsHalHidlTargetTestBase Super;
59 public:
60 ::std::string getTestCaseInfo() const override {
61 return ::std::string() +
62 "Component: " + gEnv->getComponent().c_str() + " | " +
63 "Role: " + gEnv->getRole().c_str() + " | " +
64 "Instance: " + gEnv->getInstance().c_str() + " | " +
65 "Res: " + gEnv->getRes().c_str();
66 }
68 virtual void SetUp() override {
69 Super::SetUp();
70 disableTest = false;
71 android::hardware::media::omx::V1_0::Status status;
72 omx = Super::getService<IOmx>(gEnv->getInstance());
73 ASSERT_NE(omx, nullptr);
74 observer =
75 new CodecObserver([this](Message msg, const BufferInfo* buffer) {
76 handleMessage(msg, buffer);
77 });
78 ASSERT_NE(observer, nullptr);
79 if (strncmp(gEnv->getComponent().c_str(), "OMX.", 4) != 0)
80 disableTest = true;
81 EXPECT_TRUE(omx->allocateNode(
82 gEnv->getComponent(), observer,
83 [&](android::hardware::media::omx::V1_0::Status _s,
84 sp<IOmxNode> const& _nl) {
85 status = _s;
86 this->omxNode = _nl;
87 })
88 .isOk());
89 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
90 ASSERT_NE(omxNode, nullptr);
91 ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
92 struct StringToName {
93 const char* Name;
94 standardComp CompName;
95 };
96 const StringToName kStringToName[] = {
97 {"mp3", mp3}, {"amrnb", amrnb}, {"amrwb", amrwb},
98 {"aac", aac}, {"vorbis", vorbis}, {"opus", opus},
99 {"pcm", pcm}, {"g711alaw", g711alaw}, {"g711mlaw", g711mlaw},
100 {"gsm", gsm}, {"raw", raw}, {"flac", flac},
101 };
102 const size_t kNumStringToName =
103 sizeof(kStringToName) / sizeof(kStringToName[0]);
104 const char* pch;
105 char substring[OMX_MAX_STRINGNAME_SIZE];
106 strcpy(substring, gEnv->getRole().c_str());
107 pch = strchr(substring, '.');
108 ASSERT_NE(pch, nullptr);
109 compName = unknown_comp;
110 for (size_t i = 0; i < kNumStringToName; ++i) {
111 if (!strcasecmp(pch + 1, kStringToName[i].Name)) {
112 compName = kStringToName[i].CompName;
113 break;
114 }
115 }
116 if (compName == unknown_comp) disableTest = true;
117 struct CompToCoding {
118 standardComp CompName;
119 OMX_AUDIO_CODINGTYPE eEncoding;
120 };
121 static const CompToCoding kCompToCoding[] = {
122 {mp3, OMX_AUDIO_CodingMP3},
123 {amrnb, OMX_AUDIO_CodingAMR},
124 {amrwb, OMX_AUDIO_CodingAMR},
125 {aac, OMX_AUDIO_CodingAAC},
126 {vorbis, OMX_AUDIO_CodingVORBIS},
127 {pcm, OMX_AUDIO_CodingPCM},
128 {opus, (OMX_AUDIO_CODINGTYPE)OMX_AUDIO_CodingAndroidOPUS},
129 {g711alaw, OMX_AUDIO_CodingG711},
130 {g711mlaw, OMX_AUDIO_CodingG711},
131 {gsm, OMX_AUDIO_CodingGSMFR},
132 {raw, OMX_AUDIO_CodingPCM},
133 {flac, OMX_AUDIO_CodingFLAC},
134 };
135 static const size_t kNumCompToCoding =
136 sizeof(kCompToCoding) / sizeof(kCompToCoding[0]);
137 size_t i;
138 for (i = 0; i < kNumCompToCoding; ++i) {
139 if (kCompToCoding[i].CompName == compName) {
140 eEncoding = kCompToCoding[i].eEncoding;
141 break;
142 }
143 }
144 if (i == kNumCompToCoding) disableTest = true;
145 eosFlag = false;
146 framesReceived = 0;
147 timestampUs = 0;
148 timestampDevTest = false;
149 if (disableTest) std::cout << "[ WARN ] Test Disabled \n";
150 }
152 virtual void TearDown() override {
153 if (omxNode != nullptr) {
154 // If you have encountered a fatal failure, it is possible that
155 // freeNode() will not go through. Instead of hanging the app.
156 // let it pass through and report errors
157 if (::testing::Test::HasFatalFailure()) return;
158 EXPECT_TRUE((omxNode->freeNode()).isOk());
159 omxNode = nullptr;
160 }
161 Super::TearDown();
162 }
164 // callback function to process messages received by onMessages() from IL
165 // client.
166 void handleMessage(Message msg, const BufferInfo* buffer) {
167 (void)buffer;
168 if (msg.type == Message::Type::FILL_BUFFER_DONE) {
169 if (msg.data.extendedBufferData.flags & OMX_BUFFERFLAG_EOS) {
170 eosFlag = true;
171 }
172 if (msg.data.extendedBufferData.rangeLength != 0) {
173 framesReceived += 1;
174 // For decoder components current timestamp always exceeds
175 // previous timestamp
176 EXPECT_GE(msg.data.extendedBufferData.timestampUs, timestampUs);
177 timestampUs = msg.data.extendedBufferData.timestampUs;
178 // Test if current timestamp is among the list of queued
179 // timestamps
180 if (timestampDevTest) {
181 bool tsHit = false;
182 android::List<uint64_t>::iterator it =
183 timestampUslist.begin();
184 while (it != timestampUslist.end()) {
185 if (*it == timestampUs) {
186 timestampUslist.erase(it);
187 tsHit = true;
188 break;
189 }
190 it++;
191 }
192 if (tsHit == false) {
193 if (timestampUslist.empty() == false) {
194 EXPECT_EQ(tsHit, true)
195 << "TimeStamp not recognized";
196 } else {
197 std::cout << "[ INFO ] Received non-zero "
198 "output / TimeStamp not recognized \n";
199 }
200 }
201 }
202 #define WRITE_OUTPUT 0
203 #if WRITE_OUTPUT
204 static int count = 0;
205 FILE* ofp = nullptr;
206 if (count)
207 ofp = fopen("out.bin", "ab");
208 else
209 ofp = fopen("out.bin", "wb");
210 if (ofp != nullptr) {
211 fwrite(static_cast<void*>(buffer->mMemory->getPointer()),
212 sizeof(char),
213 msg.data.extendedBufferData.rangeLength, ofp);
214 fclose(ofp);
215 count++;
216 }
217 #endif
218 }
219 }
220 }
222 enum standardComp {
223 mp3,
224 amrnb,
225 amrwb,
226 aac,
227 vorbis,
228 opus,
229 pcm,
230 g711alaw,
231 g711mlaw,
232 gsm,
233 raw,
234 flac,
235 unknown_comp,
236 };
238 sp<IOmx> omx;
239 sp<CodecObserver> observer;
240 sp<IOmxNode> omxNode;
241 standardComp compName;
242 OMX_AUDIO_CODINGTYPE eEncoding;
243 bool disableTest;
244 bool eosFlag;
245 uint32_t framesReceived;
246 uint64_t timestampUs;
247 ::android::List<uint64_t> timestampUslist;
248 bool timestampDevTest;
250 protected:
251 static void description(const std::string& description) {
252 RecordProperty("description", description);
253 }
254 };
256 // Set Default port param.
257 void setDefaultPortParam(
258 sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE eEncoding,
259 int32_t nChannels = 2, int32_t nSampleRate = 44100,
260 OMX_AUDIO_PCMMODETYPE ePCMMode = OMX_AUDIO_PCMModeLinear,
261 OMX_NUMERICALDATATYPE eNumData = OMX_NumericalDataSigned,
262 int32_t nBitPerSample = 16) {
263 android::hardware::media::omx::V1_0::Status status;
265 OMX_PARAM_PORTDEFINITIONTYPE portDef;
266 status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
267 &portDef);
268 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
270 portDef.format.audio.bFlagErrorConcealment = OMX_TRUE;
271 portDef.format.audio.eEncoding = eEncoding;
272 status = setPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
273 &portDef);
274 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
276 switch ((int)eEncoding) {
277 case OMX_AUDIO_CodingPCM:
278 setupPCMPort(omxNode, portIndex, nChannels, eNumData, nBitPerSample,
279 nSampleRate, ePCMMode);
280 break;
281 case OMX_AUDIO_CodingAAC:
282 setupAACPort(omxNode, portIndex, OMX_AUDIO_AACObjectNull,
283 OMX_AUDIO_AACStreamFormatMP4FF, nChannels, 0,
284 nSampleRate);
285 default:
286 break;
287 }
288 }
290 // In decoder components, often the input port parameters get updated upon
291 // parsing the header of elementary stream. Client needs to collect this
292 // information to reconfigure other ports that share data with this input
293 // port.
294 void getInputChannelInfo(sp<IOmxNode> omxNode, OMX_U32 kPortIndexInput,
295 OMX_AUDIO_CODINGTYPE eEncoding, int32_t* nChannels,
296 int32_t* nSampleRate) {
297 android::hardware::media::omx::V1_0::Status status;
298 *nChannels = 0;
299 *nSampleRate = 0;
301 switch ((int)eEncoding) {
302 case OMX_AUDIO_CodingGSMFR:
303 case OMX_AUDIO_CodingG711:
304 case OMX_AUDIO_CodingPCM: {
305 OMX_AUDIO_PARAM_PCMMODETYPE param;
306 status = getPortParam(omxNode, OMX_IndexParamAudioPcm,
307 kPortIndexInput, ¶m);
308 ASSERT_EQ(status,
309 ::android::hardware::media::omx::V1_0::Status::OK);
310 *nChannels = param.nChannels;
311 *nSampleRate = param.nSamplingRate;
312 break;
313 }
314 case OMX_AUDIO_CodingMP3: {
315 OMX_AUDIO_PARAM_MP3TYPE param;
316 status = getPortParam(omxNode, OMX_IndexParamAudioMp3,
317 kPortIndexInput, ¶m);
318 ASSERT_EQ(status,
319 ::android::hardware::media::omx::V1_0::Status::OK);
320 *nChannels = param.nChannels;
321 *nSampleRate = param.nSampleRate;
322 break;
323 }
324 case OMX_AUDIO_CodingAndroidOPUS: {
325 OMX_AUDIO_PARAM_ANDROID_OPUSTYPE param;
326 status = getPortParam(omxNode,
327 (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
328 kPortIndexInput, ¶m);
329 ASSERT_EQ(status,
330 ::android::hardware::media::omx::V1_0::Status::OK);
331 *nChannels = param.nChannels;
332 *nSampleRate = param.nSampleRate;
333 break;
334 }
335 case OMX_AUDIO_CodingVORBIS: {
336 OMX_AUDIO_PARAM_VORBISTYPE param;
337 status = getPortParam(omxNode, OMX_IndexParamAudioVorbis,
338 kPortIndexInput, ¶m);
339 ASSERT_EQ(status,
340 ::android::hardware::media::omx::V1_0::Status::OK);
341 *nChannels = param.nChannels;
342 *nSampleRate = param.nSampleRate;
343 break;
344 }
345 case OMX_AUDIO_CodingAMR: {
346 OMX_AUDIO_PARAM_AMRTYPE param;
347 status = getPortParam(omxNode, OMX_IndexParamAudioAmr,
348 kPortIndexInput, ¶m);
349 ASSERT_EQ(status,
350 ::android::hardware::media::omx::V1_0::Status::OK);
351 *nChannels = param.nChannels;
352 // NOTE: For amrnb sample rate is 8k and amrwb sample rate is 16k.
353 // There is no nSampleRate field in OMX_AUDIO_PARAM_AMRTYPE. Just
354 // return 8k to avoid returning uninit variable.
355 *nSampleRate = 8000;
356 break;
357 }
358 case OMX_AUDIO_CodingAAC: {
359 OMX_AUDIO_PARAM_AACPROFILETYPE param;
360 status = getPortParam(omxNode, OMX_IndexParamAudioAac,
361 kPortIndexInput, ¶m);
362 ASSERT_EQ(status,
363 ::android::hardware::media::omx::V1_0::Status::OK);
364 *nChannels = param.nChannels;
365 *nSampleRate = param.nSampleRate;
366 break;
367 }
368 case OMX_AUDIO_CodingFLAC: {
369 OMX_AUDIO_PARAM_FLACTYPE param;
370 status = getPortParam(omxNode, OMX_IndexParamAudioFlac,
371 kPortIndexInput, ¶m);
372 ASSERT_EQ(status,
373 ::android::hardware::media::omx::V1_0::Status::OK);
374 *nChannels = param.nChannels;
375 *nSampleRate = param.nSampleRate;
376 break;
377 }
378 default:
379 ASSERT_TRUE(false);
380 break;
381 }
382 }
384 // LookUpTable of clips and metadata for component testing
385 void GetURLForComponent(AudioDecHidlTest::standardComp comp, char* mURL,
386 char* info) {
387 struct CompToURL {
388 AudioDecHidlTest::standardComp comp;
389 const char* mURL;
390 const char* info;
391 };
392 static const CompToURL kCompToURL[] = {
393 {AudioDecHidlTest::standardComp::mp3,
394 "bbb_mp3_stereo_192kbps_48000hz.mp3",
395 "bbb_mp3_stereo_192kbps_48000hz.info"},
396 {AudioDecHidlTest::standardComp::aac,
397 "bbb_aac_stereo_128kbps_48000hz.aac",
398 "bbb_aac_stereo_128kbps_48000hz.info"},
399 {AudioDecHidlTest::standardComp::amrnb,
400 "sine_amrnb_1ch_12kbps_8000hz.amrnb",
401 "sine_amrnb_1ch_12kbps_8000hz.info"},
402 {AudioDecHidlTest::standardComp::amrwb,
403 "bbb_amrwb_1ch_14kbps_16000hz.amrwb",
404 "bbb_amrwb_1ch_14kbps_16000hz.info"},
405 {AudioDecHidlTest::standardComp::vorbis,
406 "bbb_vorbis_stereo_128kbps_48000hz.vorbis",
407 "bbb_vorbis_stereo_128kbps_48000hz.info"},
408 {AudioDecHidlTest::standardComp::opus,
409 "bbb_opus_stereo_128kbps_48000hz.opus",
410 "bbb_opus_stereo_128kbps_48000hz.info"},
411 {AudioDecHidlTest::standardComp::g711alaw, "bbb_g711alaw_1ch_8khz.raw",
412 "bbb_g711alaw_1ch_8khz.info"},
413 {AudioDecHidlTest::standardComp::g711mlaw, "bbb_g711mulaw_1ch_8khz.raw",
414 "bbb_g711mulaw_1ch_8khz.info"},
415 {AudioDecHidlTest::standardComp::gsm, "bbb_gsm_1ch_8khz_13kbps.raw",
416 "bbb_gsm_1ch_8khz_13kbps.info"},
417 {AudioDecHidlTest::standardComp::raw, "bbb_raw_1ch_8khz_s32le.raw",
418 "bbb_raw_1ch_8khz_s32le.info"},
419 {AudioDecHidlTest::standardComp::flac,
420 "bbb_flac_stereo_680kbps_48000hz.flac",
421 "bbb_flac_stereo_680kbps_48000hz.info"},
422 };
424 for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
425 if (kCompToURL[i].comp == comp) {
426 strcat(mURL, kCompToURL[i].mURL);
427 strcat(info, kCompToURL[i].info);
428 return;
429 }
430 }
431 }
433 // port settings reconfiguration during runtime. reconfigures sample rate and
434 // number
435 typedef struct {
436 OMX_AUDIO_CODINGTYPE eEncoding;
437 AudioDecHidlTest::standardComp comp;
438 } packedArgs;
439 void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
440 android::Vector<BufferInfo>* iBuffer,
441 android::Vector<BufferInfo>* oBuffer,
442 OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
443 Message msg, PortMode oPortMode, void* args) {
444 android::hardware::media::omx::V1_0::Status status;
445 packedArgs* audioArgs = static_cast<packedArgs*>(args);
446 OMX_AUDIO_CODINGTYPE eEncoding = audioArgs->eEncoding;
447 AudioDecHidlTest::standardComp comp = audioArgs->comp;
448 (void)oPortMode;
450 if (msg.data.eventData.event == OMX_EventPortSettingsChanged) {
451 ASSERT_EQ(msg.data.eventData.data1, kPortIndexOutput);
453 status = omxNode->sendCommand(toRawCommandType(OMX_CommandPortDisable),
454 kPortIndexOutput);
455 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
457 status =
458 observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
459 if (status == android::hardware::media::omx::V1_0::Status::TIMED_OUT) {
460 for (size_t i = 0; i < oBuffer->size(); ++i) {
461 // test if client got all its buffers back
462 EXPECT_EQ((*oBuffer)[i].owner, client);
463 // free the buffers
464 status =
465 omxNode->freeBuffer(kPortIndexOutput, (*oBuffer)[i].id);
466 ASSERT_EQ(status,
467 android::hardware::media::omx::V1_0::Status::OK);
468 }
469 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer,
470 oBuffer);
471 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
472 ASSERT_EQ(msg.type, Message::Type::EVENT);
473 ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
474 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortDisable);
475 ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
477 // set Port Params
478 int32_t nChannels;
479 int32_t nSampleRate;
480 ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
481 omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
482 // Configure output port
483 // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way
484 // to configure output PCM port. The port undergoes auto
485 // configuration internally basing on parsed elementary stream
486 // information.
487 if (comp != AudioDecHidlTest::standardComp::vorbis &&
488 comp != AudioDecHidlTest::standardComp::opus &&
489 comp != AudioDecHidlTest::standardComp::raw) {
490 setDefaultPortParam(omxNode, kPortIndexOutput,
491 OMX_AUDIO_CodingPCM, nChannels,
492 nSampleRate);
493 }
495 // If you can disable a port, then you should be able to enable it
496 // as well
497 status = omxNode->sendCommand(
498 toRawCommandType(OMX_CommandPortEnable), kPortIndexOutput);
499 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
501 // do not enable the port until all the buffers are supplied
502 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer,
503 oBuffer);
504 ASSERT_EQ(status,
505 android::hardware::media::omx::V1_0::Status::TIMED_OUT);
507 ASSERT_NO_FATAL_FAILURE(
508 allocatePortBuffers(omxNode, oBuffer, kPortIndexOutput));
509 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer,
510 oBuffer);
511 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
512 ASSERT_EQ(msg.type, Message::Type::EVENT);
513 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortEnable);
514 ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
516 // dispatch output buffers
517 for (size_t i = 0; i < oBuffer->size(); i++) {
518 ASSERT_NO_FATAL_FAILURE(
519 dispatchOutputBuffer(omxNode, oBuffer, i));
520 }
521 } else {
522 ASSERT_TRUE(false);
523 }
524 } else {
525 ASSERT_TRUE(false);
526 }
527 }
529 // blocking call to ensures application to Wait till all the inputs are consumed
530 void waitOnInputConsumption(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
531 android::Vector<BufferInfo>* iBuffer,
532 android::Vector<BufferInfo>* oBuffer,
533 OMX_AUDIO_CODINGTYPE eEncoding,
534 OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
535 AudioDecHidlTest::standardComp comp) {
536 android::hardware::media::omx::V1_0::Status status;
537 Message msg;
538 int timeOut = TIMEOUT_COUNTER_Q;
540 while (timeOut--) {
541 size_t i = 0;
542 status =
543 observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
544 if (status == android::hardware::media::omx::V1_0::Status::OK) {
545 ASSERT_EQ(msg.type, Message::Type::EVENT);
546 packedArgs audioArgs = {eEncoding, comp};
547 ASSERT_NO_FATAL_FAILURE(
548 portReconfiguration(omxNode, observer, iBuffer, oBuffer,
549 kPortIndexInput, kPortIndexOutput, msg,
550 PortMode::PRESET_BYTE_BUFFER, &audioArgs));
551 }
552 // status == TIMED_OUT, it could be due to process time being large
553 // than DEFAULT_TIMEOUT or component needs output buffers to start
554 // processing.
555 for (; i < iBuffer->size(); i++) {
556 if ((*iBuffer)[i].owner != client) break;
557 }
558 if (i == iBuffer->size()) break;
560 // Dispatch an output buffer assuming outQueue.empty() is true
561 size_t index;
562 if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
563 ASSERT_NO_FATAL_FAILURE(
564 dispatchOutputBuffer(omxNode, oBuffer, index));
565 timeOut = TIMEOUT_COUNTER_Q;
566 }
567 }
568 }
570 // Decode N Frames
571 void decodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
572 android::Vector<BufferInfo>* iBuffer,
573 android::Vector<BufferInfo>* oBuffer,
574 OMX_AUDIO_CODINGTYPE eEncoding, OMX_U32 kPortIndexInput,
575 OMX_U32 kPortIndexOutput, std::ifstream& eleStream,
576 android::Vector<FrameData>* Info, int offset, int range,
577 AudioDecHidlTest::standardComp comp, bool signalEOS = true) {
578 android::hardware::media::omx::V1_0::Status status;
579 Message msg;
580 size_t index;
581 uint32_t flags = 0;
582 int frameID = offset;
583 int timeOut = TIMEOUT_COUNTER_Q;
584 bool iQueued, oQueued;
586 while (1) {
587 iQueued = oQueued = false;
588 status =
589 observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
590 // Port Reconfiguration
591 if (status == android::hardware::media::omx::V1_0::Status::OK &&
592 msg.type == Message::Type::EVENT) {
593 packedArgs audioArgs = {eEncoding, comp};
594 ASSERT_NO_FATAL_FAILURE(
595 portReconfiguration(omxNode, observer, iBuffer, oBuffer,
596 kPortIndexInput, kPortIndexOutput, msg,
597 PortMode::PRESET_BYTE_BUFFER, &audioArgs));
598 }
600 if (frameID == (int)Info->size() || frameID == (offset + range)) break;
602 // Dispatch input buffer
603 if ((index = getEmptyBufferID(iBuffer)) < iBuffer->size()) {
604 char* ipBuffer = static_cast<char*>(
605 static_cast<void*>((*iBuffer)[index].mMemory->getPointer()));
606 ASSERT_LE((*Info)[frameID].bytesCount,
607 static_cast<int>((*iBuffer)[index].mMemory->getSize()));
608 eleStream.read(ipBuffer, (*Info)[frameID].bytesCount);
609 ASSERT_EQ(eleStream.gcount(), (*Info)[frameID].bytesCount);
610 flags = (*Info)[frameID].flags;
611 // Indicate to omx core that the buffer contains a full frame worth
612 // of data
613 flags |= OMX_BUFFERFLAG_ENDOFFRAME;
614 // Indicate the omx core that this is the last buffer it needs to
615 // process
616 if (signalEOS && ((frameID == (int)Info->size() - 1) ||
617 (frameID == (offset + range - 1))))
618 flags |= OMX_BUFFERFLAG_EOS;
619 ASSERT_NO_FATAL_FAILURE(dispatchInputBuffer(
620 omxNode, iBuffer, index, (*Info)[frameID].bytesCount, flags,
621 (*Info)[frameID].timestamp));
622 frameID++;
623 iQueued = true;
624 }
625 // Dispatch output buffer
626 if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
627 ASSERT_NO_FATAL_FAILURE(
628 dispatchOutputBuffer(omxNode, oBuffer, index));
629 oQueued = true;
630 }
631 // Reset Counters when either input or output buffer is dispatched
632 if (iQueued || oQueued)
633 timeOut = TIMEOUT_COUNTER_Q;
634 else
635 timeOut--;
636 if (timeOut == 0) {
637 ASSERT_TRUE(false) << "Wait on Input/Output is found indefinite";
638 }
639 }
640 }
642 // set component role
643 TEST_F(AudioDecHidlTest, SetRole) {
644 description("Test Set Component Role");
645 if (disableTest) return;
646 android::hardware::media::omx::V1_0::Status status;
647 status = setRole(omxNode, gEnv->getRole().c_str());
648 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
649 }
651 // port format enumeration
652 TEST_F(AudioDecHidlTest, EnumeratePortFormat) {
653 description("Test Component on Mandatory Port Parameters (Port Format)");
654 if (disableTest) return;
655 android::hardware::media::omx::V1_0::Status status;
656 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
657 status = setRole(omxNode, gEnv->getRole().c_str());
658 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
659 OMX_PORT_PARAM_TYPE params;
660 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
661 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
662 ASSERT_EQ(params.nPorts, 2U);
663 kPortIndexInput = params.nStartPortNumber;
664 kPortIndexOutput = kPortIndexInput + 1;
665 }
666 status = setAudioPortFormat(omxNode, kPortIndexInput, eEncoding);
667 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
668 status = setAudioPortFormat(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM);
669 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
670 }
672 // test port settings reconfiguration, elementary stream decode and timestamp
673 // deviation
674 TEST_F(AudioDecHidlTest, DecodeTest) {
675 description("Tests Port Reconfiguration, Decode and timestamp deviation");
676 if (disableTest) return;
677 android::hardware::media::omx::V1_0::Status status;
678 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
679 status = setRole(omxNode, gEnv->getRole().c_str());
680 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
681 OMX_PORT_PARAM_TYPE params;
682 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
683 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
684 ASSERT_EQ(params.nPorts, 2U);
685 kPortIndexInput = params.nStartPortNumber;
686 kPortIndexOutput = kPortIndexInput + 1;
687 }
688 char mURL[512], info[512];
689 strcpy(mURL, gEnv->getRes().c_str());
690 strcpy(info, gEnv->getRes().c_str());
691 GetURLForComponent(compName, mURL, info);
693 std::ifstream eleStream, eleInfo;
695 eleInfo.open(info);
696 ASSERT_EQ(eleInfo.is_open(), true);
697 android::Vector<FrameData> Info;
698 int bytesCount = 0;
699 uint32_t flags = 0;
700 uint32_t timestamp = 0;
701 timestampDevTest = false;
702 while (1) {
703 if (!(eleInfo >> bytesCount)) break;
704 eleInfo >> flags;
705 eleInfo >> timestamp;
706 Info.push_back({bytesCount, flags, timestamp});
707 if (timestampDevTest && (flags != OMX_BUFFERFLAG_CODECCONFIG))
708 timestampUslist.push_back(timestamp);
709 }
710 eleInfo.close();
712 int32_t nChannels, nSampleRate;
713 // Configure input port
714 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
715 if (compName == raw)
716 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
717 OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
718 32);
719 ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
720 omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
721 // Configure output port
722 // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
723 // configure output PCM port. The port undergoes auto configuration
724 // internally basing on parsed elementary stream information.
725 if (compName != vorbis && compName != opus && compName != raw) {
726 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
727 nChannels, nSampleRate);
728 }
730 android::Vector<BufferInfo> iBuffer, oBuffer;
732 // set state to idle
733 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(omxNode, observer, &iBuffer,
734 &oBuffer, kPortIndexInput,
735 kPortIndexOutput));
736 // set state to executing
737 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
738 // Port Reconfiguration
739 eleStream.open(mURL, std::ifstream::binary);
740 ASSERT_EQ(eleStream.is_open(), true);
741 ASSERT_NO_FATAL_FAILURE(decodeNFrames(
742 omxNode, observer, &iBuffer, &oBuffer, eEncoding, kPortIndexInput,
743 kPortIndexOutput, eleStream, &Info, 0, (int)Info.size(), compName));
744 eleStream.close();
745 ASSERT_NO_FATAL_FAILURE(
746 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
747 kPortIndexInput, kPortIndexOutput, compName));
748 packedArgs audioArgs = {eEncoding, compName};
749 ASSERT_NO_FATAL_FAILURE(testEOS(
750 omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, nullptr,
751 portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs));
752 if (timestampDevTest) EXPECT_EQ(timestampUslist.empty(), true);
753 // set state to idle
754 ASSERT_NO_FATAL_FAILURE(
755 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
756 // set state to executing
757 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
758 &oBuffer, kPortIndexInput,
759 kPortIndexOutput));
760 }
762 // end of sequence test
763 TEST_F(AudioDecHidlTest, EOSTest_M) {
764 description("Test end of stream monkeying");
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 }
778 int32_t nChannels, nSampleRate;
779 // Configure input port
780 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
781 if (compName == raw)
782 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
783 OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
784 32);
785 ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
786 omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
787 // Configure output port
788 // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
789 // configure output PCM port. The port undergoes auto configuration
790 // internally basing on parsed elementary stream information.
791 if (compName != vorbis && compName != opus && compName != raw) {
792 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
793 nChannels, nSampleRate);
794 }
796 android::Vector<BufferInfo> iBuffer, oBuffer;
798 // set state to idle
799 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(omxNode, observer, &iBuffer,
800 &oBuffer, kPortIndexInput,
801 kPortIndexOutput));
802 // set state to executing
803 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
805 // request EOS at the start
806 packedArgs audioArgs = {eEncoding, compName};
807 ASSERT_NO_FATAL_FAILURE(testEOS(
808 omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, nullptr,
809 portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs));
810 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
811 kPortIndexInput, kPortIndexOutput));
812 EXPECT_GE(framesReceived, 0U);
813 framesReceived = 0;
814 timestampUs = 0;
816 // set state to idle
817 ASSERT_NO_FATAL_FAILURE(
818 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
820 // set state to executing
821 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
822 &oBuffer, kPortIndexInput,
823 kPortIndexOutput));
824 }
826 // end of sequence test
827 TEST_F(AudioDecHidlTest, ThumbnailTest) {
828 description("Test Request for thumbnail");
829 if (disableTest) return;
830 android::hardware::media::omx::V1_0::Status status;
831 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
832 status = setRole(omxNode, gEnv->getRole().c_str());
833 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
834 OMX_PORT_PARAM_TYPE params;
835 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
836 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
837 ASSERT_EQ(params.nPorts, 2U);
838 kPortIndexInput = params.nStartPortNumber;
839 kPortIndexOutput = kPortIndexInput + 1;
840 }
841 char mURL[512], info[512];
842 strcpy(mURL, gEnv->getRes().c_str());
843 strcpy(info, gEnv->getRes().c_str());
844 GetURLForComponent(compName, mURL, info);
846 std::ifstream eleStream, eleInfo;
848 eleInfo.open(info);
849 ASSERT_EQ(eleInfo.is_open(), true);
850 android::Vector<FrameData> Info;
851 int bytesCount = 0;
852 uint32_t flags = 0;
853 uint32_t timestamp = 0;
854 while (1) {
855 if (!(eleInfo >> bytesCount)) break;
856 eleInfo >> flags;
857 eleInfo >> timestamp;
858 Info.push_back({bytesCount, flags, timestamp});
859 }
860 eleInfo.close();
862 int32_t nChannels, nSampleRate;
863 // Configure input port
864 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
865 if (compName == raw)
866 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
867 OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
868 32);
869 ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
870 omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
871 // Configure output port
872 // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
873 // configure output PCM port. The port undergoes auto configuration
874 // internally basing on parsed elementary stream information.
875 if (compName != vorbis && compName != opus && compName != raw) {
876 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
877 nChannels, nSampleRate);
878 }
880 android::Vector<BufferInfo> iBuffer, oBuffer;
882 // set state to idle
883 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(omxNode, observer, &iBuffer,
884 &oBuffer, kPortIndexInput,
885 kPortIndexOutput));
886 // set state to executing
887 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
889 // request EOS for thumbnail
890 // signal EOS flag with last frame
891 size_t i = 0;
892 while (!(Info[i].flags & OMX_BUFFERFLAG_SYNCFRAME)) i++;
893 eleStream.open(mURL, std::ifstream::binary);
894 ASSERT_EQ(eleStream.is_open(), true);
895 ASSERT_NO_FATAL_FAILURE(decodeNFrames(
896 omxNode, observer, &iBuffer, &oBuffer, eEncoding, kPortIndexInput,
897 kPortIndexOutput, eleStream, &Info, 0, i + 1, compName));
898 eleStream.close();
899 ASSERT_NO_FATAL_FAILURE(
900 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
901 kPortIndexInput, kPortIndexOutput, compName));
902 packedArgs audioArgs = {eEncoding, compName};
903 ASSERT_NO_FATAL_FAILURE(testEOS(
904 omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, nullptr,
905 portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs));
906 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
907 kPortIndexInput, kPortIndexOutput));
908 EXPECT_GE(framesReceived, 1U);
909 framesReceived = 0;
910 timestampUs = 0;
912 // signal EOS flag after last frame
913 eleStream.open(mURL, std::ifstream::binary);
914 ASSERT_EQ(eleStream.is_open(), true);
915 ASSERT_NO_FATAL_FAILURE(decodeNFrames(
916 omxNode, observer, &iBuffer, &oBuffer, eEncoding, kPortIndexInput,
917 kPortIndexOutput, eleStream, &Info, 0, i + 1, compName, false));
918 eleStream.close();
919 ASSERT_NO_FATAL_FAILURE(
920 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
921 kPortIndexInput, kPortIndexOutput, compName));
922 ASSERT_NO_FATAL_FAILURE(testEOS(
923 omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, nullptr,
924 portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs));
925 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
926 kPortIndexInput, kPortIndexOutput));
927 EXPECT_GE(framesReceived, 1U);
928 framesReceived = 0;
929 timestampUs = 0;
931 // set state to idle
932 ASSERT_NO_FATAL_FAILURE(
933 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
934 // set state to executing
935 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
936 &oBuffer, kPortIndexInput,
937 kPortIndexOutput));
938 }
940 // end of sequence test
941 TEST_F(AudioDecHidlTest, SimpleEOSTest) {
942 description("Test end of stream");
943 if (disableTest) return;
944 android::hardware::media::omx::V1_0::Status status;
945 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
946 status = setRole(omxNode, gEnv->getRole().c_str());
947 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
948 OMX_PORT_PARAM_TYPE params;
949 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
950 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
951 ASSERT_EQ(params.nPorts, 2U);
952 kPortIndexInput = params.nStartPortNumber;
953 kPortIndexOutput = kPortIndexInput + 1;
954 }
955 char mURL[512], info[512];
956 strcpy(mURL, gEnv->getRes().c_str());
957 strcpy(info, gEnv->getRes().c_str());
958 GetURLForComponent(compName, mURL, info);
960 std::ifstream eleStream, eleInfo;
962 eleInfo.open(info);
963 ASSERT_EQ(eleInfo.is_open(), true);
964 android::Vector<FrameData> Info;
965 int bytesCount = 0;
966 uint32_t flags = 0;
967 uint32_t timestamp = 0;
968 while (1) {
969 if (!(eleInfo >> bytesCount)) break;
970 eleInfo >> flags;
971 eleInfo >> timestamp;
972 Info.push_back({bytesCount, flags, timestamp});
973 }
974 eleInfo.close();
976 int32_t nChannels, nSampleRate;
977 // Configure input port
978 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
979 if (compName == raw)
980 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
981 OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
982 32);
983 ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
984 omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
985 // Configure output port
986 // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
987 // configure output PCM port. The port undergoes auto configuration
988 // internally basing on parsed elementary stream information.
989 if (compName != vorbis && compName != opus && compName != raw) {
990 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
991 nChannels, nSampleRate);
992 }
994 android::Vector<BufferInfo> iBuffer, oBuffer;
996 // set state to idle
997 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(omxNode, observer, &iBuffer,
998 &oBuffer, kPortIndexInput,
999 kPortIndexOutput));
1000 // set state to executing
1001 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
1003 // request EOS at the end
1004 eleStream.open(mURL, std::ifstream::binary);
1005 ASSERT_EQ(eleStream.is_open(), true);
1006 ASSERT_NO_FATAL_FAILURE(decodeNFrames(omxNode, observer, &iBuffer, &oBuffer,
1007 eEncoding, kPortIndexInput,
1008 kPortIndexOutput, eleStream, &Info, 0,
1009 (int)Info.size(), compName, false));
1010 eleStream.close();
1011 ASSERT_NO_FATAL_FAILURE(
1012 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
1013 kPortIndexInput, kPortIndexOutput, compName));
1014 packedArgs audioArgs = {eEncoding, compName};
1015 ASSERT_NO_FATAL_FAILURE(testEOS(
1016 omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, nullptr,
1017 portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs));
1018 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
1019 kPortIndexInput, kPortIndexOutput));
1020 framesReceived = 0;
1021 timestampUs = 0;
1023 // set state to idle
1024 ASSERT_NO_FATAL_FAILURE(
1025 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
1026 // set state to executing
1027 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
1028 &oBuffer, kPortIndexInput,
1029 kPortIndexOutput));
1030 }
1032 // test input/output port flush
1033 TEST_F(AudioDecHidlTest, FlushTest) {
1034 description("Test Flush");
1035 if (disableTest) return;
1036 android::hardware::media::omx::V1_0::Status status;
1037 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1038 status = setRole(omxNode, gEnv->getRole().c_str());
1039 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1040 OMX_PORT_PARAM_TYPE params;
1041 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms);
1042 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1043 ASSERT_EQ(params.nPorts, 2U);
1044 kPortIndexInput = params.nStartPortNumber;
1045 kPortIndexOutput = kPortIndexInput + 1;
1046 }
1047 char mURL[512], info[512];
1048 strcpy(mURL, gEnv->getRes().c_str());
1049 strcpy(info, gEnv->getRes().c_str());
1050 GetURLForComponent(compName, mURL, info);
1052 std::ifstream eleStream, eleInfo;
1054 eleInfo.open(info);
1055 ASSERT_EQ(eleInfo.is_open(), true);
1056 android::Vector<FrameData> Info;
1057 int bytesCount = 0;
1058 uint32_t flags = 0;
1059 uint32_t timestamp = 0;
1060 while (1) {
1061 if (!(eleInfo >> bytesCount)) break;
1062 eleInfo >> flags;
1063 eleInfo >> timestamp;
1064 Info.push_back({bytesCount, flags, timestamp});
1065 }
1066 eleInfo.close();
1068 int32_t nChannels, nSampleRate;
1069 // Configure input port
1070 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
1071 if (compName == raw)
1072 setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
1073 OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
1074 32);
1075 ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(
1076 omxNode, kPortIndexInput, eEncoding, &nChannels, &nSampleRate));
1077 // Configure output port
1078 // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
1079 // configure output PCM port. The port undergoes auto configuration
1080 // internally basing on parsed elementary stream information.
1081 if (compName != vorbis && compName != opus && compName != raw) {
1082 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
1083 nChannels, nSampleRate);
1084 }
1086 android::Vector<BufferInfo> iBuffer, oBuffer;
1088 // set state to idle
1089 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(omxNode, observer, &iBuffer,
1090 &oBuffer, kPortIndexInput,
1091 kPortIndexOutput));
1092 // set state to executing
1093 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
1095 // Decode 128 frames and flush. here 128 is chosen to ensure there is a key
1096 // frame after this so that the below section can be convered for all
1097 // components
1098 int nFrames = 128;
1099 eleStream.open(mURL, std::ifstream::binary);
1100 ASSERT_EQ(eleStream.is_open(), true);
1101 ASSERT_NO_FATAL_FAILURE(decodeNFrames(
1102 omxNode, observer, &iBuffer, &oBuffer, eEncoding, kPortIndexInput,
1103 kPortIndexOutput, eleStream, &Info, 0, nFrames, compName, false));
1104 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
1105 kPortIndexInput, kPortIndexOutput));
1106 framesReceived = 0;
1108 // Seek to next key frame and start decoding till the end
1109 int index = nFrames;
1110 bool keyFrame = false;
1111 while (index < (int)Info.size()) {
1112 if ((Info[index].flags & OMX_BUFFERFLAG_SYNCFRAME) ==
1113 OMX_BUFFERFLAG_SYNCFRAME) {
1114 timestampUs = Info[index - 1].timestamp;
1115 keyFrame = true;
1116 break;
1117 }
1118 eleStream.ignore(Info[index].bytesCount);
1119 index++;
1120 }
1121 if (keyFrame) {
1122 ASSERT_NO_FATAL_FAILURE(
1123 decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
1124 kPortIndexInput, kPortIndexOutput, eleStream, &Info,
1125 index, Info.size() - index, compName, false));
1126 }
1127 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer,
1128 kPortIndexInput, kPortIndexOutput));
1129 framesReceived = 0;
1131 // set state to idle
1132 ASSERT_NO_FATAL_FAILURE(
1133 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
1134 // set state to executing
1135 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
1136 &oBuffer, kPortIndexInput,
1137 kPortIndexOutput));
1138 }
1140 int main(int argc, char** argv) {
1141 gEnv = new ComponentTestEnvironment();
1142 ::testing::AddGlobalTestEnvironment(gEnv);
1143 ::testing::InitGoogleTest(&argc, argv);
1144 gEnv->init(&argc, argv);
1145 int status = gEnv->initFromOptions(argc, argv);
1146 if (status == 0) {
1147 status = RUN_ALL_TESTS();
1148 ALOGI("Test result = %d", status);
1149 }
1150 return status;
1151 }