Home | History | Annotate | Download | only in common
      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, &params);
     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