VtsHalMediaOmxV1_0TargetComponentTest.cpp revision f9c4003fcdf63d86a20de2c35ee32eab72d75b16
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_component_test" 18#include <android-base/logging.h> 19 20#include <android/hardware/media/omx/1.0/IOmx.h> 21#include <android/hardware/media/omx/1.0/IOmxNode.h> 22#include <android/hardware/media/omx/1.0/IOmxObserver.h> 23#include <android/hardware/media/omx/1.0/types.h> 24#include <android/hidl/allocator/1.0/IAllocator.h> 25#include <android/hidl/memory/1.0/IMapper.h> 26#include <android/hidl/memory/1.0/IMemory.h> 27 28using ::android::hardware::media::omx::V1_0::IOmx; 29using ::android::hardware::media::omx::V1_0::IOmxObserver; 30using ::android::hardware::media::omx::V1_0::IOmxNode; 31using ::android::hardware::media::omx::V1_0::Message; 32using ::android::hardware::media::omx::V1_0::CodecBuffer; 33using ::android::hidl::allocator::V1_0::IAllocator; 34using ::android::hidl::memory::V1_0::IMemory; 35using ::android::hidl::memory::V1_0::IMapper; 36using ::android::hardware::Return; 37using ::android::hardware::Void; 38using ::android::hardware::hidl_vec; 39using ::android::hardware::hidl_string; 40using ::android::sp; 41 42#include <VtsHalHidlTargetTestBase.h> 43#include <getopt.h> 44#include <media_hidl_test_common.h> 45 46// A class for test environment setup 47class ComponentTestEnvironment : public ::testing::Environment { 48 public: 49 virtual void SetUp() {} 50 virtual void TearDown() {} 51 52 ComponentTestEnvironment() : instance("default") {} 53 54 void setInstance(const char* _instance) { instance = _instance; } 55 56 void setComponent(const char* _component) { component = _component; } 57 58 void setRole(const char* _role) { role = _role; } 59 60 void setQuirks(int _quirks) { quirks = _quirks; } 61 62 const hidl_string getInstance() const { return instance; } 63 64 const hidl_string getComponent() const { return component; } 65 66 const hidl_string getRole() const { return role; } 67 68 int getQuirks() const { return quirks; } 69 70 int initFromOptions(int argc, char** argv) { 71 static struct option options[] = { 72 {"instance", required_argument, 0, 'I'}, 73 {"component", required_argument, 0, 'C'}, 74 {"role", required_argument, 0, 'R'}, 75 {"quirks", required_argument, 0, 'Q'}, 76 {0, 0, 0, 0}}; 77 78 while (true) { 79 int index = 0; 80 int c = getopt_long(argc, argv, "I:C:Q:R:", options, &index); 81 if (c == -1) { 82 break; 83 } 84 85 switch (c) { 86 case 'I': 87 setInstance(optarg); 88 break; 89 case 'C': 90 setComponent(optarg); 91 break; 92 case 'Q': 93 setQuirks(atoi(optarg)); 94 break; 95 case 'R': 96 setRole(optarg); 97 break; 98 case '?': 99 break; 100 } 101 } 102 103 if (optind < argc) { 104 fprintf(stderr, 105 "unrecognized option: %s\n\n" 106 "usage: %s <gtest options> <test options>\n\n" 107 "test options are:\n\n" 108 "-I, --instance: HAL instance to test\n" 109 "-C, --component: OMX component to test\n" 110 "-R, --Role: OMX component Role\n" 111 "-Q, --quirks: Component quirks\n", 112 argv[optind ?: 1], argv[0]); 113 return 2; 114 } 115 return 0; 116 } 117 118 private: 119 hidl_string instance; 120 hidl_string component; 121 hidl_string role; 122 // to be removed when IOmxNode::setQuirks is removed 123 int quirks; 124}; 125 126static ComponentTestEnvironment* gEnv = nullptr; 127 128class ComponentHidlTest : public ::testing::VtsHalHidlTargetTestBase { 129 public: 130 virtual void SetUp() override { 131 android::hardware::media::omx::V1_0::Status status; 132 omx = ::testing::VtsHalHidlTargetTestBase::getService<IOmx>( 133 gEnv->getInstance()); 134 ASSERT_NE(omx, nullptr); 135 observer = new CodecObserver(); 136 ASSERT_NE(observer, nullptr); 137 ASSERT_EQ(strncmp(gEnv->getComponent().c_str(), "OMX.", 4), 0) 138 << "Invalid Component Name"; 139 EXPECT_TRUE(omx->allocateNode( 140 gEnv->getComponent(), observer, 141 [&](android::hardware::media::omx::V1_0::Status _s, 142 sp<IOmxNode> const& _nl) { 143 status = _s; 144 this->omxNode = _nl; 145 }) 146 .isOk()); 147 ASSERT_NE(omxNode, nullptr); 148 ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role"; 149 struct StringToClass { 150 const char* Class; 151 standardCompClass CompClass; 152 }; 153 const StringToClass kStringToClass[] = { 154 {"audio_decoder", audio_decoder}, 155 {"audio_encoder", audio_encoder}, 156 {"video_decoder", video_decoder}, 157 {"video_encoder", video_encoder}, 158 }; 159 const size_t kNumStringToClass = 160 sizeof(kStringToClass) / sizeof(kStringToClass[0]); 161 const char* pch; 162 char substring[OMX_MAX_STRINGNAME_SIZE]; 163 strcpy(substring, gEnv->getRole().c_str()); 164 pch = strchr(substring, '.'); 165 ASSERT_NE(pch, nullptr) << "Invalid Component Role"; 166 substring[pch - substring] = '\0'; 167 compClass = unknown_class; 168 for (size_t i = 0; i < kNumStringToClass; ++i) { 169 if (!strcasecmp(substring, kStringToClass[i].Class)) { 170 compClass = kStringToClass[i].CompClass; 171 break; 172 } 173 } 174 ASSERT_NE(compClass, unknown_class) << "Invalid Component Class"; 175 } 176 177 virtual void TearDown() override { 178 if (omxNode != nullptr) { 179 EXPECT_TRUE((omxNode->freeNode()).isOk()); 180 omxNode = nullptr; 181 } 182 } 183 184 enum standardCompClass { 185 audio_decoder, 186 audio_encoder, 187 video_decoder, 188 video_encoder, 189 unknown_class, 190 }; 191 192 sp<IOmx> omx; 193 sp<CodecObserver> observer; 194 sp<IOmxNode> omxNode; 195 standardCompClass compClass; 196 197 protected: 198 static void description(const std::string& description) { 199 RecordProperty("description", description); 200 } 201}; 202 203// Random Index used for monkey testing while get/set parameters 204#define RANDOM_INDEX 1729 205 206// allocate buffers needed on a component port 207void allocatePortBuffers(sp<IOmxNode> omxNode, 208 android::Vector<BufferInfo>* buffArray, 209 OMX_U32 portIndex) { 210 android::hardware::media::omx::V1_0::Status status; 211 OMX_PARAM_PORTDEFINITIONTYPE portDef; 212 213 buffArray->clear(); 214 215 sp<IAllocator> allocator = IAllocator::getService("ashmem"); 216 EXPECT_NE(allocator.get(), nullptr); 217 218 status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex, 219 &portDef); 220 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 221 222 for (size_t i = 0; i < portDef.nBufferCountActual; i++) { 223 BufferInfo buffer; 224 buffer.owner = client; 225 buffer.omxBuffer.type = CodecBuffer::Type::SHARED_MEM; 226 buffer.omxBuffer.attr.preset.rangeOffset = 0; 227 buffer.omxBuffer.attr.preset.rangeLength = 0; 228 bool success = false; 229 allocator->allocate( 230 portDef.nBufferSize, 231 [&success, &buffer](bool _s, 232 ::android::hardware::hidl_memory const& mem) { 233 success = _s; 234 buffer.omxBuffer.sharedMemory = mem; 235 }); 236 ASSERT_EQ(success, true); 237 ASSERT_EQ(buffer.omxBuffer.sharedMemory.size(), portDef.nBufferSize); 238 239 omxNode->useBuffer( 240 portIndex, buffer.omxBuffer, 241 [&status, &buffer](android::hardware::media::omx::V1_0::Status _s, 242 uint32_t id) { 243 status = _s; 244 buffer.id = id; 245 }); 246 buffArray->push(buffer); 247 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 248 } 249} 250 251// State Transition : Loaded -> Idle 252// Note: This function does not make any background checks for this transition. 253// The callee holds the reponsibility to ensure the legality of the transition. 254void changeStateLoadedtoIdle(sp<IOmxNode> omxNode, sp<CodecObserver> observer, 255 android::Vector<BufferInfo>* iBuffer, 256 android::Vector<BufferInfo>* oBuffer, 257 OMX_U32 kPortIndexInput, 258 OMX_U32 kPortIndexOutput) { 259 android::hardware::media::omx::V1_0::Status status; 260 Message msg; 261 262 // set state to idle 263 status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet), 264 OMX_StateIdle); 265 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 266 267 // Dont switch states until the ports are populated 268 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer); 269 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT); 270 271 // allocate buffers on input port 272 allocatePortBuffers(omxNode, iBuffer, kPortIndexInput); 273 274 // Dont switch states until the ports are populated 275 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer); 276 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT); 277 278 // allocate buffers on output port 279 allocatePortBuffers(omxNode, oBuffer, kPortIndexOutput); 280 281 // As the ports are populated, check if the state transition is complete 282 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer); 283 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 284 ASSERT_EQ(msg.type, Message::Type::EVENT); 285 ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete); 286 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet); 287 ASSERT_EQ(msg.data.eventData.data2, OMX_StateIdle); 288 289 return; 290} 291 292// State Transition : Idle -> Loaded 293// Note: This function does not make any background checks for this transition. 294// The callee holds the reponsibility to ensure the legality of the transition. 295void changeStateIdletoLoaded(sp<IOmxNode> omxNode, sp<CodecObserver> observer, 296 android::Vector<BufferInfo>* iBuffer, 297 android::Vector<BufferInfo>* oBuffer, 298 OMX_U32 kPortIndexInput, 299 OMX_U32 kPortIndexOutput) { 300 android::hardware::media::omx::V1_0::Status status; 301 Message msg; 302 303 // set state to Loaded 304 status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet), 305 OMX_StateLoaded); 306 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 307 308 // dont change state until all buffers are freed 309 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer); 310 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT); 311 312 for (size_t i = 0; i < iBuffer->size(); ++i) { 313 status = omxNode->freeBuffer(kPortIndexInput, (*iBuffer)[i].id); 314 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 315 } 316 317 // dont change state until all buffers are freed 318 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer); 319 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT); 320 321 for (size_t i = 0; i < oBuffer->size(); ++i) { 322 status = omxNode->freeBuffer(kPortIndexOutput, (*oBuffer)[i].id); 323 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 324 } 325 326 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer); 327 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 328 ASSERT_EQ(msg.type, Message::Type::EVENT); 329 ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete); 330 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet); 331 ASSERT_EQ(msg.data.eventData.data2, OMX_StateLoaded); 332 333 return; 334} 335 336// State Transition : Idle -> Execute 337// Note: This function does not make any background checks for this transition. 338// The callee holds the reponsibility to ensure the legality of the transition. 339void changeStateIdletoExecute(sp<IOmxNode> omxNode, 340 sp<CodecObserver> observer) { 341 android::hardware::media::omx::V1_0::Status status; 342 Message msg; 343 344 // set state to execute 345 status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet), 346 OMX_StateExecuting); 347 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 348 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT); 349 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 350 ASSERT_EQ(msg.type, Message::Type::EVENT); 351 ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete); 352 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet); 353 ASSERT_EQ(msg.data.eventData.data2, OMX_StateExecuting); 354 355 return; 356} 357 358// State Transition : Execute -> Idle 359// Note: This function does not make any background checks for this transition. 360// The callee holds the reponsibility to ensure the legality of the transition. 361void changeStateExecutetoIdle(sp<IOmxNode> omxNode, sp<CodecObserver> observer, 362 android::Vector<BufferInfo>* iBuffer, 363 android::Vector<BufferInfo>* oBuffer) { 364 android::hardware::media::omx::V1_0::Status status; 365 Message msg; 366 367 // set state to Idle 368 status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet), 369 OMX_StateIdle); 370 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 371 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer); 372 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 373 ASSERT_EQ(msg.type, Message::Type::EVENT); 374 ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete); 375 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet); 376 ASSERT_EQ(msg.data.eventData.data2, OMX_StateIdle); 377 378 // test if client got all its buffers back 379 for (size_t i = 0; i < oBuffer->size(); ++i) { 380 EXPECT_EQ((*oBuffer)[i].owner, client); 381 } 382 for (size_t i = 0; i < iBuffer->size(); ++i) { 383 EXPECT_EQ((*iBuffer)[i].owner, client); 384 } 385} 386 387// dispatch buffer to output port 388void dispatchOutputBuffer(sp<IOmxNode> omxNode, 389 android::Vector<BufferInfo>* buffArray, 390 size_t bufferIndex) { 391 android::hardware::media::omx::V1_0::Status status; 392 CodecBuffer t; 393 t.sharedMemory = android::hardware::hidl_memory(); 394 t.nativeHandle = android::hardware::hidl_handle(); 395 t.type = CodecBuffer::Type::PRESET; 396 t.attr.preset.rangeOffset = 0; 397 t.attr.preset.rangeLength = 0; 398 native_handle_t* fenceNh = native_handle_create(0, 0); 399 ASSERT_NE(fenceNh, nullptr); 400 status = omxNode->fillBuffer((*buffArray)[bufferIndex].id, t, fenceNh); 401 native_handle_close(fenceNh); 402 native_handle_delete(fenceNh); 403 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 404 buffArray->editItemAt(bufferIndex).owner = component; 405} 406 407// dispatch buffer to input port 408void dispatchInputBuffer(sp<IOmxNode> omxNode, 409 android::Vector<BufferInfo>* buffArray, 410 size_t bufferIndex, int bytesCount, uint32_t flags, 411 uint64_t timestamp) { 412 android::hardware::media::omx::V1_0::Status status; 413 CodecBuffer t; 414 t.sharedMemory = android::hardware::hidl_memory(); 415 t.nativeHandle = android::hardware::hidl_handle(); 416 t.type = CodecBuffer::Type::PRESET; 417 t.attr.preset.rangeOffset = 0; 418 t.attr.preset.rangeLength = bytesCount; 419 native_handle_t* fenceNh = native_handle_create(0, 0); 420 ASSERT_NE(fenceNh, nullptr); 421 status = omxNode->emptyBuffer((*buffArray)[bufferIndex].id, t, flags, 422 timestamp, fenceNh); 423 native_handle_close(fenceNh); 424 native_handle_delete(fenceNh); 425 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 426 buffArray->editItemAt(bufferIndex).owner = component; 427} 428 429// Flush input and output ports 430void flushPorts(sp<IOmxNode> omxNode, sp<CodecObserver> observer, 431 android::Vector<BufferInfo>* iBuffer, 432 android::Vector<BufferInfo>* oBuffer, OMX_U32 kPortIndexInput, 433 OMX_U32 kPortIndexOutput) { 434 android::hardware::media::omx::V1_0::Status status; 435 Message msg; 436 437 // Flush input port 438 status = omxNode->sendCommand(toRawCommandType(OMX_CommandFlush), 439 kPortIndexInput); 440 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 441 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer); 442 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 443 ASSERT_EQ(msg.type, Message::Type::EVENT); 444 ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete); 445 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandFlush); 446 ASSERT_EQ(msg.data.eventData.data2, kPortIndexInput); 447 // test if client got all its buffers back 448 for (size_t i = 0; i < iBuffer->size(); ++i) { 449 EXPECT_EQ((*iBuffer)[i].owner, client); 450 } 451 452 // Flush output port 453 status = omxNode->sendCommand(toRawCommandType(OMX_CommandFlush), 454 kPortIndexOutput); 455 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 456 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer); 457 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 458 ASSERT_EQ(msg.type, Message::Type::EVENT); 459 ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete); 460 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandFlush); 461 ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput); 462 // test if client got all its buffers back 463 for (size_t i = 0; i < oBuffer->size(); ++i) { 464 EXPECT_EQ((*oBuffer)[i].owner, client); 465 } 466} 467 468Return<android::hardware::media::omx::V1_0::Status> setVideoPortFormat( 469 sp<IOmxNode> omxNode, OMX_U32 portIndex, 470 OMX_VIDEO_CODINGTYPE compressionFormat, OMX_COLOR_FORMATTYPE colorFormat, 471 OMX_U32 frameRate) { 472 OMX_U32 index = 0; 473 OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat; 474 std::vector<OMX_COLOR_FORMATTYPE> eColorFormat; 475 std::vector<OMX_VIDEO_CODINGTYPE> eCompressionFormat; 476 android::hardware::media::omx::V1_0::Status status; 477 478 while (1) { 479 portFormat.nIndex = index; 480 status = getPortParam(omxNode, OMX_IndexParamVideoPortFormat, portIndex, 481 &portFormat); 482 if (status != ::android::hardware::media::omx::V1_0::Status::OK) break; 483 if (compressionFormat == OMX_VIDEO_CodingUnused) 484 eColorFormat.push_back(portFormat.eColorFormat); 485 else 486 eCompressionFormat.push_back(portFormat.eCompressionFormat); 487 index++; 488 if (index == 512) { 489 // enumerated way too many formats, highly unusual for this to 490 // happen. 491 EXPECT_LE(index, 512U) 492 << "Expecting OMX_ErrorNoMore but not received"; 493 break; 494 } 495 } 496 if (!index) return status; 497 if (compressionFormat == OMX_VIDEO_CodingUnused) { 498 for (index = 0; index < eColorFormat.size(); index++) { 499 if (eColorFormat[index] == colorFormat) { 500 portFormat.eColorFormat = eColorFormat[index]; 501 break; 502 } 503 } 504 if (index == eColorFormat.size()) { 505 ALOGI("setting default color format"); 506 portFormat.eColorFormat = eColorFormat[0]; 507 } 508 portFormat.eCompressionFormat = OMX_VIDEO_CodingUnused; 509 } else { 510 for (index = 0; index < eCompressionFormat.size(); index++) { 511 if (eCompressionFormat[index] == compressionFormat) { 512 portFormat.eCompressionFormat = eCompressionFormat[index]; 513 break; 514 } 515 } 516 if (index == eCompressionFormat.size()) { 517 ALOGI("setting default compression format"); 518 portFormat.eCompressionFormat = eCompressionFormat[0]; 519 } 520 portFormat.eColorFormat = OMX_COLOR_FormatUnused; 521 } 522 // In setParam call nIndex shall be ignored as per omx-il specification. 523 // see how this holds up by corrupting nIndex 524 portFormat.nIndex = RANDOM_INDEX; 525 portFormat.xFramerate = frameRate; 526 status = setPortParam(omxNode, OMX_IndexParamVideoPortFormat, portIndex, 527 &portFormat); 528 return status; 529} 530 531Return<android::hardware::media::omx::V1_0::Status> setAudioPortFormat( 532 sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE encoding) { 533 OMX_U32 index = 0; 534 OMX_AUDIO_PARAM_PORTFORMATTYPE portFormat; 535 std::vector<OMX_AUDIO_CODINGTYPE> eEncoding; 536 android::hardware::media::omx::V1_0::Status status; 537 538 while (1) { 539 portFormat.nIndex = index; 540 status = getPortParam(omxNode, OMX_IndexParamAudioPortFormat, portIndex, 541 &portFormat); 542 if (status != ::android::hardware::media::omx::V1_0::Status::OK) break; 543 eEncoding.push_back(portFormat.eEncoding); 544 index++; 545 if (index == 512) { 546 // enumerated way too many formats, highly unusual for this to 547 // happen. 548 EXPECT_LE(index, 512U) 549 << "Expecting OMX_ErrorNoMore but not received"; 550 break; 551 } 552 } 553 if (!index) return status; 554 for (index = 0; index < eEncoding.size(); index++) { 555 if (eEncoding[index] == encoding) { 556 portFormat.eEncoding = eEncoding[index]; 557 break; 558 } 559 } 560 if (index == eEncoding.size()) { 561 ALOGI("setting default Port format"); 562 portFormat.eEncoding = eEncoding[0]; 563 } 564 // In setParam call nIndex shall be ignored as per omx-il specification. 565 // see how this holds up by corrupting nIndex 566 portFormat.nIndex = RANDOM_INDEX; 567 status = setPortParam(omxNode, OMX_IndexParamAudioPortFormat, portIndex, 568 &portFormat); 569 return status; 570} 571 572Return<android::hardware::media::omx::V1_0::Status> setRole( 573 sp<IOmxNode> omxNode, const char* role) { 574 OMX_PARAM_COMPONENTROLETYPE params; 575 strcpy((char*)params.cRole, role); 576 return setParam(omxNode, OMX_IndexParamStandardComponentRole, ¶ms); 577} 578 579TEST_F(ComponentHidlTest, SetRole) { 580 description("Test Set Component Role"); 581 android::hardware::media::omx::V1_0::Status status; 582 status = setRole(omxNode, gEnv->getRole().c_str()); 583 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 584} 585 586TEST_F(ComponentHidlTest, GetPortIndices) { 587 description("Test Component on Mandatory Port Parameters (Port ID's)"); 588 android::hardware::media::omx::V1_0::Status status; 589 OMX_PORT_PARAM_TYPE params; 590 591 status = setRole(omxNode, gEnv->getRole().c_str()); 592 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 593 594 // Get Number of Ports and their Indices for all Domains 595 // (Audio/Video/Image/Other) 596 // All standard OMX components shall support following OMX Index types 597 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms); 598 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 599 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms); 600 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 601 status = getParam(omxNode, OMX_IndexParamImageInit, ¶ms); 602 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 603 status = getParam(omxNode, OMX_IndexParamOtherInit, ¶ms); 604 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 605} 606 607TEST_F(ComponentHidlTest, EnumeratePortFormat) { 608 description("Test Component on Mandatory Port Parameters (Port Format)"); 609 android::hardware::media::omx::V1_0::Status status; 610 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1; 611 612 status = setRole(omxNode, gEnv->getRole().c_str()); 613 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 614 OMX_PORT_PARAM_TYPE params; 615 if (compClass == audio_decoder || compClass == audio_encoder) { 616 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms); 617 } else { 618 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms); 619 } 620 if (status == ::android::hardware::media::omx::V1_0::Status::OK) { 621 ASSERT_EQ(params.nPorts, 2U); 622 kPortIndexInput = params.nStartPortNumber; 623 kPortIndexOutput = kPortIndexInput + 1; 624 } 625 626 OMX_COLOR_FORMATTYPE colorFormat = OMX_COLOR_FormatYUV420Planar; 627 OMX_U32 frameRate = 24 << 16; 628 629 // Enumerate Port Format 630 if (compClass == audio_encoder) { 631 status = 632 setAudioPortFormat(omxNode, kPortIndexInput, OMX_AUDIO_CodingPCM); 633 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 634 status = setAudioPortFormat(omxNode, kPortIndexOutput, 635 OMX_AUDIO_CodingAutoDetect); 636 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 637 } else if (compClass == audio_decoder) { 638 status = setAudioPortFormat(omxNode, kPortIndexInput, 639 OMX_AUDIO_CodingAutoDetect); 640 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 641 status = 642 setAudioPortFormat(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM); 643 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 644 } else if (compClass == video_encoder) { 645 status = 646 setVideoPortFormat(omxNode, kPortIndexInput, OMX_VIDEO_CodingUnused, 647 colorFormat, frameRate); 648 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 649 status = setVideoPortFormat(omxNode, kPortIndexOutput, 650 OMX_VIDEO_CodingAutoDetect, 651 OMX_COLOR_FormatUnused, 0U); 652 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 653 } else { 654 status = setVideoPortFormat(omxNode, kPortIndexInput, 655 OMX_VIDEO_CodingAutoDetect, 656 OMX_COLOR_FormatUnused, 0U); 657 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 658 status = 659 setVideoPortFormat(omxNode, kPortIndexOutput, 660 OMX_VIDEO_CodingUnused, colorFormat, frameRate); 661 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 662 } 663} 664 665TEST_F(ComponentHidlTest, SetDefaultPortParams) { 666 description( 667 "Test Component on Mandatory Port Parameters (Port Definition)"); 668 android::hardware::media::omx::V1_0::Status status; 669 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1; 670 671 status = setRole(omxNode, gEnv->getRole().c_str()); 672 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 673 OMX_PORT_PARAM_TYPE params; 674 if (compClass == audio_decoder || compClass == audio_encoder) { 675 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms); 676 } else { 677 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms); 678 } 679 if (status == ::android::hardware::media::omx::V1_0::Status::OK) { 680 ASSERT_EQ(params.nPorts, 2U); 681 kPortIndexInput = params.nStartPortNumber; 682 kPortIndexOutput = kPortIndexInput + 1; 683 } 684 685 // r/w default i/o port parameters 686 OMX_PARAM_PORTDEFINITIONTYPE iPortDef; 687 status = getPortParam(omxNode, OMX_IndexParamPortDefinition, 688 kPortIndexInput, &iPortDef); 689 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 690 if (status == android::hardware::media::omx::V1_0::Status::OK) { 691 EXPECT_EQ(iPortDef.eDir, OMX_DirInput); 692 EXPECT_EQ(iPortDef.bEnabled, OMX_TRUE); 693 EXPECT_EQ(iPortDef.bPopulated, OMX_FALSE); 694 EXPECT_GE(iPortDef.nBufferCountMin, 1U); 695 EXPECT_GE(iPortDef.nBufferCountActual, iPortDef.nBufferCountMin); 696 if (compClass == audio_encoder || compClass == audio_decoder) { 697 EXPECT_EQ(iPortDef.eDomain, OMX_PortDomainAudio); 698 if (compClass == audio_decoder) { 699 iPortDef.format.audio.bFlagErrorConcealment = OMX_TRUE; 700 status = setPortParam(omxNode, OMX_IndexParamPortDefinition, 701 kPortIndexInput, &iPortDef); 702 } 703 EXPECT_EQ(status, 704 ::android::hardware::media::omx::V1_0::Status::OK); 705 } else if (compClass == video_encoder || compClass == video_decoder) { 706 EXPECT_EQ(iPortDef.eDomain, OMX_PortDomainVideo); 707 } 708 OMX_PARAM_PORTDEFINITIONTYPE dummy = iPortDef; 709 iPortDef.nBufferCountActual = iPortDef.nBufferCountMin - 1; 710 status = setPortParam(omxNode, OMX_IndexParamPortDefinition, 711 kPortIndexInput, &iPortDef); 712 EXPECT_NE(status, ::android::hardware::media::omx::V1_0::Status::OK); 713 // Edit Read-Only fields. 714 iPortDef.eDir = OMX_DirOutput; // Read Only field 715 iPortDef.nBufferCountActual = dummy.nBufferCountActual << 1; 716 iPortDef.nBufferCountMin = dummy.nBufferCountMin 717 << 1; // Read Only field 718 iPortDef.nBufferSize = dummy.nBufferSize << 1; // Read Only field 719 status = setPortParam(omxNode, OMX_IndexParamPortDefinition, 720 kPortIndexInput, &iPortDef); 721 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 722 status = getPortParam(omxNode, OMX_IndexParamPortDefinition, 723 kPortIndexInput, &iPortDef); 724 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 725 EXPECT_EQ(iPortDef.nBufferCountActual, dummy.nBufferCountActual << 1); 726 if ((iPortDef.eDir != OMX_DirInput) || 727 (iPortDef.nBufferCountMin != dummy.nBufferCountMin) || 728 (iPortDef.nBufferSize != dummy.nBufferSize)) { 729 std::cerr << "[ ] Warning ! Component input port does not " 730 "preserve Read-Only fields \n"; 731 } 732 } 733 734 OMX_PARAM_PORTDEFINITIONTYPE oPortDef; 735 status = getPortParam(omxNode, OMX_IndexParamPortDefinition, 736 kPortIndexOutput, &oPortDef); 737 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 738 if (status == ::android::hardware::media::omx::V1_0::Status::OK) { 739 EXPECT_EQ(oPortDef.eDir, OMX_DirOutput); 740 EXPECT_EQ(oPortDef.bEnabled, OMX_TRUE); 741 EXPECT_EQ(oPortDef.bPopulated, OMX_FALSE); 742 EXPECT_GE(oPortDef.nBufferCountMin, 1U); 743 EXPECT_GE(oPortDef.nBufferCountActual, oPortDef.nBufferCountMin); 744 if (compClass == audio_encoder || compClass == audio_decoder) { 745 EXPECT_EQ(oPortDef.eDomain, OMX_PortDomainAudio); 746 if (compClass == audio_encoder) { 747 oPortDef.format.audio.bFlagErrorConcealment = OMX_TRUE; 748 status = setPortParam(omxNode, OMX_IndexParamPortDefinition, 749 kPortIndexOutput, &oPortDef); 750 } 751 EXPECT_EQ(status, 752 ::android::hardware::media::omx::V1_0::Status::OK); 753 } else if (compClass == video_encoder || compClass == video_decoder) { 754 EXPECT_EQ(oPortDef.eDomain, OMX_PortDomainVideo); 755 } 756 OMX_PARAM_PORTDEFINITIONTYPE dummy = oPortDef; 757 oPortDef.nBufferCountActual = oPortDef.nBufferCountMin - 1; 758 status = setPortParam(omxNode, OMX_IndexParamPortDefinition, 759 kPortIndexOutput, &oPortDef); 760 EXPECT_NE(status, ::android::hardware::media::omx::V1_0::Status::OK); 761 // Edit Read-Only fields. 762 oPortDef.eDir = OMX_DirInput; // Read Only field 763 oPortDef.nBufferCountActual = dummy.nBufferCountActual << 1; 764 oPortDef.nBufferCountMin = dummy.nBufferCountMin 765 << 1; // Read Only field 766 oPortDef.nBufferSize = dummy.nBufferSize << 1; // Read Only field 767 status = setPortParam(omxNode, OMX_IndexParamPortDefinition, 768 kPortIndexOutput, &oPortDef); 769 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 770 status = getPortParam(omxNode, OMX_IndexParamPortDefinition, 771 kPortIndexOutput, &oPortDef); 772 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 773 EXPECT_EQ(oPortDef.nBufferCountActual, dummy.nBufferCountActual << 1); 774 if ((oPortDef.eDir != OMX_DirOutput) || 775 (oPortDef.nBufferCountMin != dummy.nBufferCountMin) || 776 (oPortDef.nBufferSize != dummy.nBufferSize)) { 777 std::cerr << "[ ] Warning ! Component output port does " 778 "not preserve Read-Only fields \n"; 779 } 780 } 781} 782 783TEST_F(ComponentHidlTest, PopulatePort) { 784 description("Verify bPopulated field of a component port"); 785 android::hardware::media::omx::V1_0::Status status; 786 OMX_U32 portBase = 0; 787 788 status = setRole(omxNode, gEnv->getRole().c_str()); 789 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 790 OMX_PORT_PARAM_TYPE params; 791 if (compClass == audio_decoder || compClass == audio_encoder) { 792 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms); 793 } else { 794 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms); 795 } 796 if (status == ::android::hardware::media::omx::V1_0::Status::OK) { 797 ASSERT_EQ(params.nPorts, 2U); 798 portBase = params.nStartPortNumber; 799 } 800 801 sp<IAllocator> allocator = IAllocator::getService("ashmem"); 802 EXPECT_NE(allocator.get(), nullptr); 803 804 OMX_PARAM_PORTDEFINITIONTYPE portDef; 805 status = 806 getPortParam(omxNode, OMX_IndexParamPortDefinition, portBase, &portDef); 807 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 808 ASSERT_EQ(portDef.bPopulated, OMX_FALSE); 809 810 android::Vector<BufferInfo> pBuffer; 811 pBuffer.clear(); 812 uint32_t nBufferSize = portDef.nBufferSize >> 1; 813 814 for (size_t i = 0; i < portDef.nBufferCountActual; i++) { 815 BufferInfo buffer; 816 buffer.owner = client; 817 buffer.omxBuffer.type = CodecBuffer::Type::SHARED_MEM; 818 buffer.omxBuffer.attr.preset.rangeOffset = 0; 819 buffer.omxBuffer.attr.preset.rangeLength = 0; 820 bool success = false; 821 allocator->allocate( 822 nBufferSize, 823 [&success, &buffer](bool _s, 824 ::android::hardware::hidl_memory const& mem) { 825 success = _s; 826 buffer.omxBuffer.sharedMemory = mem; 827 }); 828 ASSERT_EQ(success, true); 829 ASSERT_EQ(buffer.omxBuffer.sharedMemory.size(), nBufferSize); 830 831 omxNode->useBuffer( 832 portBase, buffer.omxBuffer, 833 [&status, &buffer](android::hardware::media::omx::V1_0::Status _s, 834 uint32_t id) { 835 status = _s; 836 buffer.id = id; 837 }); 838 pBuffer.push(buffer); 839 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 840 } 841 842 status = 843 getPortParam(omxNode, OMX_IndexParamPortDefinition, portBase, &portDef); 844 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 845 // A port is populated when all of the buffers indicated by 846 // nBufferCountActual 847 // with a size of at least nBufferSizehave been allocated on the port. 848 ASSERT_EQ(portDef.bPopulated, OMX_FALSE); 849} 850 851TEST_F(ComponentHidlTest, Flush) { 852 description("Test Flush"); 853 android::hardware::media::omx::V1_0::Status status; 854 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1; 855 Message msg; 856 857 status = setRole(omxNode, gEnv->getRole().c_str()); 858 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 859 OMX_PORT_PARAM_TYPE params; 860 if (compClass == audio_decoder || compClass == audio_encoder) { 861 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms); 862 } else { 863 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms); 864 } 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 android::Vector<BufferInfo> iBuffer, oBuffer; 872 873 // set state to idle 874 changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer, 875 kPortIndexInput, kPortIndexOutput); 876 // set state to executing 877 changeStateIdletoExecute(omxNode, observer); 878 // dispatch buffers 879 for (size_t i = 0; i < oBuffer.size(); i++) { 880 dispatchOutputBuffer(omxNode, &oBuffer, i); 881 } 882 // flush port 883 flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput, 884 kPortIndexOutput); 885 // dispatch buffers 886 for (size_t i = 0; i < iBuffer.size(); i++) { 887 dispatchInputBuffer(omxNode, &iBuffer, i, 0, 0, 0); 888 } 889 // flush ports 890 flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput, 891 kPortIndexOutput); 892 // set state to idle 893 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer); 894 // set state to loaded 895 changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer, 896 kPortIndexInput, kPortIndexOutput); 897} 898 899TEST_F(ComponentHidlTest, StateTransitions) { 900 description("Test State Transitions"); 901 android::hardware::media::omx::V1_0::Status status; 902 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1; 903 Message msg; 904 905 status = setRole(omxNode, gEnv->getRole().c_str()); 906 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 907 OMX_PORT_PARAM_TYPE params; 908 if (compClass == audio_decoder || compClass == audio_encoder) { 909 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms); 910 } else { 911 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms); 912 } 913 if (status == ::android::hardware::media::omx::V1_0::Status::OK) { 914 ASSERT_EQ(params.nPorts, 2U); 915 kPortIndexInput = params.nStartPortNumber; 916 kPortIndexOutput = kPortIndexInput + 1; 917 } 918 919 android::Vector<BufferInfo> iBuffer, oBuffer; 920 921 // set state to idle 922 changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer, 923 kPortIndexInput, kPortIndexOutput); 924 // set state to executing 925 changeStateIdletoExecute(omxNode, observer); 926 // dispatch buffers 927 for (size_t i = 0; i < oBuffer.size(); i++) { 928 dispatchOutputBuffer(omxNode, &oBuffer, i); 929 } 930 // set state to idle 931 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer); 932 // set state to executing 933 changeStateIdletoExecute(omxNode, observer); 934 // dispatch buffers 935 for (size_t i = 0; i < iBuffer.size(); i++) { 936 dispatchInputBuffer(omxNode, &iBuffer, i, 0, 0, 0); 937 } 938 // set state to idle 939 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer); 940 // set state to loaded 941 changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer, 942 kPortIndexInput, kPortIndexOutput); 943} 944 945TEST_F(ComponentHidlTest, StateTransitions_M) { 946 description("Test State Transitions monkeying"); 947 android::hardware::media::omx::V1_0::Status status; 948 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1; 949 Message msg; 950 951 status = setRole(omxNode, gEnv->getRole().c_str()); 952 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 953 OMX_PORT_PARAM_TYPE params; 954 if (compClass == audio_decoder || compClass == audio_encoder) { 955 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms); 956 } else { 957 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms); 958 } 959 if (status == ::android::hardware::media::omx::V1_0::Status::OK) { 960 ASSERT_EQ(params.nPorts, 2U); 961 kPortIndexInput = params.nStartPortNumber; 962 kPortIndexOutput = kPortIndexInput + 1; 963 } 964 965 android::Vector<BufferInfo> iBuffer, oBuffer; 966 967 // set state to loaded ; receive error OMX_ErrorSameState 968 status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet), 969 OMX_StateLoaded); 970 EXPECT_NE(status, android::hardware::media::omx::V1_0::Status::OK); 971 972 // set state to executing ; receive error OMX_ErrorIncorrectStateTransition 973 status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet), 974 OMX_StateExecuting); 975 EXPECT_NE(status, android::hardware::media::omx::V1_0::Status::OK); 976 977 // set state to idle 978 changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer, 979 kPortIndexInput, kPortIndexOutput); 980 981 // set state to idle ; receive error OMX_ErrorSameState 982 status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet), 983 OMX_StateIdle); 984 EXPECT_NE(status, android::hardware::media::omx::V1_0::Status::OK); 985 986 // set state to executing 987 changeStateIdletoExecute(omxNode, observer); 988 989 // set state to executing ; receive error OMX_ErrorSameState 990 status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet), 991 OMX_StateExecuting); 992 EXPECT_NE(status, android::hardware::media::omx::V1_0::Status::OK); 993 994 // set state to Loaded ; receive error OMX_ErrorIncorrectStateTransition 995 status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet), 996 OMX_StateLoaded); 997 EXPECT_NE(status, android::hardware::media::omx::V1_0::Status::OK); 998 999 // set state to Idle 1000 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer); 1001 1002 // set state to Loaded 1003 changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer, 1004 kPortIndexInput, kPortIndexOutput); 1005} 1006 1007TEST_F(ComponentHidlTest, PortEnableDisable_Loaded) { 1008 description("Test Port Enable and Disable (Component State :: Loaded)"); 1009 android::hardware::media::omx::V1_0::Status status; 1010 OMX_U32 portBase = 0; 1011 Message msg; 1012 status = setRole(omxNode, gEnv->getRole().c_str()); 1013 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 1014 OMX_PORT_PARAM_TYPE params; 1015 if (compClass == audio_decoder || compClass == audio_encoder) { 1016 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms); 1017 } else { 1018 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms); 1019 } 1020 if (status == ::android::hardware::media::omx::V1_0::Status::OK) { 1021 ASSERT_EQ(params.nPorts, 2U); 1022 portBase = params.nStartPortNumber; 1023 } 1024 1025 for (size_t i = portBase; i < portBase + 2; i++) { 1026 status = 1027 omxNode->sendCommand(toRawCommandType(OMX_CommandPortDisable), i); 1028 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 1029 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT); 1030 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 1031 ASSERT_EQ(msg.type, Message::Type::EVENT); 1032 if (msg.data.eventData.event == OMX_EventCmdComplete) { 1033 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortDisable); 1034 ASSERT_EQ(msg.data.eventData.data2, i); 1035 // If you can disable a port, then you should be able to enable it 1036 // as well 1037 status = omxNode->sendCommand( 1038 toRawCommandType(OMX_CommandPortEnable), i); 1039 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 1040 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT); 1041 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 1042 ASSERT_EQ(msg.type, Message::Type::EVENT); 1043 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortEnable); 1044 ASSERT_EQ(msg.data.eventData.data2, i); 1045 } else if (msg.data.eventData.event == OMX_EventError) { 1046 ALOGI("Port %d Disabling failed with error %d", (int)i, 1047 (int)msg.data.eventData.event); 1048 } else { 1049 // something unexpected happened 1050 ASSERT_TRUE(false); 1051 } 1052 } 1053} 1054 1055TEST_F(ComponentHidlTest, PortEnableDisable_Idle) { 1056 description("Test Port Enable and Disable (Component State :: Idle)"); 1057 android::hardware::media::omx::V1_0::Status status; 1058 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1; 1059 OMX_U32 portBase = 0; 1060 Message msg; 1061 status = setRole(omxNode, gEnv->getRole().c_str()); 1062 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 1063 OMX_PORT_PARAM_TYPE params; 1064 if (compClass == audio_decoder || compClass == audio_encoder) { 1065 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms); 1066 } else { 1067 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms); 1068 } 1069 if (status == ::android::hardware::media::omx::V1_0::Status::OK) { 1070 ASSERT_EQ(params.nPorts, 2U); 1071 portBase = params.nStartPortNumber; 1072 } 1073 kPortIndexInput = portBase; 1074 kPortIndexOutput = portBase + 1; 1075 1076 // Component State :: Idle 1077 android::Vector<BufferInfo> pBuffer[2]; 1078 1079 // set state to idle 1080 changeStateLoadedtoIdle(omxNode, observer, &pBuffer[0], &pBuffer[1], 1081 kPortIndexInput, kPortIndexOutput); 1082 1083 for (size_t i = portBase; i < portBase + 2; i++) { 1084 status = 1085 omxNode->sendCommand(toRawCommandType(OMX_CommandPortDisable), i); 1086 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 1087 1088 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &pBuffer[0], 1089 &pBuffer[1]); 1090 if (status == android::hardware::media::omx::V1_0::Status::OK) { 1091 ASSERT_EQ(msg.type, Message::Type::EVENT); 1092 if (msg.data.eventData.event == OMX_EventCmdComplete) { 1093 // do not disable the port until all the buffers are freed 1094 ASSERT_TRUE(false); 1095 } else if (msg.data.eventData.event == OMX_EventError) { 1096 ALOGI("Port %d Disabling failed with error %d", (int)i, 1097 (int)msg.data.eventData.event); 1098 } else { 1099 // something unexpected happened 1100 ASSERT_TRUE(false); 1101 } 1102 } else if (status == 1103 android::hardware::media::omx::V1_0::Status::TIMED_OUT) { 1104 for (size_t j = 0; j < pBuffer[i - portBase].size(); ++j) { 1105 status = omxNode->freeBuffer(i, pBuffer[i - portBase][j].id); 1106 ASSERT_EQ(status, 1107 android::hardware::media::omx::V1_0::Status::OK); 1108 } 1109 1110 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, 1111 &pBuffer[0], &pBuffer[1]); 1112 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 1113 ASSERT_EQ(msg.type, Message::Type::EVENT); 1114 ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete); 1115 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortDisable); 1116 ASSERT_EQ(msg.data.eventData.data2, i); 1117 1118 // If you can disable a port, then you should be able to enable it 1119 // as well 1120 status = omxNode->sendCommand( 1121 toRawCommandType(OMX_CommandPortEnable), i); 1122 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 1123 1124 // do not enable the port until all the buffers are supplied 1125 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, 1126 &pBuffer[0], &pBuffer[1]); 1127 ASSERT_EQ(status, 1128 android::hardware::media::omx::V1_0::Status::TIMED_OUT); 1129 1130 allocatePortBuffers(omxNode, &pBuffer[i - portBase], i); 1131 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, 1132 &pBuffer[0], &pBuffer[1]); 1133 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 1134 ASSERT_EQ(msg.type, Message::Type::EVENT); 1135 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortEnable); 1136 ASSERT_EQ(msg.data.eventData.data2, i); 1137 } else { 1138 // something unexpected happened 1139 ASSERT_TRUE(false); 1140 } 1141 } 1142 1143 // set state to Loaded 1144 changeStateIdletoLoaded(omxNode, observer, &pBuffer[0], &pBuffer[1], 1145 kPortIndexInput, kPortIndexOutput); 1146} 1147 1148TEST_F(ComponentHidlTest, PortEnableDisable_Execute) { 1149 description("Test Port Enable and Disable (Component State :: Execute)"); 1150 android::hardware::media::omx::V1_0::Status status; 1151 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1; 1152 OMX_U32 portBase = 0; 1153 Message msg; 1154 status = setRole(omxNode, gEnv->getRole().c_str()); 1155 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 1156 OMX_PORT_PARAM_TYPE params; 1157 if (compClass == audio_decoder || compClass == audio_encoder) { 1158 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms); 1159 } else { 1160 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms); 1161 } 1162 if (status == ::android::hardware::media::omx::V1_0::Status::OK) { 1163 ASSERT_EQ(params.nPorts, 2U); 1164 portBase = params.nStartPortNumber; 1165 } 1166 kPortIndexInput = portBase; 1167 kPortIndexOutput = portBase + 1; 1168 1169 // Component State :: Idle 1170 android::Vector<BufferInfo> pBuffer[2]; 1171 1172 // set state to idle 1173 changeStateLoadedtoIdle(omxNode, observer, &pBuffer[0], &pBuffer[1], 1174 kPortIndexInput, kPortIndexOutput); 1175 1176 // set state to executing 1177 changeStateIdletoExecute(omxNode, observer); 1178 1179 // dispatch buffers 1180 for (size_t i = 0; i < pBuffer[1].size(); i++) { 1181 dispatchOutputBuffer(omxNode, &pBuffer[1], i); 1182 } 1183 1184 for (size_t i = portBase; i < portBase + 2; i++) { 1185 status = 1186 omxNode->sendCommand(toRawCommandType(OMX_CommandPortDisable), i); 1187 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 1188 1189 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &pBuffer[0], 1190 &pBuffer[1]); 1191 if (status == android::hardware::media::omx::V1_0::Status::OK) { 1192 ASSERT_EQ(msg.type, Message::Type::EVENT); 1193 if (msg.data.eventData.event == OMX_EventCmdComplete) { 1194 // do not disable the port until all the buffers are freed 1195 ASSERT_TRUE(false); 1196 } else if (msg.data.eventData.event == OMX_EventError) { 1197 ALOGI("Port %d Disabling failed with error %d", (int)i, 1198 (int)msg.data.eventData.event); 1199 } else { 1200 // something unexpected happened 1201 ASSERT_TRUE(false); 1202 } 1203 } else if (status == 1204 android::hardware::media::omx::V1_0::Status::TIMED_OUT) { 1205 for (size_t j = 0; j < pBuffer[i - portBase].size(); ++j) { 1206 // test if client got all its buffers back 1207 EXPECT_EQ(pBuffer[i - portBase][j].owner, client); 1208 // free the buffers 1209 status = omxNode->freeBuffer(i, pBuffer[i - portBase][j].id); 1210 ASSERT_EQ(status, 1211 android::hardware::media::omx::V1_0::Status::OK); 1212 } 1213 1214 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, 1215 &pBuffer[0], &pBuffer[1]); 1216 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 1217 ASSERT_EQ(msg.type, Message::Type::EVENT); 1218 ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete); 1219 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortDisable); 1220 ASSERT_EQ(msg.data.eventData.data2, i); 1221 1222 // If you can disable a port, then you should be able to enable it 1223 // as well 1224 status = omxNode->sendCommand( 1225 toRawCommandType(OMX_CommandPortEnable), i); 1226 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 1227 1228 // do not enable the port until all the buffers are supplied 1229 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, 1230 &pBuffer[0], &pBuffer[1]); 1231 ASSERT_EQ(status, 1232 android::hardware::media::omx::V1_0::Status::TIMED_OUT); 1233 1234 allocatePortBuffers(omxNode, &pBuffer[i - portBase], i); 1235 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, 1236 &pBuffer[0], &pBuffer[1]); 1237 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 1238 ASSERT_EQ(msg.type, Message::Type::EVENT); 1239 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortEnable); 1240 ASSERT_EQ(msg.data.eventData.data2, i); 1241 } else { 1242 // something unexpected happened 1243 ASSERT_TRUE(false); 1244 } 1245 } 1246 1247 // set state to Idle 1248 changeStateExecutetoIdle(omxNode, observer, &pBuffer[0], &pBuffer[1]); 1249 1250 // set state to Loaded 1251 changeStateIdletoLoaded(omxNode, observer, &pBuffer[0], &pBuffer[1], 1252 kPortIndexInput, kPortIndexOutput); 1253} 1254 1255TEST_F(ComponentHidlTest, PortEnableDisable_M) { 1256 description( 1257 "Test Port Enable and Disable Monkeying (Component State :: Loaded)"); 1258 android::hardware::media::omx::V1_0::Status status; 1259 OMX_U32 portBase = 0; 1260 Message msg; 1261 status = setRole(omxNode, gEnv->getRole().c_str()); 1262 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 1263 OMX_PORT_PARAM_TYPE params; 1264 if (compClass == audio_decoder || compClass == audio_encoder) { 1265 status = getParam(omxNode, OMX_IndexParamAudioInit, ¶ms); 1266 } else { 1267 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms); 1268 } 1269 if (status == ::android::hardware::media::omx::V1_0::Status::OK) { 1270 ASSERT_EQ(params.nPorts, 2U); 1271 portBase = params.nStartPortNumber; 1272 } 1273 1274 // disable invalid port, expecting OMX_ErrorBadPortIndex 1275 status = omxNode->sendCommand(toRawCommandType(OMX_CommandPortDisable), 1276 RANDOM_INDEX); 1277 ASSERT_NE(status, android::hardware::media::omx::V1_0::Status::OK); 1278 1279 // enable invalid port, expecting OMX_ErrorBadPortIndex 1280 status = omxNode->sendCommand(toRawCommandType(OMX_CommandPortEnable), 1281 RANDOM_INDEX); 1282 ASSERT_NE(status, android::hardware::media::omx::V1_0::Status::OK); 1283 1284 // disable all ports 1285 status = 1286 omxNode->sendCommand(toRawCommandType(OMX_CommandPortDisable), OMX_ALL); 1287 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 1288 for (size_t i = 0; i < 2; i++) { 1289 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT); 1290 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 1291 ASSERT_EQ(msg.type, Message::Type::EVENT); 1292 if (msg.data.eventData.event == OMX_EventCmdComplete) { 1293 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortDisable); 1294 if (msg.data.eventData.data2 != portBase || 1295 msg.data.eventData.data2 != portBase + 1) 1296 EXPECT_TRUE(false); 1297 } else if (msg.data.eventData.event == OMX_EventError) { 1298 ALOGI("Port %d Disabling failed with error %d", (int)i, 1299 (int)msg.data.eventData.event); 1300 } else { 1301 // something unexpected happened 1302 ASSERT_TRUE(false); 1303 } 1304 } 1305 1306 // enable all ports 1307 status = 1308 omxNode->sendCommand(toRawCommandType(OMX_CommandPortEnable), OMX_ALL); 1309 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 1310 for (size_t i = 0; i < 2; i++) { 1311 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT); 1312 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 1313 ASSERT_EQ(msg.type, Message::Type::EVENT); 1314 if (msg.data.eventData.event == OMX_EventCmdComplete) { 1315 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortEnable); 1316 if (msg.data.eventData.data2 != portBase || 1317 msg.data.eventData.data2 != portBase + 1) 1318 EXPECT_TRUE(false); 1319 } else if (msg.data.eventData.event == OMX_EventError) { 1320 ALOGI("Port %d Enabling failed with error %d", (int)i, 1321 (int)msg.data.eventData.event); 1322 } else { 1323 // something unexpected happened 1324 ASSERT_TRUE(false); 1325 } 1326 } 1327} 1328 1329int main(int argc, char** argv) { 1330 gEnv = new ComponentTestEnvironment(); 1331 ::testing::AddGlobalTestEnvironment(gEnv); 1332 ::testing::InitGoogleTest(&argc, argv); 1333 int status = gEnv->initFromOptions(argc, argv); 1334 if (status == 0) { 1335 status = RUN_ALL_TESTS(); 1336 ALOGI("Test result = %d", status); 1337 } 1338 return status; 1339} 1340