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