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