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_video_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 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; 46 47 #include <VtsHalHidlTargetTestBase.h> 48 #include <getopt.h> 49 #include <media/hardware/HardwareAPI.h> 50 #include <media_hidl_test_common.h> 51 #include <media_video_hidl_test_common.h> 52 #include <fstream> 53 54 static ComponentTestEnvironment* gEnv = nullptr; 55 56 // video decoder test fixture class 57 class VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase { 58 private: 59 typedef ::testing::VtsHalHidlTargetTestBase Super; 60 public: 61 ::std::string getTestCaseInfo() const override { 62 return ::std::string() + 63 "Component: " + gEnv->getComponent().c_str() + " | " + 64 "Role: " + gEnv->getRole().c_str() + " | " + 65 "Instance: " + gEnv->getInstance().c_str() + " | " + 66 "Res: " + gEnv->getRes().c_str(); 67 } 68 69 virtual void SetUp() override { 70 Super::SetUp(); 71 disableTest = false; 72 android::hardware::media::omx::V1_0::Status status; 73 omx = Super::getService<IOmx>(gEnv->getInstance()); 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 (strncmp(gEnv->getComponent().c_str(), "OMX.", 4) != 0) 81 disableTest = true; 82 EXPECT_TRUE(omx->allocateNode( 83 gEnv->getComponent(), observer, 84 [&](android::hardware::media::omx::V1_0::Status _s, 85 sp<IOmxNode> const& _nl) { 86 status = _s; 87 this->omxNode = _nl; 88 }) 89 .isOk()); 90 if (status == android::hardware::media::omx::V1_0::Status::NAME_NOT_FOUND) { 91 disableTest = true; 92 std::cout << "[ WARN ] Test Disabled, component not present\n"; 93 return; 94 } 95 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 96 ASSERT_NE(omxNode, nullptr); 97 ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role"; 98 struct StringToName { 99 const char* Name; 100 standardComp CompName; 101 }; 102 const StringToName kStringToName[] = { 103 {"h263", h263}, {"avc", avc}, {"mpeg2", mpeg2}, {"mpeg4", mpeg4}, 104 {"hevc", hevc}, {"vp8", vp8}, {"vp9", vp9}, 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, gEnv->getRole().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 CompToCompression { 122 standardComp CompName; 123 OMX_VIDEO_CODINGTYPE eCompressionFormat; 124 }; 125 static const CompToCompression kCompToCompression[] = { 126 {h263, OMX_VIDEO_CodingH263}, {avc, OMX_VIDEO_CodingAVC}, 127 {mpeg2, OMX_VIDEO_CodingMPEG2}, {mpeg4, OMX_VIDEO_CodingMPEG4}, 128 {hevc, OMX_VIDEO_CodingHEVC}, {vp8, OMX_VIDEO_CodingVP8}, 129 {vp9, OMX_VIDEO_CodingVP9}, 130 }; 131 static const size_t kNumCompToCompression = 132 sizeof(kCompToCompression) / sizeof(kCompToCompression[0]); 133 size_t i; 134 for (i = 0; i < kNumCompToCompression; ++i) { 135 if (kCompToCompression[i].CompName == compName) { 136 eCompressionFormat = kCompToCompression[i].eCompressionFormat; 137 break; 138 } 139 } 140 if (i == kNumCompToCompression) disableTest = true; 141 portMode[0] = portMode[1] = PortMode::PRESET_BYTE_BUFFER; 142 eosFlag = false; 143 framesReceived = 0; 144 timestampUs = 0; 145 timestampDevTest = false; 146 isSecure = false; 147 portSettingsChange = false; 148 size_t suffixLen = strlen(".secure"); 149 if (strlen(gEnv->getComponent().c_str()) >= suffixLen) { 150 isSecure = 151 !strcmp(gEnv->getComponent().c_str() + 152 strlen(gEnv->getComponent().c_str()) - suffixLen, 153 ".secure"); 154 } 155 if (isSecure) disableTest = true; 156 if (disableTest) std::cout << "[ WARN ] Test Disabled \n"; 157 } 158 159 virtual void TearDown() override { 160 if (omxNode != nullptr) { 161 // If you have encountered a fatal failure, it is possible that 162 // freeNode() will not go through. Instead of hanging the app. 163 // let it pass through and report errors 164 if (::testing::Test::HasFatalFailure()) return; 165 EXPECT_TRUE((omxNode->freeNode()).isOk()); 166 omxNode = nullptr; 167 } 168 Super::TearDown(); 169 } 170 171 // callback function to process messages received by onMessages() from IL 172 // client. 173 void handleMessage(Message msg, const BufferInfo* buffer) { 174 (void)buffer; 175 if (msg.type == Message::Type::FILL_BUFFER_DONE) { 176 if (msg.data.extendedBufferData.flags & OMX_BUFFERFLAG_EOS) { 177 eosFlag = true; 178 } 179 if (msg.data.extendedBufferData.rangeLength != 0) { 180 framesReceived += 1; 181 // For decoder components current timestamp always exceeds 182 // previous timestamp 183 EXPECT_GE(msg.data.extendedBufferData.timestampUs, timestampUs); 184 timestampUs = msg.data.extendedBufferData.timestampUs; 185 // Test if current timestamp is among the list of queued 186 // timestamps 187 if (timestampDevTest) { 188 bool tsHit = false; 189 android::List<uint64_t>::iterator it = 190 timestampUslist.begin(); 191 while (it != timestampUslist.end()) { 192 if (*it == timestampUs) { 193 timestampUslist.erase(it); 194 tsHit = true; 195 break; 196 } 197 it++; 198 } 199 if (tsHit == false) { 200 if (timestampUslist.empty() == false) { 201 EXPECT_EQ(tsHit, true) 202 << "TimeStamp not recognized"; 203 } else { 204 std::cout << "[ INFO ] Received non-zero " 205 "output / TimeStamp not recognized \n"; 206 } 207 } 208 } 209 #define WRITE_OUTPUT 0 210 #if WRITE_OUTPUT 211 static int count = 0; 212 FILE* ofp = nullptr; 213 if (count) 214 ofp = fopen("out.bin", "ab"); 215 else 216 ofp = fopen("out.bin", "wb"); 217 if (ofp != nullptr && 218 portMode[1] == PortMode::PRESET_BYTE_BUFFER) { 219 fwrite(static_cast<void*>(buffer->mMemory->getPointer()), 220 sizeof(char), 221 msg.data.extendedBufferData.rangeLength, ofp); 222 fclose(ofp); 223 count++; 224 } 225 #endif 226 } 227 } else if (msg.type == Message::Type::EVENT) { 228 if (msg.data.eventData.event == OMX_EventPortSettingsChanged) { 229 if ((msg.data.eventData.data2 == OMX_IndexParamPortDefinition || 230 msg.data.eventData.data2 == 0)) { 231 portSettingsChange = true; 232 } 233 } 234 } 235 } 236 237 enum standardComp { 238 h263, 239 avc, 240 mpeg2, 241 mpeg4, 242 hevc, 243 vp8, 244 vp9, 245 unknown_comp, 246 }; 247 248 sp<IOmx> omx; 249 sp<CodecObserver> observer; 250 sp<IOmxNode> omxNode; 251 standardComp compName; 252 OMX_VIDEO_CODINGTYPE eCompressionFormat; 253 bool disableTest; 254 PortMode portMode[2]; 255 bool eosFlag; 256 uint32_t framesReceived; 257 uint64_t timestampUs; 258 ::android::List<uint64_t> timestampUslist; 259 bool timestampDevTest; 260 bool isSecure; 261 bool portSettingsChange; 262 263 protected: 264 static void description(const std::string& description) { 265 RecordProperty("description", description); 266 } 267 }; 268 269 // Set Default port param. 270 void setDefaultPortParam(sp<IOmxNode> omxNode, OMX_U32 portIndex, 271 OMX_VIDEO_CODINGTYPE eCompressionFormat, 272 OMX_COLOR_FORMATTYPE eColorFormat, 273 OMX_U32 nFrameWidth = 352, OMX_U32 nFrameHeight = 288, 274 OMX_U32 nBitrate = 0, 275 OMX_U32 xFramerate = (24U << 16)) { 276 switch ((int)eCompressionFormat) { 277 case OMX_VIDEO_CodingUnused: 278 setupRAWPort(omxNode, portIndex, nFrameWidth, nFrameHeight, 279 nBitrate, xFramerate, eColorFormat); 280 break; 281 default: 282 break; 283 } 284 } 285 286 // In decoder components, often the input port parameters get updated upon 287 // parsing the header of elementary stream. Client needs to collect this 288 // information to reconfigure other ports that share data with this input 289 // port. 290 void getInputChannelInfo(sp<IOmxNode> omxNode, OMX_U32 kPortIndexInput, 291 uint32_t* nFrameWidth, uint32_t* nFrameHeight, 292 uint32_t* xFramerate) { 293 android::hardware::media::omx::V1_0::Status status; 294 *nFrameWidth = 352; 295 *nFrameHeight = 288; 296 *xFramerate = (24U << 16); 297 298 OMX_PARAM_PORTDEFINITIONTYPE portDef; 299 status = getPortParam(omxNode, OMX_IndexParamPortDefinition, 300 kPortIndexInput, &portDef); 301 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 302 if (status == ::android::hardware::media::omx::V1_0::Status::OK) { 303 *nFrameWidth = portDef.format.video.nFrameWidth; 304 *nFrameHeight = portDef.format.video.nFrameHeight; 305 *xFramerate = portDef.format.video.xFramerate; 306 } 307 } 308 309 // number of elementary streams per component 310 #define STREAM_COUNT 2 311 // LookUpTable of clips and metadata for component testing 312 void GetURLForComponent(VideoDecHidlTest::standardComp comp, char* mURL, 313 char* info, size_t streamIndex = 1) { 314 struct CompToURL { 315 VideoDecHidlTest::standardComp comp; 316 const char mURL[STREAM_COUNT][512]; 317 const char info[STREAM_COUNT][512]; 318 }; 319 ASSERT_TRUE(streamIndex < STREAM_COUNT); 320 321 static const CompToURL kCompToURL[] = { 322 {VideoDecHidlTest::standardComp::avc, 323 {"bbb_avc_176x144_300kbps_60fps.h264", 324 "bbb_avc_640x360_768kbps_30fps.h264"}, 325 {"bbb_avc_176x144_300kbps_60fps.info", 326 "bbb_avc_640x360_768kbps_30fps.info"}}, 327 {VideoDecHidlTest::standardComp::hevc, 328 {"bbb_hevc_176x144_176kbps_60fps.hevc", 329 "bbb_hevc_640x360_1600kbps_30fps.hevc"}, 330 {"bbb_hevc_176x144_176kbps_60fps.info", 331 "bbb_hevc_640x360_1600kbps_30fps.info"}}, 332 {VideoDecHidlTest::standardComp::mpeg2, 333 {"bbb_mpeg2_176x144_105kbps_25fps.m2v", 334 "bbb_mpeg2_352x288_1mbps_60fps.m2v"}, 335 {"bbb_mpeg2_176x144_105kbps_25fps.info", 336 "bbb_mpeg2_352x288_1mbps_60fps.info"}}, 337 {VideoDecHidlTest::standardComp::h263, 338 {"", "bbb_h263_352x288_300kbps_12fps.h263"}, 339 {"", "bbb_h263_352x288_300kbps_12fps.info"}}, 340 {VideoDecHidlTest::standardComp::mpeg4, 341 {"", "bbb_mpeg4_352x288_512kbps_30fps.m4v"}, 342 {"", "bbb_mpeg4_352x288_512kbps_30fps.info"}}, 343 {VideoDecHidlTest::standardComp::vp8, 344 {"bbb_vp8_176x144_240kbps_60fps.vp8", 345 "bbb_vp8_640x360_2mbps_30fps.vp8"}, 346 {"bbb_vp8_176x144_240kbps_60fps.info", 347 "bbb_vp8_640x360_2mbps_30fps.info"}}, 348 {VideoDecHidlTest::standardComp::vp9, 349 {"bbb_vp9_176x144_285kbps_60fps.vp9", 350 "bbb_vp9_640x360_1600kbps_30fps.vp9"}, 351 {"bbb_vp9_176x144_285kbps_60fps.info", 352 "bbb_vp9_640x360_1600kbps_30fps.info"}}, 353 }; 354 355 for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) { 356 if (kCompToURL[i].comp == comp) { 357 strcat(mURL, kCompToURL[i].mURL[streamIndex]); 358 strcat(info, kCompToURL[i].info[streamIndex]); 359 return; 360 } 361 } 362 } 363 364 // port settings reconfiguration during runtime. reconfigures frame dimensions 365 void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer, 366 android::Vector<BufferInfo>* iBuffer, 367 android::Vector<BufferInfo>* oBuffer, 368 OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput, 369 Message msg, PortMode oPortMode, void* args) { 370 android::hardware::media::omx::V1_0::Status status; 371 (void)args; 372 373 if (msg.data.eventData.event == OMX_EventPortSettingsChanged) { 374 ASSERT_EQ(msg.data.eventData.data1, kPortIndexOutput); 375 if (msg.data.eventData.data2 == OMX_IndexParamPortDefinition || 376 msg.data.eventData.data2 == 0) { 377 // Components can send various kinds of port settings changed events 378 // all at once. Before committing to a full port reconfiguration, 379 // defer any events waiting in the queue to be addressed to a later 380 // point. 381 android::List<Message> msgQueueDefer; 382 while (1) { 383 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, 384 iBuffer, oBuffer); 385 if (status != 386 android::hardware::media::omx::V1_0::Status::TIMED_OUT) { 387 msgQueueDefer.push_back(msg); 388 continue; 389 } else 390 break; 391 } 392 status = omxNode->sendCommand( 393 toRawCommandType(OMX_CommandPortDisable), kPortIndexOutput); 394 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 395 396 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, 397 oBuffer); 398 if (status == 399 android::hardware::media::omx::V1_0::Status::TIMED_OUT) { 400 for (size_t i = 0; i < oBuffer->size(); ++i) { 401 // test if client got all its buffers back 402 EXPECT_EQ((*oBuffer)[i].owner, client); 403 // free the buffers 404 status = 405 omxNode->freeBuffer(kPortIndexOutput, (*oBuffer)[i].id); 406 ASSERT_EQ(status, 407 android::hardware::media::omx::V1_0::Status::OK); 408 } 409 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, 410 iBuffer, oBuffer); 411 ASSERT_EQ(status, 412 android::hardware::media::omx::V1_0::Status::OK); 413 ASSERT_EQ(msg.type, Message::Type::EVENT); 414 ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete); 415 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortDisable); 416 ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput); 417 418 // set Port Params 419 uint32_t nFrameWidth, nFrameHeight, xFramerate; 420 getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, 421 &nFrameHeight, &xFramerate); 422 // get configured color format 423 OMX_PARAM_PORTDEFINITIONTYPE portDef; 424 status = getPortParam(omxNode, OMX_IndexParamPortDefinition, 425 kPortIndexOutput, &portDef); 426 setDefaultPortParam(omxNode, kPortIndexOutput, 427 OMX_VIDEO_CodingUnused, 428 portDef.format.video.eColorFormat, 429 nFrameWidth, nFrameHeight, 0, xFramerate); 430 431 // If you can disable a port, then you should be able to 432 // enable it as well 433 status = omxNode->sendCommand( 434 toRawCommandType(OMX_CommandPortEnable), kPortIndexOutput); 435 ASSERT_EQ(status, 436 android::hardware::media::omx::V1_0::Status::OK); 437 438 // do not enable the port until all the buffers are supplied 439 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, 440 iBuffer, oBuffer); 441 ASSERT_EQ( 442 status, 443 android::hardware::media::omx::V1_0::Status::TIMED_OUT); 444 445 ASSERT_NO_FATAL_FAILURE(allocatePortBuffers( 446 omxNode, oBuffer, kPortIndexOutput, oPortMode, true)); 447 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, 448 iBuffer, oBuffer); 449 ASSERT_EQ(status, 450 android::hardware::media::omx::V1_0::Status::OK); 451 ASSERT_EQ(msg.type, Message::Type::EVENT); 452 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortEnable); 453 ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput); 454 455 // Push back deferred messages to the list 456 android::List<Message>::iterator it = msgQueueDefer.begin(); 457 while (it != msgQueueDefer.end()) { 458 status = omxNode->dispatchMessage(*it); 459 ASSERT_EQ( 460 status, 461 ::android::hardware::media::omx::V1_0::Status::OK); 462 it++; 463 } 464 465 // dispatch output buffers 466 for (size_t i = 0; i < oBuffer->size(); i++) { 467 ASSERT_NO_FATAL_FAILURE( 468 dispatchOutputBuffer(omxNode, oBuffer, i, oPortMode)); 469 } 470 } else { 471 ASSERT_TRUE(false); 472 } 473 } else if (msg.data.eventData.data2 == 474 OMX_IndexConfigCommonOutputCrop) { 475 std::cout << "[ INFO ] OMX_EventPortSettingsChanged/ " 476 "OMX_IndexConfigCommonOutputCrop not handled \n"; 477 } else if (msg.data.eventData.data2 == OMX_IndexVendorStartUnused + 3) { 478 std::cout << "[ INFO ] OMX_EventPortSettingsChanged/ " 479 "kDescribeColorAspectsIndex not handled \n"; 480 } 481 } else if (msg.data.eventData.event == OMX_EventError) { 482 std::cerr << "[ ERROR ] OMX_EventError/ " 483 "Decode Frame Call might be failed \n"; 484 ASSERT_TRUE(false); 485 } else { 486 // something unexpected happened 487 ASSERT_TRUE(false); 488 } 489 } 490 491 // blocking call to ensures application to Wait till all the inputs are consumed 492 void waitOnInputConsumption(sp<IOmxNode> omxNode, sp<CodecObserver> observer, 493 android::Vector<BufferInfo>* iBuffer, 494 android::Vector<BufferInfo>* oBuffer, 495 OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput, 496 PortMode oPortMode) { 497 android::hardware::media::omx::V1_0::Status status; 498 Message msg; 499 int timeOut = TIMEOUT_COUNTER_Q; 500 501 while (timeOut--) { 502 size_t i = 0; 503 status = 504 observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer); 505 if (status == android::hardware::media::omx::V1_0::Status::OK) { 506 ASSERT_EQ(msg.type, Message::Type::EVENT); 507 ASSERT_NO_FATAL_FAILURE(portReconfiguration( 508 omxNode, observer, iBuffer, oBuffer, kPortIndexInput, 509 kPortIndexOutput, msg, oPortMode, nullptr)); 510 } 511 // status == TIMED_OUT, it could be due to process time being large 512 // than DEFAULT_TIMEOUT or component needs output buffers to start 513 // processing. 514 for (; i < iBuffer->size(); i++) { 515 if ((*iBuffer)[i].owner != client) break; 516 } 517 if (i == iBuffer->size()) break; 518 519 // Dispatch an output buffer assuming outQueue.empty() is true 520 size_t index; 521 if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) { 522 ASSERT_NO_FATAL_FAILURE( 523 dispatchOutputBuffer(omxNode, oBuffer, index, oPortMode)); 524 timeOut = TIMEOUT_COUNTER_Q; 525 } 526 } 527 } 528 529 // Decode N Frames 530 void decodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer, 531 android::Vector<BufferInfo>* iBuffer, 532 android::Vector<BufferInfo>* oBuffer, 533 OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput, 534 std::ifstream& eleStream, android::Vector<FrameData>* Info, 535 int offset, int range, PortMode oPortMode, 536 bool signalEOS = true) { 537 android::hardware::media::omx::V1_0::Status status; 538 Message msg; 539 size_t index; 540 uint32_t flags = 0; 541 int frameID = offset; 542 int timeOut = TIMEOUT_COUNTER_Q; 543 bool iQueued, oQueued; 544 545 while (1) { 546 iQueued = oQueued = false; 547 status = 548 observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer); 549 // Port Reconfiguration 550 if (status == android::hardware::media::omx::V1_0::Status::OK && 551 msg.type == Message::Type::EVENT) { 552 ASSERT_NO_FATAL_FAILURE(portReconfiguration( 553 omxNode, observer, iBuffer, oBuffer, kPortIndexInput, 554 kPortIndexOutput, msg, oPortMode, nullptr)); 555 } 556 557 if (frameID == (int)Info->size() || frameID == (offset + range)) break; 558 559 // Dispatch input buffer 560 if ((index = getEmptyBufferID(iBuffer)) < iBuffer->size()) { 561 char* ipBuffer = static_cast<char*>( 562 static_cast<void*>((*iBuffer)[index].mMemory->getPointer())); 563 ASSERT_LE((*Info)[frameID].bytesCount, 564 static_cast<int>((*iBuffer)[index].mMemory->getSize())); 565 eleStream.read(ipBuffer, (*Info)[frameID].bytesCount); 566 ASSERT_EQ(eleStream.gcount(), (*Info)[frameID].bytesCount); 567 flags = (*Info)[frameID].flags; 568 // Indicate to omx core that the buffer contains a full frame worth 569 // of data 570 flags |= OMX_BUFFERFLAG_ENDOFFRAME; 571 // Indicate the omx core that this is the last buffer it needs to 572 // process 573 if (signalEOS && ((frameID == (int)Info->size() - 1) || 574 (frameID == (offset + range - 1)))) 575 flags |= OMX_BUFFERFLAG_EOS; 576 ASSERT_NO_FATAL_FAILURE(dispatchInputBuffer( 577 omxNode, iBuffer, index, (*Info)[frameID].bytesCount, flags, 578 (*Info)[frameID].timestamp)); 579 frameID++; 580 iQueued = true; 581 } 582 // Dispatch output buffer 583 if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) { 584 ASSERT_NO_FATAL_FAILURE( 585 dispatchOutputBuffer(omxNode, oBuffer, index, oPortMode)); 586 oQueued = true; 587 } 588 // Reset Counters when either input or output buffer is dispatched 589 if (iQueued || oQueued) 590 timeOut = TIMEOUT_COUNTER_Q; 591 else 592 timeOut--; 593 if (timeOut == 0) { 594 ASSERT_TRUE(false) << "Wait on Input/Output is found indefinite"; 595 } 596 } 597 } 598 599 // DescribeColorFormatParams Copy Constructor (Borrowed from OMXUtils.cpp) 600 android::DescribeColorFormatParams::DescribeColorFormatParams( 601 const android::DescribeColorFormat2Params& params) { 602 eColorFormat = params.eColorFormat; 603 nFrameWidth = params.nFrameWidth; 604 nFrameHeight = params.nFrameHeight; 605 nStride = params.nStride; 606 nSliceHeight = params.nSliceHeight; 607 bUsingNativeBuffers = params.bUsingNativeBuffers; 608 }; 609 610 bool isColorFormatFlexibleYUV(sp<IOmxNode> omxNode, 611 OMX_COLOR_FORMATTYPE eColorFormat) { 612 android::hardware::media::omx::V1_0::Status status; 613 unsigned int index = OMX_IndexMax, index2 = OMX_IndexMax; 614 omxNode->getExtensionIndex( 615 "OMX.google.android.index.describeColorFormat", 616 [&index](android::hardware::media::omx::V1_0::Status _s, 617 unsigned int _nl) { 618 if (_s == ::android::hardware::media::omx::V1_0::Status::OK) 619 index = _nl; 620 }); 621 omxNode->getExtensionIndex( 622 "OMX.google.android.index.describeColorFormat2", 623 [&index2](android::hardware::media::omx::V1_0::Status _s, 624 unsigned int _nl) { 625 if (_s == ::android::hardware::media::omx::V1_0::Status::OK) 626 index2 = _nl; 627 }); 628 629 android::DescribeColorFormat2Params describeParams; 630 describeParams.eColorFormat = eColorFormat; 631 describeParams.nFrameWidth = 128; 632 describeParams.nFrameHeight = 128; 633 describeParams.nStride = 128; 634 describeParams.nSliceHeight = 128; 635 describeParams.bUsingNativeBuffers = OMX_FALSE; 636 if (index != OMX_IndexMax) { 637 android::DescribeColorFormatParams describeParamsV1(describeParams); 638 status = getParam(omxNode, static_cast<OMX_INDEXTYPE>(index), 639 &describeParamsV1); 640 if (status == ::android::hardware::media::omx::V1_0::Status::OK) { 641 android::MediaImage& img = describeParamsV1.sMediaImage; 642 if (img.mType == android::MediaImage::MEDIA_IMAGE_TYPE_YUV) { 643 if (img.mNumPlanes == 3 && 644 img.mPlane[img.Y].mHorizSubsampling == 1 && 645 img.mPlane[img.Y].mVertSubsampling == 1) { 646 if (img.mPlane[img.U].mHorizSubsampling == 2 && 647 img.mPlane[img.U].mVertSubsampling == 2 && 648 img.mPlane[img.V].mHorizSubsampling == 2 && 649 img.mPlane[img.V].mVertSubsampling == 2) { 650 if (img.mBitDepth <= 8) { 651 return true; 652 } 653 } 654 } 655 } 656 } 657 } else if (index2 != OMX_IndexMax) { 658 status = getParam(omxNode, static_cast<OMX_INDEXTYPE>(index2), 659 &describeParams); 660 android::MediaImage2& img = describeParams.sMediaImage; 661 if (img.mType == android::MediaImage2::MEDIA_IMAGE_TYPE_YUV) { 662 if (img.mNumPlanes == 3 && 663 img.mPlane[img.Y].mHorizSubsampling == 1 && 664 img.mPlane[img.Y].mVertSubsampling == 1) { 665 if (img.mPlane[img.U].mHorizSubsampling == 2 && 666 img.mPlane[img.U].mVertSubsampling == 2 && 667 img.mPlane[img.V].mHorizSubsampling == 2 && 668 img.mPlane[img.V].mVertSubsampling == 2) { 669 if (img.mBitDepth <= 8) { 670 return true; 671 } 672 } 673 } 674 } 675 } 676 return false; 677 } 678 679 // get default color format for output port 680 void getDefaultColorFormat(sp<IOmxNode> omxNode, OMX_U32 kPortIndexOutput, 681 PortMode oPortMode, 682 OMX_COLOR_FORMATTYPE* eColorFormat) { 683 android::hardware::media::omx::V1_0::Status status; 684 OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat; 685 *eColorFormat = OMX_COLOR_FormatUnused; 686 portFormat.nIndex = 0; 687 while (portFormat.nIndex < 512) { 688 status = getPortParam(omxNode, OMX_IndexParamVideoPortFormat, 689 kPortIndexOutput, &portFormat); 690 if (status != ::android::hardware::media::omx::V1_0::Status::OK) break; 691 EXPECT_EQ(portFormat.eCompressionFormat, OMX_VIDEO_CodingUnused); 692 if (oPortMode != PortMode::PRESET_BYTE_BUFFER) { 693 *eColorFormat = portFormat.eColorFormat; 694 break; 695 } 696 if (isColorFormatFlexibleYUV(omxNode, portFormat.eColorFormat)) { 697 *eColorFormat = portFormat.eColorFormat; 698 break; 699 } 700 if (OMX_COLOR_FormatYUV420SemiPlanar == portFormat.eColorFormat || 701 OMX_COLOR_FormatYUV420Planar == portFormat.eColorFormat || 702 OMX_COLOR_FormatYUV420PackedPlanar == portFormat.eColorFormat || 703 OMX_COLOR_FormatYUV420PackedSemiPlanar == portFormat.eColorFormat) { 704 *eColorFormat = portFormat.eColorFormat; 705 break; 706 } 707 portFormat.nIndex++; 708 } 709 } 710 711 // set component role 712 TEST_F(VideoDecHidlTest, SetRole) { 713 description("Test Set Component Role"); 714 if (disableTest) return; 715 android::hardware::media::omx::V1_0::Status status; 716 status = setRole(omxNode, gEnv->getRole().c_str()); 717 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 718 } 719 720 // port format enumeration 721 TEST_F(VideoDecHidlTest, EnumeratePortFormat) { 722 description("Test Component on Mandatory Port Parameters (Port Format)"); 723 if (disableTest) return; 724 android::hardware::media::omx::V1_0::Status status; 725 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1; 726 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatYUV420Planar; 727 OMX_U32 xFramerate = (24U << 16); 728 status = setRole(omxNode, gEnv->getRole().c_str()); 729 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 730 OMX_PORT_PARAM_TYPE params; 731 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms); 732 if (status == ::android::hardware::media::omx::V1_0::Status::OK) { 733 ASSERT_EQ(params.nPorts, 2U); 734 kPortIndexInput = params.nStartPortNumber; 735 kPortIndexOutput = kPortIndexInput + 1; 736 } 737 status = setVideoPortFormat(omxNode, kPortIndexInput, eCompressionFormat, 738 OMX_COLOR_FormatUnused, 0U); 739 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 740 status = 741 setVideoPortFormat(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused, 742 eColorFormat, xFramerate); 743 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 744 } 745 746 // test port settings reconfiguration, elementary stream decode and timestamp 747 // deviation 748 TEST_F(VideoDecHidlTest, DecodeTest) { 749 description("Tests Port Reconfiguration, Decode and timestamp deviation"); 750 if (disableTest) return; 751 android::hardware::media::omx::V1_0::Status status; 752 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1; 753 status = setRole(omxNode, gEnv->getRole().c_str()); 754 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 755 OMX_PORT_PARAM_TYPE params; 756 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms); 757 if (status == ::android::hardware::media::omx::V1_0::Status::OK) { 758 ASSERT_EQ(params.nPorts, 2U); 759 kPortIndexInput = params.nStartPortNumber; 760 kPortIndexOutput = kPortIndexInput + 1; 761 } 762 char mURL[512], info[512]; 763 strcpy(mURL, gEnv->getRes().c_str()); 764 strcpy(info, gEnv->getRes().c_str()); 765 GetURLForComponent(compName, mURL, info); 766 767 std::ifstream eleStream, eleInfo; 768 769 eleInfo.open(info); 770 ASSERT_EQ(eleInfo.is_open(), true); 771 android::Vector<FrameData> Info; 772 int bytesCount = 0, maxBytesCount = 0; 773 uint32_t flags = 0; 774 uint32_t timestamp = 0; 775 timestampDevTest = true; 776 while (1) { 777 if (!(eleInfo >> bytesCount)) break; 778 eleInfo >> flags; 779 eleInfo >> timestamp; 780 Info.push_back({bytesCount, flags, timestamp}); 781 if (timestampDevTest && (flags != OMX_BUFFERFLAG_CODECCONFIG)) 782 timestampUslist.push_back(timestamp); 783 if (maxBytesCount < bytesCount) maxBytesCount = bytesCount; 784 } 785 eleInfo.close(); 786 787 // As the frame sizes are known ahead, use it to configure i/p buffer size 788 maxBytesCount = ALIGN_POWER_OF_TWO(maxBytesCount, 10); 789 status = setPortBufferSize(omxNode, kPortIndexInput, maxBytesCount); 790 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 791 792 // set port mode 793 portMode[0] = PortMode::PRESET_BYTE_BUFFER; 794 portMode[1] = PortMode::DYNAMIC_ANW_BUFFER; 795 status = omxNode->setPortMode(kPortIndexInput, portMode[0]); 796 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 797 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]); 798 if (status != ::android::hardware::media::omx::V1_0::Status::OK) { 799 portMode[1] = PortMode::PRESET_BYTE_BUFFER; 800 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]); 801 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 802 } 803 804 // set Port Params 805 uint32_t nFrameWidth, nFrameHeight, xFramerate; 806 getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight, 807 &xFramerate); 808 // get default color format 809 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused; 810 getDefaultColorFormat(omxNode, kPortIndexOutput, portMode[1], 811 &eColorFormat); 812 ASSERT_NE(eColorFormat, OMX_COLOR_FormatUnused); 813 status = 814 setVideoPortFormat(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused, 815 eColorFormat, xFramerate); 816 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 817 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused, 818 eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate); 819 820 android::Vector<BufferInfo> iBuffer, oBuffer; 821 822 // set state to idle 823 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle( 824 omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput, 825 kPortIndexOutput, portMode, true)); 826 // set state to executing 827 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer)); 828 829 // Port Reconfiguration 830 eleStream.open(mURL, std::ifstream::binary); 831 ASSERT_EQ(eleStream.is_open(), true); 832 ASSERT_NO_FATAL_FAILURE(decodeNFrames( 833 omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput, 834 kPortIndexOutput, eleStream, &Info, 0, (int)Info.size(), portMode[1])); 835 eleStream.close(); 836 ASSERT_NO_FATAL_FAILURE( 837 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, 838 kPortIndexInput, kPortIndexOutput, portMode[1])); 839 ASSERT_NO_FATAL_FAILURE(testEOS( 840 omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, portMode, 841 portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr)); 842 if (timestampDevTest) EXPECT_EQ(timestampUslist.empty(), true); 843 // set state to idle 844 ASSERT_NO_FATAL_FAILURE( 845 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer)); 846 // set state to executing 847 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer, 848 &oBuffer, kPortIndexInput, 849 kPortIndexOutput)); 850 } 851 852 // Test for adaptive playback support 853 TEST_F(VideoDecHidlTest, AdaptivePlaybackTest) { 854 description("Tests for Adaptive Playback support"); 855 if (disableTest) return; 856 if (!(compName == avc || compName == hevc || compName == vp8 || 857 compName == vp9 || compName == mpeg2)) 858 return; 859 android::hardware::media::omx::V1_0::Status status; 860 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1; 861 status = setRole(omxNode, gEnv->getRole().c_str()); 862 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 863 OMX_PORT_PARAM_TYPE params; 864 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms); 865 if (status == ::android::hardware::media::omx::V1_0::Status::OK) { 866 ASSERT_EQ(params.nPorts, 2U); 867 kPortIndexInput = params.nStartPortNumber; 868 kPortIndexOutput = kPortIndexInput + 1; 869 } 870 871 // set port mode 872 portMode[0] = PortMode::PRESET_BYTE_BUFFER; 873 portMode[1] = PortMode::DYNAMIC_ANW_BUFFER; 874 status = omxNode->setPortMode(kPortIndexInput, portMode[0]); 875 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 876 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]); 877 if (status != ::android::hardware::media::omx::V1_0::Status::OK) { 878 portMode[1] = PortMode::PRESET_BYTE_BUFFER; 879 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]); 880 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 881 } 882 883 // prepare for adaptive playback 884 uint32_t adaptiveMaxWidth = 320; 885 uint32_t adaptiveMaxHeight = 240; 886 status = omxNode->prepareForAdaptivePlayback( 887 kPortIndexOutput, true, adaptiveMaxWidth, adaptiveMaxHeight); 888 if (strncmp(gEnv->getComponent().c_str(), "OMX.google.", 11) == 0) { 889 // SoftOMX Decoders donot support graphic buffer modes. So for them 890 // support for adaptive play back is mandatory in Byte Buffer mode 891 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 892 } else { 893 // for vendor codecs, support for adaptive play back is optional 894 // in byte buffer mode. 895 if (portMode[1] == PortMode::PRESET_BYTE_BUFFER) return; 896 if (status != ::android::hardware::media::omx::V1_0::Status::OK) return; 897 } 898 899 // TODO: Handle this better !!! 900 // Without the knowledge of the maximum resolution of the frame to be 901 // decoded it is not possible to choose the size of the input buffer. 902 // The value below is based on the info. files of clips in res folder. 903 status = setPortBufferSize(omxNode, kPortIndexInput, 482304); 904 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 905 906 // set Port Params 907 uint32_t nFrameWidth, nFrameHeight, xFramerate; 908 getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight, 909 &xFramerate); 910 // get default color format 911 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused; 912 getDefaultColorFormat(omxNode, kPortIndexOutput, portMode[1], 913 &eColorFormat); 914 ASSERT_NE(eColorFormat, OMX_COLOR_FormatUnused); 915 status = 916 setVideoPortFormat(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused, 917 eColorFormat, xFramerate); 918 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 919 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused, 920 eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate); 921 922 android::Vector<BufferInfo> iBuffer, oBuffer; 923 924 // set state to idle 925 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle( 926 omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput, 927 kPortIndexOutput, portMode, true)); 928 // set state to executing 929 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer)); 930 931 timestampDevTest = true; 932 uint32_t timestampOffset = 0; 933 for (uint32_t i = 0; i < STREAM_COUNT * 2; i++) { 934 std::ifstream eleStream, eleInfo; 935 char mURL[512], info[512]; 936 android::Vector<FrameData> Info; 937 strcpy(mURL, gEnv->getRes().c_str()); 938 strcpy(info, gEnv->getRes().c_str()); 939 GetURLForComponent(compName, mURL, info, i % STREAM_COUNT); 940 eleInfo.open(info); 941 ASSERT_EQ(eleInfo.is_open(), true); 942 int bytesCount = 0; 943 uint32_t flags = 0; 944 uint32_t timestamp = 0; 945 uint32_t timestampMax = 0; 946 while (1) { 947 if (!(eleInfo >> bytesCount)) break; 948 eleInfo >> flags; 949 eleInfo >> timestamp; 950 timestamp += timestampOffset; 951 Info.push_back({bytesCount, flags, timestamp}); 952 if (timestampDevTest && (flags != OMX_BUFFERFLAG_CODECCONFIG)) 953 timestampUslist.push_back(timestamp); 954 if (timestampMax < timestamp) timestampMax = timestamp; 955 } 956 timestampOffset = timestampMax; 957 eleInfo.close(); 958 959 // Port Reconfiguration 960 eleStream.open(mURL, std::ifstream::binary); 961 ASSERT_EQ(eleStream.is_open(), true); 962 ASSERT_NO_FATAL_FAILURE( 963 decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, 964 kPortIndexInput, kPortIndexOutput, eleStream, &Info, 965 0, (int)Info.size(), portMode[1], false)); 966 eleStream.close(); 967 968 getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, 969 &nFrameHeight, &xFramerate); 970 if ((nFrameWidth > adaptiveMaxWidth) || 971 (nFrameHeight > adaptiveMaxHeight)) { 972 if (nFrameWidth > adaptiveMaxWidth) adaptiveMaxWidth = nFrameWidth; 973 if (nFrameHeight > adaptiveMaxHeight) 974 adaptiveMaxHeight = nFrameHeight; 975 EXPECT_TRUE(portSettingsChange); 976 } else { 977 // In DynamicANW Buffer mode, its ok to do a complete 978 // reconfiguration even if a partial reconfiguration is sufficient. 979 if (portMode[1] != PortMode::DYNAMIC_ANW_BUFFER) 980 EXPECT_FALSE(portSettingsChange); 981 } 982 portSettingsChange = false; 983 } 984 ASSERT_NO_FATAL_FAILURE( 985 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, 986 kPortIndexInput, kPortIndexOutput, portMode[1])); 987 ASSERT_NO_FATAL_FAILURE(testEOS( 988 omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, portMode, 989 portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr)); 990 if (timestampDevTest) EXPECT_EQ(timestampUslist.empty(), true); 991 // set state to idle 992 ASSERT_NO_FATAL_FAILURE( 993 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer)); 994 // set state to executing 995 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer, 996 &oBuffer, kPortIndexInput, 997 kPortIndexOutput)); 998 } 999 1000 // end of sequence test 1001 TEST_F(VideoDecHidlTest, EOSTest_M) { 1002 description("Test End of stream monkeying"); 1003 if (disableTest) return; 1004 android::hardware::media::omx::V1_0::Status status; 1005 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1; 1006 status = setRole(omxNode, gEnv->getRole().c_str()); 1007 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 1008 OMX_PORT_PARAM_TYPE params; 1009 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms); 1010 if (status == ::android::hardware::media::omx::V1_0::Status::OK) { 1011 ASSERT_EQ(params.nPorts, 2U); 1012 kPortIndexInput = params.nStartPortNumber; 1013 kPortIndexOutput = kPortIndexInput + 1; 1014 } 1015 1016 // set port mode 1017 status = omxNode->setPortMode(kPortIndexInput, portMode[0]); 1018 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 1019 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]); 1020 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 1021 1022 // set Port Params 1023 uint32_t nFrameWidth, nFrameHeight, xFramerate; 1024 getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight, 1025 &xFramerate); 1026 // get default color format 1027 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused; 1028 getDefaultColorFormat(omxNode, kPortIndexOutput, portMode[1], 1029 &eColorFormat); 1030 ASSERT_NE(eColorFormat, OMX_COLOR_FormatUnused); 1031 status = 1032 setVideoPortFormat(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused, 1033 eColorFormat, xFramerate); 1034 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 1035 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused, 1036 eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate); 1037 1038 android::Vector<BufferInfo> iBuffer, oBuffer; 1039 1040 // set state to idle 1041 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle( 1042 omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput, 1043 kPortIndexOutput, portMode, true)); 1044 // set state to executing 1045 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer)); 1046 1047 // request EOS at the start 1048 ASSERT_NO_FATAL_FAILURE(testEOS( 1049 omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, portMode, 1050 portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr)); 1051 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer, 1052 kPortIndexInput, kPortIndexOutput)); 1053 EXPECT_GE(framesReceived, 0U); 1054 framesReceived = 0; 1055 timestampUs = 0; 1056 1057 // set state to idle 1058 ASSERT_NO_FATAL_FAILURE( 1059 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer)); 1060 // set state to executing 1061 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer, 1062 &oBuffer, kPortIndexInput, 1063 kPortIndexOutput)); 1064 } 1065 1066 // end of sequence test 1067 TEST_F(VideoDecHidlTest, ThumbnailTest) { 1068 description("Test Request for thumbnail"); 1069 if (disableTest) return; 1070 android::hardware::media::omx::V1_0::Status status; 1071 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1; 1072 status = setRole(omxNode, gEnv->getRole().c_str()); 1073 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 1074 OMX_PORT_PARAM_TYPE params; 1075 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms); 1076 if (status == ::android::hardware::media::omx::V1_0::Status::OK) { 1077 ASSERT_EQ(params.nPorts, 2U); 1078 kPortIndexInput = params.nStartPortNumber; 1079 kPortIndexOutput = kPortIndexInput + 1; 1080 } 1081 char mURL[512], info[512]; 1082 strcpy(mURL, gEnv->getRes().c_str()); 1083 strcpy(info, gEnv->getRes().c_str()); 1084 GetURLForComponent(compName, mURL, info); 1085 1086 std::ifstream eleStream, eleInfo; 1087 1088 eleInfo.open(info); 1089 ASSERT_EQ(eleInfo.is_open(), true); 1090 android::Vector<FrameData> Info; 1091 int bytesCount = 0, maxBytesCount = 0; 1092 uint32_t flags = 0; 1093 uint32_t timestamp = 0; 1094 while (1) { 1095 if (!(eleInfo >> bytesCount)) break; 1096 eleInfo >> flags; 1097 eleInfo >> timestamp; 1098 Info.push_back({bytesCount, flags, timestamp}); 1099 if (maxBytesCount < bytesCount) maxBytesCount = bytesCount; 1100 } 1101 eleInfo.close(); 1102 1103 // As the frame sizes are known ahead, use it to configure i/p buffer size 1104 maxBytesCount = ALIGN_POWER_OF_TWO(maxBytesCount, 10); 1105 status = setPortBufferSize(omxNode, kPortIndexInput, maxBytesCount); 1106 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 1107 1108 // set port mode 1109 status = omxNode->setPortMode(kPortIndexInput, portMode[0]); 1110 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 1111 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]); 1112 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 1113 1114 // set Port Params 1115 uint32_t nFrameWidth, nFrameHeight, xFramerate; 1116 getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight, 1117 &xFramerate); 1118 // get default color format 1119 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused; 1120 getDefaultColorFormat(omxNode, kPortIndexOutput, portMode[1], 1121 &eColorFormat); 1122 ASSERT_NE(eColorFormat, OMX_COLOR_FormatUnused); 1123 status = 1124 setVideoPortFormat(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused, 1125 eColorFormat, xFramerate); 1126 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 1127 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused, 1128 eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate); 1129 1130 android::Vector<BufferInfo> iBuffer, oBuffer; 1131 1132 // set state to idle 1133 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle( 1134 omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput, 1135 kPortIndexOutput, portMode, true)); 1136 // set state to executing 1137 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer)); 1138 1139 // request EOS for thumbnail 1140 size_t i = 0; 1141 while (!(Info[i].flags & OMX_BUFFERFLAG_SYNCFRAME)) i++; 1142 eleStream.open(mURL, std::ifstream::binary); 1143 ASSERT_EQ(eleStream.is_open(), true); 1144 ASSERT_NO_FATAL_FAILURE(decodeNFrames( 1145 omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput, 1146 kPortIndexOutput, eleStream, &Info, 0, i + 1, portMode[1])); 1147 eleStream.close(); 1148 ASSERT_NO_FATAL_FAILURE( 1149 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, 1150 kPortIndexInput, kPortIndexOutput, portMode[1])); 1151 ASSERT_NO_FATAL_FAILURE(testEOS( 1152 omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, portMode, 1153 portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr)); 1154 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer, 1155 kPortIndexInput, kPortIndexOutput)); 1156 EXPECT_GE(framesReceived, 1U); 1157 framesReceived = 0; 1158 timestampUs = 0; 1159 1160 eleStream.open(mURL, std::ifstream::binary); 1161 ASSERT_EQ(eleStream.is_open(), true); 1162 ASSERT_NO_FATAL_FAILURE(decodeNFrames( 1163 omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput, 1164 kPortIndexOutput, eleStream, &Info, 0, i + 1, portMode[1], false)); 1165 eleStream.close(); 1166 ASSERT_NO_FATAL_FAILURE( 1167 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, 1168 kPortIndexInput, kPortIndexOutput, portMode[1])); 1169 ASSERT_NO_FATAL_FAILURE(testEOS( 1170 omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, portMode, 1171 portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr)); 1172 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer, 1173 kPortIndexInput, kPortIndexOutput)); 1174 EXPECT_GE(framesReceived, 1U); 1175 framesReceived = 0; 1176 timestampUs = 0; 1177 1178 // set state to idle 1179 ASSERT_NO_FATAL_FAILURE( 1180 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer)); 1181 // set state to executing 1182 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer, 1183 &oBuffer, kPortIndexInput, 1184 kPortIndexOutput)); 1185 } 1186 1187 // end of sequence test 1188 TEST_F(VideoDecHidlTest, SimpleEOSTest) { 1189 description("Test End of stream"); 1190 if (disableTest) return; 1191 android::hardware::media::omx::V1_0::Status status; 1192 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1; 1193 status = setRole(omxNode, gEnv->getRole().c_str()); 1194 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 1195 OMX_PORT_PARAM_TYPE params; 1196 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms); 1197 if (status == ::android::hardware::media::omx::V1_0::Status::OK) { 1198 ASSERT_EQ(params.nPorts, 2U); 1199 kPortIndexInput = params.nStartPortNumber; 1200 kPortIndexOutput = kPortIndexInput + 1; 1201 } 1202 char mURL[512], info[512]; 1203 strcpy(mURL, gEnv->getRes().c_str()); 1204 strcpy(info, gEnv->getRes().c_str()); 1205 GetURLForComponent(compName, mURL, info); 1206 1207 std::ifstream eleStream, eleInfo; 1208 1209 eleInfo.open(info); 1210 ASSERT_EQ(eleInfo.is_open(), true); 1211 android::Vector<FrameData> Info; 1212 int bytesCount = 0, maxBytesCount = 0; 1213 uint32_t flags = 0; 1214 uint32_t timestamp = 0; 1215 while (1) { 1216 if (!(eleInfo >> bytesCount)) break; 1217 eleInfo >> flags; 1218 eleInfo >> timestamp; 1219 Info.push_back({bytesCount, flags, timestamp}); 1220 if (maxBytesCount < bytesCount) maxBytesCount = bytesCount; 1221 } 1222 eleInfo.close(); 1223 1224 // As the frame sizes are known ahead, use it to configure i/p buffer size 1225 maxBytesCount = ALIGN_POWER_OF_TWO(maxBytesCount, 10); 1226 status = setPortBufferSize(omxNode, kPortIndexInput, maxBytesCount); 1227 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 1228 1229 // set port mode 1230 portMode[0] = PortMode::PRESET_BYTE_BUFFER; 1231 portMode[1] = PortMode::PRESET_ANW_BUFFER; 1232 status = omxNode->setPortMode(kPortIndexInput, portMode[0]); 1233 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 1234 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]); 1235 if (status != ::android::hardware::media::omx::V1_0::Status::OK) { 1236 portMode[1] = PortMode::PRESET_BYTE_BUFFER; 1237 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]); 1238 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 1239 } 1240 1241 // set Port Params 1242 uint32_t nFrameWidth, nFrameHeight, xFramerate; 1243 getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight, 1244 &xFramerate); 1245 // get default color format 1246 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused; 1247 getDefaultColorFormat(omxNode, kPortIndexOutput, portMode[1], 1248 &eColorFormat); 1249 ASSERT_NE(eColorFormat, OMX_COLOR_FormatUnused); 1250 status = 1251 setVideoPortFormat(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused, 1252 eColorFormat, xFramerate); 1253 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 1254 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused, 1255 eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate); 1256 1257 android::Vector<BufferInfo> iBuffer, oBuffer; 1258 1259 // set state to idle 1260 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle( 1261 omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput, 1262 kPortIndexOutput, portMode, true)); 1263 // set state to executing 1264 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer)); 1265 1266 // request EOS at the end 1267 eleStream.open(mURL, std::ifstream::binary); 1268 ASSERT_EQ(eleStream.is_open(), true); 1269 ASSERT_NO_FATAL_FAILURE(decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, 1270 kPortIndexInput, kPortIndexOutput, 1271 eleStream, &Info, 0, (int)Info.size(), 1272 portMode[1], false)); 1273 eleStream.close(); 1274 ASSERT_NO_FATAL_FAILURE( 1275 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, 1276 kPortIndexInput, kPortIndexOutput, portMode[1])); 1277 ASSERT_NO_FATAL_FAILURE(testEOS( 1278 omxNode, observer, &iBuffer, &oBuffer, true, eosFlag, portMode, 1279 portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr)); 1280 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer, 1281 kPortIndexInput, kPortIndexOutput)); 1282 framesReceived = 0; 1283 timestampUs = 0; 1284 1285 // set state to idle 1286 ASSERT_NO_FATAL_FAILURE( 1287 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer)); 1288 // set state to executing 1289 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer, 1290 &oBuffer, kPortIndexInput, 1291 kPortIndexOutput)); 1292 } 1293 1294 // test input/output port flush 1295 TEST_F(VideoDecHidlTest, FlushTest) { 1296 description("Test Flush"); 1297 if (disableTest) return; 1298 android::hardware::media::omx::V1_0::Status status; 1299 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1; 1300 status = setRole(omxNode, gEnv->getRole().c_str()); 1301 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 1302 OMX_PORT_PARAM_TYPE params; 1303 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms); 1304 if (status == ::android::hardware::media::omx::V1_0::Status::OK) { 1305 ASSERT_EQ(params.nPorts, 2U); 1306 kPortIndexInput = params.nStartPortNumber; 1307 kPortIndexOutput = kPortIndexInput + 1; 1308 } 1309 char mURL[512], info[512]; 1310 strcpy(mURL, gEnv->getRes().c_str()); 1311 strcpy(info, gEnv->getRes().c_str()); 1312 GetURLForComponent(compName, mURL, info); 1313 1314 std::ifstream eleStream, eleInfo; 1315 1316 eleInfo.open(info); 1317 ASSERT_EQ(eleInfo.is_open(), true); 1318 android::Vector<FrameData> Info; 1319 int bytesCount = 0, maxBytesCount = 0; 1320 uint32_t flags = 0; 1321 uint32_t timestamp = 0; 1322 while (1) { 1323 if (!(eleInfo >> bytesCount)) break; 1324 eleInfo >> flags; 1325 eleInfo >> timestamp; 1326 Info.push_back({bytesCount, flags, timestamp}); 1327 if (maxBytesCount < bytesCount) maxBytesCount = bytesCount; 1328 } 1329 eleInfo.close(); 1330 1331 // As the frame sizes are known ahead, use it to configure i/p buffer size 1332 maxBytesCount = ALIGN_POWER_OF_TWO(maxBytesCount, 10); 1333 status = setPortBufferSize(omxNode, kPortIndexInput, maxBytesCount); 1334 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 1335 1336 // set port mode 1337 status = omxNode->setPortMode(kPortIndexInput, portMode[0]); 1338 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 1339 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]); 1340 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 1341 1342 // set Port Params 1343 uint32_t nFrameWidth, nFrameHeight, xFramerate; 1344 getInputChannelInfo(omxNode, kPortIndexInput, &nFrameWidth, &nFrameHeight, 1345 &xFramerate); 1346 // get default color format 1347 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused; 1348 getDefaultColorFormat(omxNode, kPortIndexOutput, portMode[1], 1349 &eColorFormat); 1350 ASSERT_NE(eColorFormat, OMX_COLOR_FormatUnused); 1351 status = 1352 setVideoPortFormat(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused, 1353 eColorFormat, xFramerate); 1354 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 1355 setDefaultPortParam(omxNode, kPortIndexOutput, OMX_VIDEO_CodingUnused, 1356 eColorFormat, nFrameWidth, nFrameHeight, 0, xFramerate); 1357 1358 android::Vector<BufferInfo> iBuffer, oBuffer; 1359 1360 // set state to idle 1361 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle( 1362 omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput, 1363 kPortIndexOutput, portMode, true)); 1364 // set state to executing 1365 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer)); 1366 1367 // Decode 128 frames and flush. here 128 is chosen to ensure there is a key 1368 // frame after this so that the below section can be convered for all 1369 // components 1370 int nFrames = 128; 1371 eleStream.open(mURL, std::ifstream::binary); 1372 ASSERT_EQ(eleStream.is_open(), true); 1373 ASSERT_NO_FATAL_FAILURE(decodeNFrames( 1374 omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput, 1375 kPortIndexOutput, eleStream, &Info, 0, nFrames, portMode[1], false)); 1376 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer, 1377 kPortIndexInput, kPortIndexOutput)); 1378 framesReceived = 0; 1379 1380 // Seek to next key frame and start decoding till the end 1381 int index = nFrames; 1382 bool keyFrame = false; 1383 while (index < (int)Info.size()) { 1384 if ((Info[index].flags & OMX_BUFFERFLAG_SYNCFRAME) == 1385 OMX_BUFFERFLAG_SYNCFRAME) { 1386 timestampUs = Info[index - 1].timestamp; 1387 keyFrame = true; 1388 break; 1389 } 1390 eleStream.ignore(Info[index].bytesCount); 1391 index++; 1392 } 1393 if (keyFrame) { 1394 ASSERT_NO_FATAL_FAILURE( 1395 decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, 1396 kPortIndexInput, kPortIndexOutput, eleStream, &Info, 1397 index, Info.size() - index, portMode[1], false)); 1398 } 1399 eleStream.close(); 1400 ASSERT_NO_FATAL_FAILURE(flushPorts(omxNode, observer, &iBuffer, &oBuffer, 1401 kPortIndexInput, kPortIndexOutput)); 1402 framesReceived = 0; 1403 1404 // set state to idle 1405 ASSERT_NO_FATAL_FAILURE( 1406 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer)); 1407 // set state to executing 1408 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer, 1409 &oBuffer, kPortIndexInput, 1410 kPortIndexOutput)); 1411 } 1412 1413 int main(int argc, char** argv) { 1414 gEnv = new ComponentTestEnvironment(); 1415 ::testing::AddGlobalTestEnvironment(gEnv); 1416 ::testing::InitGoogleTest(&argc, argv); 1417 gEnv->init(&argc, argv); 1418 int status = gEnv->initFromOptions(argc, argv); 1419 if (status == 0) { 1420 status = RUN_ALL_TESTS(); 1421 ALOGI("Test result = %d", status); 1422 } 1423 return status; 1424 } 1425