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_test_common" 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/graphics/allocator/2.0/IAllocator.h> 25 #include <android/hardware/graphics/mapper/2.0/IMapper.h> 26 #include <android/hardware/graphics/mapper/2.0/types.h> 27 #include <android/hardware/media/omx/1.0/IOmx.h> 28 #include <android/hardware/media/omx/1.0/IOmxNode.h> 29 #include <android/hardware/media/omx/1.0/IOmxObserver.h> 30 #include <android/hardware/media/omx/1.0/types.h> 31 #include <android/hidl/allocator/1.0/IAllocator.h> 32 #include <android/hidl/memory/1.0/IMapper.h> 33 #include <android/hidl/memory/1.0/IMemory.h> 34 #include <cutils/atomic.h> 35 36 using ::android::hardware::graphics::common::V1_0::BufferUsage; 37 using ::android::hardware::graphics::common::V1_0::PixelFormat; 38 using ::android::hardware::media::omx::V1_0::IOmx; 39 using ::android::hardware::media::omx::V1_0::IOmxObserver; 40 using ::android::hardware::media::omx::V1_0::IOmxNode; 41 using ::android::hardware::media::omx::V1_0::Message; 42 using ::android::hardware::media::omx::V1_0::CodecBuffer; 43 using ::android::hardware::media::omx::V1_0::PortMode; 44 using ::android::hardware::media::omx::V1_0::Status; 45 using ::android::hidl::allocator::V1_0::IAllocator; 46 using ::android::hidl::memory::V1_0::IMemory; 47 using ::android::hidl::memory::V1_0::IMapper; 48 using ::android::hardware::Return; 49 using ::android::hardware::Void; 50 using ::android::hardware::hidl_vec; 51 using ::android::hardware::hidl_string; 52 using ::android::sp; 53 54 #include <VtsHalHidlTargetTestBase.h> 55 #include <hidlmemory/mapping.h> 56 #include <media/hardware/HardwareAPI.h> 57 #include <media_hidl_test_common.h> 58 #include <memory> 59 60 // set component role 61 Return<android::hardware::media::omx::V1_0::Status> setRole( 62 sp<IOmxNode> omxNode, const char* role) { 63 OMX_PARAM_COMPONENTROLETYPE params; 64 strcpy((char*)params.cRole, role); 65 return setParam(omxNode, OMX_IndexParamStandardComponentRole, ¶ms); 66 } 67 68 Return<android::hardware::media::omx::V1_0::Status> setPortBufferSize( 69 sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_U32 size) { 70 android::hardware::media::omx::V1_0::Status status; 71 OMX_PARAM_PORTDEFINITIONTYPE portDef; 72 73 status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex, 74 &portDef); 75 if (status != ::android::hardware::media::omx::V1_0::Status::OK) 76 return status; 77 if (portDef.nBufferSize < size) { 78 portDef.nBufferSize = size; 79 status = setPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex, 80 &portDef); 81 if (status != ::android::hardware::media::omx::V1_0::Status::OK) 82 return status; 83 } 84 return status; 85 } 86 87 // get/set video component port format 88 Return<android::hardware::media::omx::V1_0::Status> setVideoPortFormat( 89 sp<IOmxNode> omxNode, OMX_U32 portIndex, 90 OMX_VIDEO_CODINGTYPE eCompressionFormat, OMX_COLOR_FORMATTYPE eColorFormat, 91 OMX_U32 xFramerate) { 92 OMX_U32 index = 0; 93 OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat; 94 std::vector<OMX_COLOR_FORMATTYPE> arrColorFormat; 95 std::vector<OMX_VIDEO_CODINGTYPE> arrCompressionFormat; 96 android::hardware::media::omx::V1_0::Status status; 97 98 while (1) { 99 portFormat.nIndex = index; 100 status = getPortParam(omxNode, OMX_IndexParamVideoPortFormat, portIndex, 101 &portFormat); 102 if (status != ::android::hardware::media::omx::V1_0::Status::OK) break; 103 if (eCompressionFormat == OMX_VIDEO_CodingUnused) 104 arrColorFormat.push_back(portFormat.eColorFormat); 105 else 106 arrCompressionFormat.push_back(portFormat.eCompressionFormat); 107 index++; 108 if (index == 512) { 109 // enumerated way too many formats, highly unusual for this to 110 // happen. 111 EXPECT_LE(index, 512U) 112 << "Expecting OMX_ErrorNoMore but not received"; 113 break; 114 } 115 } 116 if (!index) return status; 117 if (eCompressionFormat == OMX_VIDEO_CodingUnused) { 118 for (index = 0; index < arrColorFormat.size(); index++) { 119 if (arrColorFormat[index] == eColorFormat) { 120 portFormat.eColorFormat = arrColorFormat[index]; 121 break; 122 } 123 } 124 if (index == arrColorFormat.size()) { 125 ALOGE("setting default color format %x", (int)arrColorFormat[0]); 126 portFormat.eColorFormat = arrColorFormat[0]; 127 } 128 portFormat.eCompressionFormat = OMX_VIDEO_CodingUnused; 129 } else { 130 for (index = 0; index < arrCompressionFormat.size(); index++) { 131 if (arrCompressionFormat[index] == eCompressionFormat) { 132 portFormat.eCompressionFormat = arrCompressionFormat[index]; 133 break; 134 } 135 } 136 if (index == arrCompressionFormat.size()) { 137 ALOGE("setting default compression format %x", 138 (int)arrCompressionFormat[0]); 139 portFormat.eCompressionFormat = arrCompressionFormat[0]; 140 } 141 portFormat.eColorFormat = OMX_COLOR_FormatUnused; 142 } 143 // In setParam call nIndex shall be ignored as per omx-il specification. 144 // see how this holds up by corrupting nIndex 145 portFormat.nIndex = RANDOM_INDEX; 146 portFormat.xFramerate = xFramerate; 147 status = setPortParam(omxNode, OMX_IndexParamVideoPortFormat, portIndex, 148 &portFormat); 149 return status; 150 } 151 152 // get/set audio component port format 153 Return<android::hardware::media::omx::V1_0::Status> setAudioPortFormat( 154 sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE eEncoding) { 155 OMX_U32 index = 0; 156 OMX_AUDIO_PARAM_PORTFORMATTYPE portFormat; 157 std::vector<OMX_AUDIO_CODINGTYPE> arrEncoding; 158 android::hardware::media::omx::V1_0::Status status; 159 160 while (1) { 161 portFormat.nIndex = index; 162 status = getPortParam(omxNode, OMX_IndexParamAudioPortFormat, portIndex, 163 &portFormat); 164 if (status != ::android::hardware::media::omx::V1_0::Status::OK) break; 165 arrEncoding.push_back(portFormat.eEncoding); 166 index++; 167 if (index == 512) { 168 // enumerated way too many formats, highly unusual for this to 169 // happen. 170 EXPECT_LE(index, 512U) 171 << "Expecting OMX_ErrorNoMore but not received"; 172 break; 173 } 174 } 175 if (!index) return status; 176 for (index = 0; index < arrEncoding.size(); index++) { 177 if (arrEncoding[index] == eEncoding) { 178 portFormat.eEncoding = arrEncoding[index]; 179 break; 180 } 181 } 182 if (index == arrEncoding.size()) { 183 ALOGE("setting default Port format %x", (int)arrEncoding[0]); 184 portFormat.eEncoding = arrEncoding[0]; 185 } 186 // In setParam call nIndex shall be ignored as per omx-il specification. 187 // see how this holds up by corrupting nIndex 188 portFormat.nIndex = RANDOM_INDEX; 189 status = setPortParam(omxNode, OMX_IndexParamAudioPortFormat, portIndex, 190 &portFormat); 191 return status; 192 } 193 194 void allocateGraphicBuffers(sp<IOmxNode> omxNode, OMX_U32 portIndex, 195 BufferInfo* buffer, uint32_t nFrameWidth, 196 uint32_t nFrameHeight, int32_t* nStride, 197 int format) { 198 android::hardware::media::omx::V1_0::Status status; 199 sp<android::hardware::graphics::allocator::V2_0::IAllocator> allocator = 200 android::hardware::graphics::allocator::V2_0::IAllocator::getService(); 201 ASSERT_NE(nullptr, allocator.get()); 202 203 sp<android::hardware::graphics::mapper::V2_0::IMapper> mapper = 204 android::hardware::graphics::mapper::V2_0::IMapper::getService(); 205 ASSERT_NE(mapper.get(), nullptr); 206 207 android::hardware::graphics::mapper::V2_0::IMapper::BufferDescriptorInfo 208 descriptorInfo; 209 uint32_t usage; 210 211 descriptorInfo.width = nFrameWidth; 212 descriptorInfo.height = nFrameHeight; 213 descriptorInfo.layerCount = 1; 214 descriptorInfo.format = static_cast<PixelFormat>(format); 215 descriptorInfo.usage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN); 216 omxNode->getGraphicBufferUsage( 217 portIndex, 218 [&status, &usage](android::hardware::media::omx::V1_0::Status _s, 219 uint32_t _n1) { 220 status = _s; 221 usage = _n1; 222 }); 223 if (status == android::hardware::media::omx::V1_0::Status::OK) { 224 descriptorInfo.usage |= usage; 225 } 226 227 ::android::hardware::hidl_vec<uint32_t> descriptor; 228 android::hardware::graphics::mapper::V2_0::Error error; 229 mapper->createDescriptor( 230 descriptorInfo, [&error, &descriptor]( 231 android::hardware::graphics::mapper::V2_0::Error _s, 232 ::android::hardware::hidl_vec<uint32_t> _n1) { 233 error = _s; 234 descriptor = _n1; 235 }); 236 ASSERT_EQ(error, android::hardware::graphics::mapper::V2_0::Error::NONE); 237 238 static volatile int32_t nextId = 0; 239 uint64_t id = static_cast<uint64_t>(getpid()) << 32; 240 allocator->allocate( 241 descriptor, 1, 242 [&](android::hardware::graphics::mapper::V2_0::Error _s, uint32_t _n1, 243 const ::android::hardware::hidl_vec< 244 ::android::hardware::hidl_handle>& _n2) { 245 ASSERT_EQ(android::hardware::graphics::mapper::V2_0::Error::NONE, 246 _s); 247 *nStride = _n1; 248 buffer->omxBuffer.nativeHandle = _n2[0]; 249 buffer->omxBuffer.attr.anwBuffer.width = nFrameWidth; 250 buffer->omxBuffer.attr.anwBuffer.height = nFrameHeight; 251 buffer->omxBuffer.attr.anwBuffer.stride = _n1; 252 buffer->omxBuffer.attr.anwBuffer.format = descriptorInfo.format; 253 buffer->omxBuffer.attr.anwBuffer.usage = descriptorInfo.usage; 254 buffer->omxBuffer.attr.anwBuffer.layerCount = 255 descriptorInfo.layerCount; 256 buffer->omxBuffer.attr.anwBuffer.id = 257 id | static_cast<uint32_t>(android_atomic_inc(&nextId)); 258 }); 259 } 260 261 // allocate buffers needed on a component port 262 void allocateBuffer(sp<IOmxNode> omxNode, BufferInfo* buffer, OMX_U32 portIndex, 263 OMX_U32 nBufferSize, PortMode portMode) { 264 android::hardware::media::omx::V1_0::Status status; 265 266 if (portMode == PortMode::PRESET_SECURE_BUFFER) { 267 buffer->owner = client; 268 buffer->omxBuffer.type = CodecBuffer::Type::NATIVE_HANDLE; 269 omxNode->allocateSecureBuffer( 270 portIndex, nBufferSize, 271 [&status, &buffer]( 272 android::hardware::media::omx::V1_0::Status _s, uint32_t id, 273 ::android::hardware::hidl_handle const& nativeHandle) { 274 status = _s; 275 buffer->id = id; 276 buffer->omxBuffer.nativeHandle = nativeHandle; 277 }); 278 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 279 } else if (portMode == PortMode::PRESET_BYTE_BUFFER || 280 portMode == PortMode::DYNAMIC_ANW_BUFFER) { 281 sp<IAllocator> allocator = IAllocator::getService("ashmem"); 282 ASSERT_NE(allocator.get(), nullptr); 283 284 buffer->owner = client; 285 buffer->omxBuffer.type = CodecBuffer::Type::SHARED_MEM; 286 buffer->omxBuffer.attr.preset.rangeOffset = 0; 287 buffer->omxBuffer.attr.preset.rangeLength = 0; 288 bool success = false; 289 if (portMode != PortMode::PRESET_BYTE_BUFFER) { 290 nBufferSize = sizeof(android::VideoNativeMetadata); 291 } 292 allocator->allocate( 293 nBufferSize, 294 [&success, &buffer](bool _s, 295 ::android::hardware::hidl_memory const& mem) { 296 success = _s; 297 buffer->omxBuffer.sharedMemory = mem; 298 }); 299 ASSERT_EQ(success, true); 300 ASSERT_EQ(buffer->omxBuffer.sharedMemory.size(), nBufferSize); 301 buffer->mMemory = mapMemory(buffer->omxBuffer.sharedMemory); 302 ASSERT_NE(buffer->mMemory, nullptr); 303 if (portMode == PortMode::DYNAMIC_ANW_BUFFER) { 304 android::VideoNativeMetadata* metaData = 305 static_cast<android::VideoNativeMetadata*>( 306 static_cast<void*>(buffer->mMemory->getPointer())); 307 metaData->nFenceFd = -1; 308 buffer->slot = -1; 309 } 310 omxNode->useBuffer( 311 portIndex, buffer->omxBuffer, 312 [&status, &buffer](android::hardware::media::omx::V1_0::Status _s, 313 uint32_t id) { 314 status = _s; 315 buffer->id = id; 316 }); 317 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 318 } else if (portMode == PortMode::PRESET_ANW_BUFFER) { 319 OMX_PARAM_PORTDEFINITIONTYPE portDef; 320 status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex, 321 &portDef); 322 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 323 int32_t nStride; 324 buffer->owner = client; 325 buffer->omxBuffer.type = CodecBuffer::Type::ANW_BUFFER; 326 ASSERT_NO_FATAL_FAILURE(allocateGraphicBuffers( 327 omxNode, portIndex, buffer, portDef.format.video.nFrameWidth, 328 portDef.format.video.nFrameHeight, &nStride, 329 portDef.format.video.eColorFormat)); 330 omxNode->useBuffer( 331 portIndex, buffer->omxBuffer, 332 [&status, &buffer](android::hardware::media::omx::V1_0::Status _s, 333 uint32_t id) { 334 status = _s; 335 buffer->id = id; 336 }); 337 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 338 } 339 } 340 341 // allocate buffers needed on a component port 342 void allocatePortBuffers(sp<IOmxNode> omxNode, 343 android::Vector<BufferInfo>* buffArray, 344 OMX_U32 portIndex, PortMode portMode, bool allocGrap) { 345 android::hardware::media::omx::V1_0::Status status; 346 OMX_PARAM_PORTDEFINITIONTYPE portDef; 347 348 buffArray->clear(); 349 350 status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex, 351 &portDef); 352 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK); 353 354 for (size_t i = 0; i < portDef.nBufferCountActual; i++) { 355 BufferInfo buffer; 356 ASSERT_NO_FATAL_FAILURE(allocateBuffer(omxNode, &buffer, portIndex, 357 portDef.nBufferSize, portMode)); 358 if (allocGrap && portMode == PortMode::DYNAMIC_ANW_BUFFER) { 359 int32_t nStride; 360 ASSERT_NO_FATAL_FAILURE(allocateGraphicBuffers( 361 omxNode, portIndex, &buffer, portDef.format.video.nFrameWidth, 362 portDef.format.video.nFrameHeight, &nStride, 363 portDef.format.video.eColorFormat)); 364 } 365 buffArray->push(buffer); 366 } 367 } 368 369 // State Transition : Loaded -> Idle 370 // Note: This function does not make any background checks for this transition. 371 // The callee holds the reponsibility to ensure the legality of the transition. 372 void changeStateLoadedtoIdle(sp<IOmxNode> omxNode, sp<CodecObserver> observer, 373 android::Vector<BufferInfo>* iBuffer, 374 android::Vector<BufferInfo>* oBuffer, 375 OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput, 376 PortMode* portMode, bool allocGrap) { 377 android::hardware::media::omx::V1_0::Status status; 378 Message msg; 379 PortMode defaultPortMode[2], *pm; 380 381 defaultPortMode[0] = PortMode::PRESET_BYTE_BUFFER; 382 defaultPortMode[1] = PortMode::PRESET_BYTE_BUFFER; 383 pm = portMode ? portMode : defaultPortMode; 384 385 // set state to idle 386 status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet), 387 OMX_StateIdle); 388 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 389 390 // Dont switch states until the ports are populated 391 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer); 392 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT); 393 394 // allocate buffers on input port 395 ASSERT_NO_FATAL_FAILURE(allocatePortBuffers( 396 omxNode, iBuffer, kPortIndexInput, pm[0], allocGrap)); 397 398 // Dont switch states until the ports are populated 399 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer); 400 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT); 401 402 // allocate buffers on output port 403 ASSERT_NO_FATAL_FAILURE(allocatePortBuffers( 404 omxNode, oBuffer, kPortIndexOutput, pm[1], allocGrap)); 405 406 // As the ports are populated, check if the state transition is complete 407 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer); 408 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 409 ASSERT_EQ(msg.type, Message::Type::EVENT); 410 ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete); 411 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet); 412 ASSERT_EQ(msg.data.eventData.data2, OMX_StateIdle); 413 414 return; 415 } 416 417 // State Transition : Idle -> Loaded 418 // Note: This function does not make any background checks for this transition. 419 // The callee holds the reponsibility to ensure the legality of the transition. 420 void changeStateIdletoLoaded(sp<IOmxNode> omxNode, sp<CodecObserver> observer, 421 android::Vector<BufferInfo>* iBuffer, 422 android::Vector<BufferInfo>* oBuffer, 423 OMX_U32 kPortIndexInput, 424 OMX_U32 kPortIndexOutput) { 425 android::hardware::media::omx::V1_0::Status status; 426 Message msg; 427 428 // set state to Loaded 429 status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet), 430 OMX_StateLoaded); 431 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 432 433 // dont change state until all buffers are freed 434 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer); 435 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT); 436 437 for (size_t i = 0; i < iBuffer->size(); ++i) { 438 status = omxNode->freeBuffer(kPortIndexInput, (*iBuffer)[i].id); 439 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 440 } 441 442 // dont change state until all buffers are freed 443 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer); 444 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::TIMED_OUT); 445 446 for (size_t i = 0; i < oBuffer->size(); ++i) { 447 status = omxNode->freeBuffer(kPortIndexOutput, (*oBuffer)[i].id); 448 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 449 } 450 451 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer); 452 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 453 ASSERT_EQ(msg.type, Message::Type::EVENT); 454 ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete); 455 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet); 456 ASSERT_EQ(msg.data.eventData.data2, OMX_StateLoaded); 457 458 return; 459 } 460 461 // State Transition : Idle -> Execute 462 // Note: This function does not make any background checks for this transition. 463 // The callee holds the reponsibility to ensure the legality of the transition. 464 void changeStateIdletoExecute(sp<IOmxNode> omxNode, 465 sp<CodecObserver> observer) { 466 android::hardware::media::omx::V1_0::Status status; 467 Message msg; 468 469 // set state to execute 470 status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet), 471 OMX_StateExecuting); 472 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 473 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT); 474 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 475 ASSERT_EQ(msg.type, Message::Type::EVENT); 476 ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete); 477 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet); 478 ASSERT_EQ(msg.data.eventData.data2, OMX_StateExecuting); 479 480 return; 481 } 482 483 // State Transition : Execute -> Idle 484 // Note: This function does not make any background checks for this transition. 485 // The callee holds the reponsibility to ensure the legality of the transition. 486 void changeStateExecutetoIdle(sp<IOmxNode> omxNode, sp<CodecObserver> observer, 487 android::Vector<BufferInfo>* iBuffer, 488 android::Vector<BufferInfo>* oBuffer) { 489 android::hardware::media::omx::V1_0::Status status; 490 Message msg; 491 492 // set state to Idle 493 status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet), 494 OMX_StateIdle); 495 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 496 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer); 497 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 498 ASSERT_EQ(msg.type, Message::Type::EVENT); 499 ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete); 500 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet); 501 ASSERT_EQ(msg.data.eventData.data2, OMX_StateIdle); 502 503 // test if client got all its buffers back 504 for (size_t i = 0; i < oBuffer->size(); ++i) { 505 EXPECT_EQ((*oBuffer)[i].owner, client); 506 } 507 for (size_t i = 0; i < iBuffer->size(); ++i) { 508 EXPECT_EQ((*iBuffer)[i].owner, client); 509 } 510 } 511 512 // get empty buffer index 513 size_t getEmptyBufferID(android::Vector<BufferInfo>* buffArray) { 514 android::Vector<BufferInfo>::iterator it = buffArray->begin(); 515 while (it != buffArray->end()) { 516 if (it->owner == client) { 517 // This block of code ensures that all buffers allocated at init 518 // time are utilized 519 BufferInfo backup = *it; 520 buffArray->erase(it); 521 buffArray->push_back(backup); 522 return buffArray->size() - 1; 523 } 524 it++; 525 } 526 return buffArray->size(); 527 } 528 529 // dispatch buffer to output port 530 void dispatchOutputBuffer(sp<IOmxNode> omxNode, 531 android::Vector<BufferInfo>* buffArray, 532 size_t bufferIndex, PortMode portMode) { 533 android::hardware::media::omx::V1_0::Status status; 534 CodecBuffer t; 535 native_handle_t* fenceNh = native_handle_create(0, 0); 536 ASSERT_NE(fenceNh, nullptr); 537 switch (portMode) { 538 case PortMode::DYNAMIC_ANW_BUFFER: 539 t = (*buffArray)[bufferIndex].omxBuffer; 540 t.type = CodecBuffer::Type::ANW_BUFFER; 541 status = 542 omxNode->fillBuffer((*buffArray)[bufferIndex].id, t, fenceNh); 543 break; 544 case PortMode::PRESET_ANW_BUFFER: 545 case PortMode::PRESET_SECURE_BUFFER: 546 case PortMode::PRESET_BYTE_BUFFER: 547 t.sharedMemory = android::hardware::hidl_memory(); 548 t.nativeHandle = android::hardware::hidl_handle(); 549 t.type = CodecBuffer::Type::PRESET; 550 t.attr.preset.rangeOffset = 0; 551 t.attr.preset.rangeLength = 0; 552 status = 553 omxNode->fillBuffer((*buffArray)[bufferIndex].id, t, fenceNh); 554 break; 555 default: 556 status = Status::NAME_NOT_FOUND; 557 } 558 native_handle_close(fenceNh); 559 native_handle_delete(fenceNh); 560 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 561 buffArray->editItemAt(bufferIndex).owner = component; 562 } 563 564 // dispatch buffer to input port 565 void dispatchInputBuffer(sp<IOmxNode> omxNode, 566 android::Vector<BufferInfo>* buffArray, 567 size_t bufferIndex, int bytesCount, uint32_t flags, 568 uint64_t timestamp, PortMode portMode) { 569 android::hardware::media::omx::V1_0::Status status; 570 CodecBuffer t; 571 native_handle_t* fenceNh = native_handle_create(0, 0); 572 ASSERT_NE(fenceNh, nullptr); 573 switch (portMode) { 574 case PortMode::PRESET_SECURE_BUFFER: 575 case PortMode::PRESET_BYTE_BUFFER: 576 t.sharedMemory = android::hardware::hidl_memory(); 577 t.nativeHandle = android::hardware::hidl_handle(); 578 t.type = CodecBuffer::Type::PRESET; 579 t.attr.preset.rangeOffset = 0; 580 t.attr.preset.rangeLength = bytesCount; 581 status = omxNode->emptyBuffer((*buffArray)[bufferIndex].id, t, 582 flags, timestamp, fenceNh); 583 break; 584 default: 585 status = Status::NAME_NOT_FOUND; 586 } 587 native_handle_close(fenceNh); 588 native_handle_delete(fenceNh); 589 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 590 buffArray->editItemAt(bufferIndex).owner = component; 591 } 592 593 // Flush input and output ports 594 void flushPorts(sp<IOmxNode> omxNode, sp<CodecObserver> observer, 595 android::Vector<BufferInfo>* iBuffer, 596 android::Vector<BufferInfo>* oBuffer, OMX_U32 kPortIndexInput, 597 OMX_U32 kPortIndexOutput, int64_t timeoutUs) { 598 android::hardware::media::omx::V1_0::Status status; 599 Message msg; 600 601 // Flush input port 602 status = omxNode->sendCommand(toRawCommandType(OMX_CommandFlush), 603 kPortIndexInput); 604 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 605 status = observer->dequeueMessage(&msg, timeoutUs, iBuffer, oBuffer); 606 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 607 ASSERT_EQ(msg.type, Message::Type::EVENT); 608 ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete); 609 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandFlush); 610 ASSERT_EQ(msg.data.eventData.data2, kPortIndexInput); 611 // test if client got all its buffers back 612 for (size_t i = 0; i < iBuffer->size(); ++i) { 613 EXPECT_EQ((*iBuffer)[i].owner, client); 614 } 615 616 // Flush output port 617 status = omxNode->sendCommand(toRawCommandType(OMX_CommandFlush), 618 kPortIndexOutput); 619 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 620 status = observer->dequeueMessage(&msg, timeoutUs, iBuffer, oBuffer); 621 ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK); 622 ASSERT_EQ(msg.type, Message::Type::EVENT); 623 ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete); 624 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandFlush); 625 ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput); 626 // test if client got all its buffers back 627 for (size_t i = 0; i < oBuffer->size(); ++i) { 628 EXPECT_EQ((*oBuffer)[i].owner, client); 629 } 630 } 631 632 // dispatch an empty input buffer with eos flag set if requested. 633 // This call assumes that all input buffers are processed completely. 634 // feed output buffers till we receive a buffer with eos flag set 635 void testEOS(sp<IOmxNode> omxNode, sp<CodecObserver> observer, 636 android::Vector<BufferInfo>* iBuffer, 637 android::Vector<BufferInfo>* oBuffer, bool signalEOS, 638 bool& eosFlag, PortMode* portMode, portreconfig fptr, 639 OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput, void* args) { 640 android::hardware::media::omx::V1_0::Status status; 641 PortMode defaultPortMode[2], *pm; 642 643 defaultPortMode[0] = PortMode::PRESET_BYTE_BUFFER; 644 defaultPortMode[1] = PortMode::PRESET_BYTE_BUFFER; 645 pm = portMode ? portMode : defaultPortMode; 646 647 size_t i = 0; 648 if (signalEOS) { 649 if ((i = getEmptyBufferID(iBuffer)) < iBuffer->size()) { 650 // signal an empty buffer with flag set to EOS 651 ASSERT_NO_FATAL_FAILURE(dispatchInputBuffer(omxNode, iBuffer, i, 0, 652 OMX_BUFFERFLAG_EOS, 0)); 653 } else { 654 ASSERT_TRUE(false); 655 } 656 } 657 658 int timeOut = TIMEOUT_COUNTER_PE; 659 while (timeOut--) { 660 // Dispatch all client owned output buffers to recover remaining frames 661 while (1) { 662 if ((i = getEmptyBufferID(oBuffer)) < oBuffer->size()) { 663 ASSERT_NO_FATAL_FAILURE( 664 dispatchOutputBuffer(omxNode, oBuffer, i, pm[1])); 665 // if dispatch is successful, perhaps there is a latency 666 // in the component. Dont be in a haste to leave. reset timeout 667 // counter 668 timeOut = TIMEOUT_COUNTER_PE; 669 } else { 670 break; 671 } 672 } 673 674 Message msg; 675 status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_PE, iBuffer, 676 oBuffer); 677 if (status == android::hardware::media::omx::V1_0::Status::OK) { 678 if (msg.data.eventData.event == OMX_EventPortSettingsChanged) { 679 if (fptr) { 680 ASSERT_NO_FATAL_FAILURE((*fptr)( 681 omxNode, observer, iBuffer, oBuffer, kPortIndexInput, 682 kPortIndexOutput, msg, pm[1], args)); 683 } else { 684 // something unexpected happened 685 ASSERT_TRUE(false); 686 } 687 } else { 688 // something unexpected happened 689 ASSERT_TRUE(false); 690 } 691 } 692 if (eosFlag == true) break; 693 } 694 // test for flag 695 EXPECT_EQ(eosFlag, true); 696 eosFlag = false; 697 } 698