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 32using ::android::hardware::media::omx::V1_0::IOmx; 33using ::android::hardware::media::omx::V1_0::IOmxObserver; 34using ::android::hardware::media::omx::V1_0::IOmxNode; 35using ::android::hardware::media::omx::V1_0::Message; 36using ::android::hardware::media::omx::V1_0::CodecBuffer; 37using ::android::hardware::media::omx::V1_0::PortMode; 38using ::android::hidl::allocator::V1_0::IAllocator; 39using ::android::hidl::memory::V1_0::IMemory; 40using ::android::hidl::memory::V1_0::IMapper; 41using ::android::hardware::Return; 42using ::android::hardware::Void; 43using ::android::hardware::hidl_vec; 44using ::android::hardware::hidl_string; 45using ::android::sp; 46 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> 52 53// A class for test environment setup 54class ComponentTestEnvironment : public ::testing::Environment { 55 public: 56 virtual void SetUp() {} 57 virtual void TearDown() {} 58 59 ComponentTestEnvironment() : instance("default"), res("/sdcard/media/") {} 60 61 void setInstance(const char* _instance) { instance = _instance; } 62 63 void setComponent(const char* _component) { component = _component; } 64 65 void setRole(const char* _role) { role = _role; } 66 67 void setRes(const char* _res) { res = _res; } 68 69 const hidl_string getInstance() const { return instance; } 70 71 const hidl_string getComponent() const { return component; } 72 73 const hidl_string getRole() const { return role; } 74 75 const hidl_string getRes() const { return res; } 76 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}}; 84 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 } 91 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 } 109 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 } 124 125 private: 126 hidl_string instance; 127 hidl_string component; 128 hidl_string role; 129 hidl_string res; 130}; 131 132static ComponentTestEnvironment* gEnv = nullptr; 133 134// audio decoder test fixture class 135class 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 } 146 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 } 230 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 } 242 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 } 300 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 }; 316 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; 328 329 protected: 330 static void description(const std::string& description) { 331 RecordProperty("description", description); 332 } 333}; 334 335// Set Default port param. 336void 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; 343 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); 348 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); 354 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} 368 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. 373void 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; 379 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} 462 463// LookUpTable of clips and metadata for component testing 464void 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 }; 502 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} 511 512// port settings reconfiguration during runtime. reconfigures sample rate and 513// number 514typedef struct { 515 OMX_AUDIO_CODINGTYPE eEncoding; 516 AudioDecHidlTest::standardComp comp; 517} packedArgs; 518void 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; 528 529 if (msg.data.eventData.event == OMX_EventPortSettingsChanged) { 530 ASSERT_EQ(msg.data.eventData.data1, kPortIndexOutput); 531 532 status = omxNode->sendCommand(toRawCommandType(OMX_CommandPortDisable), 533 kPortIndexOutput); 534 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 535 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); 555 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 } 573 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); 579 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); 585 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); 594 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} 607 608// blocking call to ensures application to Wait till all the inputs are consumed 609void 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; 618 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; 638 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} 648 649// Decode N Frames 650void 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; 664 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 } 678 679 if (frameID == (int)Info->size() || frameID == (offset + range)) break; 680 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} 720 721// set component role 722TEST_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} 729 730// port format enumeration 731TEST_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} 750 751// test port settings reconfiguration, elementary stream decode and timestamp 752// deviation 753TEST_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); 771 772 std::ifstream eleStream, eleInfo; 773 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(); 790 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 } 808 809 android::Vector<BufferInfo> iBuffer, oBuffer; 810 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} 840 841// end of sequence test 842TEST_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 } 856 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 } 874 875 android::Vector<BufferInfo> iBuffer, oBuffer; 876 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)); 883 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; 894 895 // set state to idle 896 ASSERT_NO_FATAL_FAILURE( 897 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer)); 898 899 // set state to executing 900 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer, 901 &oBuffer, kPortIndexInput, 902 kPortIndexOutput)); 903} 904 905// end of sequence test 906TEST_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); 924 925 std::ifstream eleStream, eleInfo; 926 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(); 940 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 } 958 959 android::Vector<BufferInfo> iBuffer, oBuffer; 960 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)); 967 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; 990 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; 1009 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} 1018 1019// end of sequence test 1020TEST_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); 1038 1039 std::ifstream eleStream, eleInfo; 1040 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(); 1054 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 } 1072 1073 android::Vector<BufferInfo> iBuffer, oBuffer; 1074 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)); 1081 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; 1101 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} 1110 1111// test input/output port flush 1112TEST_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); 1130 1131 std::ifstream eleStream, eleInfo; 1132 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(); 1146 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 } 1164 1165 android::Vector<BufferInfo> iBuffer, oBuffer; 1166 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)); 1173 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; 1186 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; 1209 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} 1218 1219int 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} 1230