Home | History | Annotate | Download | only in common
      1 /*
      2  * Copyright 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 #ifndef MEDIA_HIDL_TEST_COMMON_H
     18 #define MEDIA_HIDL_TEST_COMMON_H
     19 
     20 #ifdef __LP64__
     21 #define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
     22 #endif
     23 
     24 #include <media/stagefright/foundation/ALooper.h>
     25 #include <utils/Condition.h>
     26 #include <utils/List.h>
     27 #include <utils/Mutex.h>
     28 
     29 #include <media/openmax/OMX_Index.h>
     30 #include <media/openmax/OMX_Core.h>
     31 #include <media/openmax/OMX_Component.h>
     32 #include <media/openmax/OMX_IndexExt.h>
     33 #include <media/openmax/OMX_AudioExt.h>
     34 #include <media/openmax/OMX_VideoExt.h>
     35 
     36 /* TIME OUTS (Wait time in dequeueMessage()) */
     37 
     38 /* As component is switching states (loaded<->idle<->execute), dequeueMessage()
     39  * expects the events to be received within this duration */
     40 #define DEFAULT_TIMEOUT 100000
     41 /* Time interval between successive Input/Output enqueues */
     42 #define DEFAULT_TIMEOUT_Q 2000
     43 /* While the component is amidst a process call, asynchronous commands like
     44  * flush, change states can get delayed (at max by process call time). Instead
     45  * of waiting on DEFAULT_TIMEOUT, we give an additional leeway. */
     46 #define DEFAULT_TIMEOUT_PE 500000
     47 
     48 /* Breakout Timeout :: 5 sec*/
     49 #define TIMEOUT_COUNTER_Q (5000000 / DEFAULT_TIMEOUT_Q)
     50 #define TIMEOUT_COUNTER_PE (5000000 / DEFAULT_TIMEOUT_PE)
     51 
     52 /*
     53  * Random Index used for monkey testing while get/set parameters
     54  */
     55 #define RANDOM_INDEX 1729
     56 
     57 #define ALIGN_POWER_OF_TWO(value, n) \
     58     (((value) + ((1 << (n)) - 1)) & ~((1 << (n)) - 1))
     59 
     60 enum bufferOwner {
     61     client,
     62     component,
     63     unknown,
     64 };
     65 
     66 /*
     67  * TODO: below definitions are borrowed from Conversion.h.
     68  * This is not the ideal way to do it. Loose these definitions once you
     69  * include Conversion.h
     70  */
     71 inline uint32_t toRawIndexType(OMX_INDEXTYPE l) {
     72     return static_cast<uint32_t>(l);
     73 }
     74 
     75 inline android::hardware::media::omx::V1_0::Status toStatus(
     76     android::status_t l) {
     77     return static_cast<android::hardware::media::omx::V1_0::Status>(l);
     78 }
     79 
     80 inline hidl_vec<uint8_t> inHidlBytes(void const* l, size_t size) {
     81     hidl_vec<uint8_t> t;
     82     t.setToExternal(static_cast<uint8_t*>(const_cast<void*>(l)), size, false);
     83     return t;
     84 }
     85 
     86 inline uint32_t toRawCommandType(OMX_COMMANDTYPE l) {
     87     return static_cast<uint32_t>(l);
     88 }
     89 
     90 /*
     91  * struct definitions
     92  */
     93 struct BufferInfo {
     94     uint32_t id;
     95     bufferOwner owner;
     96     android::hardware::media::omx::V1_0::CodecBuffer omxBuffer;
     97     ::android::sp<IMemory> mMemory;
     98     int32_t slot;
     99 };
    100 
    101 struct FrameData {
    102     int bytesCount;
    103     uint32_t flags;
    104     uint32_t timestamp;
    105 };
    106 
    107 /*
    108  * Handle Callback functions EmptythisBuffer(), FillthisBuffer(),
    109  * EventHandler()
    110  */
    111 struct CodecObserver : public IOmxObserver {
    112    public:
    113     CodecObserver(std::function<void(Message, const BufferInfo*)> fn)
    114         : callBack(fn) {}
    115     Return<void> onMessages(const hidl_vec<Message>& messages) override {
    116         android::Mutex::Autolock autoLock(msgLock);
    117         for (hidl_vec<Message>::const_iterator it = messages.begin();
    118              it != messages.end(); ++it) {
    119             msgQueue.push_back(*it);
    120         }
    121         msgCondition.signal();
    122         return Void();
    123     }
    124     android::hardware::media::omx::V1_0::Status dequeueMessage(
    125         Message* msg, int64_t timeoutUs,
    126         android::Vector<BufferInfo>* iBuffers = nullptr,
    127         android::Vector<BufferInfo>* oBuffers = nullptr) {
    128         int64_t finishBy = android::ALooper::GetNowUs() + timeoutUs;
    129         for (;;) {
    130             android::Mutex::Autolock autoLock(msgLock);
    131             android::List<Message>::iterator it = msgQueue.begin();
    132             while (it != msgQueue.end()) {
    133                 if (it->type ==
    134                     android::hardware::media::omx::V1_0::Message::Type::EVENT) {
    135                     *msg = *it;
    136                     if (callBack) callBack(*it, nullptr);
    137                     it = msgQueue.erase(it);
    138                     // OMX_EventBufferFlag event is sent when the component has
    139                     // processed a buffer with its EOS flag set. This event is
    140                     // not sent by soft omx components. Vendor components can
    141                     // send this. From IOMX point of view, we will ignore this
    142                     // event.
    143                     if (msg->data.eventData.event == OMX_EventBufferFlag)
    144                         continue;
    145                     return ::android::hardware::media::omx::V1_0::Status::OK;
    146                 } else if (it->type == android::hardware::media::omx::V1_0::
    147                                            Message::Type::FILL_BUFFER_DONE) {
    148                     if (oBuffers) {
    149                         size_t i;
    150                         for (i = 0; i < oBuffers->size(); ++i) {
    151                             if ((*oBuffers)[i].id ==
    152                                 it->data.bufferData.buffer) {
    153                                 if (callBack) callBack(*it, &(*oBuffers)[i]);
    154                                 oBuffers->editItemAt(i).owner = client;
    155                                 it = msgQueue.erase(it);
    156                                 break;
    157                             }
    158                         }
    159                         EXPECT_LE(i, oBuffers->size());
    160                     }
    161                 } else if (it->type == android::hardware::media::omx::V1_0::
    162                                            Message::Type::EMPTY_BUFFER_DONE) {
    163                     if (iBuffers) {
    164                         size_t i;
    165                         for (i = 0; i < iBuffers->size(); ++i) {
    166                             if ((*iBuffers)[i].id ==
    167                                 it->data.bufferData.buffer) {
    168                                 if (callBack) callBack(*it, &(*iBuffers)[i]);
    169                                 iBuffers->editItemAt(i).owner = client;
    170                                 it = msgQueue.erase(it);
    171                                 break;
    172                             }
    173                         }
    174                         EXPECT_LE(i, iBuffers->size());
    175                     }
    176                 } else {
    177                     EXPECT_TRUE(false) << "Received unexpected message";
    178                     ++it;
    179                 }
    180             }
    181             int64_t delayUs = finishBy - android::ALooper::GetNowUs();
    182             if (delayUs < 0) return toStatus(android::TIMED_OUT);
    183             (timeoutUs < 0)
    184                 ? msgCondition.wait(msgLock)
    185                 : msgCondition.waitRelative(msgLock, delayUs * 1000ll);
    186         }
    187     }
    188 
    189     android::List<Message> msgQueue;
    190     android::Mutex msgLock;
    191     android::Condition msgCondition;
    192     std::function<void(Message, const BufferInfo*)> callBack;
    193 };
    194 
    195 /*
    196  * Useful Wrapper utilities
    197  */
    198 template <class T>
    199 void InitOMXParams(T* params) {
    200     params->nSize = sizeof(T);
    201     params->nVersion.s.nVersionMajor = 1;
    202     params->nVersion.s.nVersionMinor = 0;
    203     params->nVersion.s.nRevision = 0;
    204     params->nVersion.s.nStep = 0;
    205 }
    206 
    207 template <class T>
    208 Return<android::hardware::media::omx::V1_0::Status> getParam(
    209     sp<IOmxNode> omxNode, OMX_INDEXTYPE omxIdx, T* params) {
    210     android::hardware::media::omx::V1_0::Status status;
    211     InitOMXParams(params);
    212     omxNode->getParameter(
    213         toRawIndexType(omxIdx), inHidlBytes(params, sizeof(*params)),
    214         [&status, &params](android::hardware::media::omx::V1_0::Status _s,
    215                            hidl_vec<uint8_t> const& outParams) {
    216             status = _s;
    217             std::copy(outParams.data(), outParams.data() + outParams.size(),
    218                       static_cast<uint8_t*>(static_cast<void*>(params)));
    219         });
    220     return status;
    221 }
    222 
    223 template <class T>
    224 Return<android::hardware::media::omx::V1_0::Status> setParam(
    225     sp<IOmxNode> omxNode, OMX_INDEXTYPE omxIdx, T* params) {
    226     InitOMXParams(params);
    227     return omxNode->setParameter(toRawIndexType(omxIdx),
    228                                  inHidlBytes(params, sizeof(*params)));
    229 }
    230 
    231 template <class T>
    232 Return<android::hardware::media::omx::V1_0::Status> getPortParam(
    233     sp<IOmxNode> omxNode, OMX_INDEXTYPE omxIdx, OMX_U32 nPortIndex, T* params) {
    234     android::hardware::media::omx::V1_0::Status status;
    235     InitOMXParams(params);
    236     params->nPortIndex = nPortIndex;
    237     omxNode->getParameter(
    238         toRawIndexType(omxIdx), inHidlBytes(params, sizeof(*params)),
    239         [&status, &params](android::hardware::media::omx::V1_0::Status _s,
    240                            hidl_vec<uint8_t> const& outParams) {
    241             status = _s;
    242             std::copy(outParams.data(), outParams.data() + outParams.size(),
    243                       static_cast<uint8_t*>(static_cast<void*>(params)));
    244         });
    245     return status;
    246 }
    247 
    248 template <class T>
    249 Return<android::hardware::media::omx::V1_0::Status> setPortParam(
    250     sp<IOmxNode> omxNode, OMX_INDEXTYPE omxIdx, OMX_U32 nPortIndex, T* params) {
    251     InitOMXParams(params);
    252     params->nPortIndex = nPortIndex;
    253     return omxNode->setParameter(toRawIndexType(omxIdx),
    254                                  inHidlBytes(params, sizeof(*params)));
    255 }
    256 
    257 template <class T>
    258 Return<android::hardware::media::omx::V1_0::Status> getPortConfig(
    259     sp<IOmxNode> omxNode, OMX_INDEXTYPE omxIdx, OMX_U32 nPortIndex, T* params) {
    260     android::hardware::media::omx::V1_0::Status status;
    261     InitOMXParams(params);
    262     params->nPortIndex = nPortIndex;
    263     omxNode->getConfig(
    264         toRawIndexType(omxIdx), inHidlBytes(params, sizeof(*params)),
    265         [&status, &params](android::hardware::media::omx::V1_0::Status _s,
    266                            hidl_vec<uint8_t> const& outParams) {
    267             status = _s;
    268             std::copy(outParams.data(), outParams.data() + outParams.size(),
    269                       static_cast<uint8_t*>(static_cast<void*>(params)));
    270         });
    271     return status;
    272 }
    273 
    274 template <class T>
    275 Return<android::hardware::media::omx::V1_0::Status> setPortConfig(
    276     sp<IOmxNode> omxNode, OMX_INDEXTYPE omxIdx, OMX_U32 nPortIndex, T* params) {
    277     InitOMXParams(params);
    278     params->nPortIndex = nPortIndex;
    279     return omxNode->setConfig(toRawIndexType(omxIdx),
    280                               inHidlBytes(params, sizeof(*params)));
    281 }
    282 
    283 /*
    284  * common functions declarations
    285  */
    286 Return<android::hardware::media::omx::V1_0::Status> setRole(
    287     sp<IOmxNode> omxNode, const char* role);
    288 
    289 Return<android::hardware::media::omx::V1_0::Status> setPortBufferSize(
    290     sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_U32 size);
    291 
    292 Return<android::hardware::media::omx::V1_0::Status> setVideoPortFormat(
    293     sp<IOmxNode> omxNode, OMX_U32 portIndex,
    294     OMX_VIDEO_CODINGTYPE eCompressionFormat, OMX_COLOR_FORMATTYPE eColorFormat,
    295     OMX_U32 xFramerate);
    296 
    297 Return<android::hardware::media::omx::V1_0::Status> setAudioPortFormat(
    298     sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE eEncoding);
    299 
    300 void allocateBuffer(sp<IOmxNode> omxNode, BufferInfo* buffer, OMX_U32 portIndex,
    301                     OMX_U32 nBufferSize, PortMode portMode);
    302 
    303 void allocatePortBuffers(sp<IOmxNode> omxNode,
    304                          android::Vector<BufferInfo>* buffArray,
    305                          OMX_U32 portIndex,
    306                          PortMode portMode = PortMode::PRESET_BYTE_BUFFER,
    307                          bool allocGrap = false);
    308 
    309 void changeStateLoadedtoIdle(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
    310                              android::Vector<BufferInfo>* iBuffer,
    311                              android::Vector<BufferInfo>* oBuffer,
    312                              OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
    313                              PortMode* portMode = nullptr,
    314                              bool allocGrap = false);
    315 
    316 void changeStateIdletoLoaded(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
    317                              android::Vector<BufferInfo>* iBuffer,
    318                              android::Vector<BufferInfo>* oBuffer,
    319                              OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput);
    320 
    321 void changeStateIdletoExecute(sp<IOmxNode> omxNode, sp<CodecObserver> observer);
    322 
    323 void changeStateExecutetoIdle(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
    324                               android::Vector<BufferInfo>* iBuffer,
    325                               android::Vector<BufferInfo>* oBuffer);
    326 
    327 size_t getEmptyBufferID(android::Vector<BufferInfo>* buffArray);
    328 
    329 void dispatchOutputBuffer(sp<IOmxNode> omxNode,
    330                           android::Vector<BufferInfo>* buffArray,
    331                           size_t bufferIndex,
    332                           PortMode portMode = PortMode::PRESET_BYTE_BUFFER);
    333 
    334 void dispatchInputBuffer(sp<IOmxNode> omxNode,
    335                          android::Vector<BufferInfo>* buffArray,
    336                          size_t bufferIndex, int bytesCount, uint32_t flags,
    337                          uint64_t timestamp,
    338                          PortMode portMode = PortMode::PRESET_BYTE_BUFFER);
    339 
    340 void flushPorts(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
    341                 android::Vector<BufferInfo>* iBuffer,
    342                 android::Vector<BufferInfo>* oBuffer, OMX_U32 kPortIndexInput,
    343                 OMX_U32 kPortIndexOutput,
    344                 int64_t timeoutUs = DEFAULT_TIMEOUT_PE);
    345 
    346 typedef void (*portreconfig)(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
    347                              android::Vector<BufferInfo>* iBuffer,
    348                              android::Vector<BufferInfo>* oBuffer,
    349                              OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
    350                              Message msg, PortMode oPortMode, void* args);
    351 void testEOS(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
    352              android::Vector<BufferInfo>* iBuffer,
    353              android::Vector<BufferInfo>* oBuffer, bool signalEOS,
    354              bool& eosFlag, PortMode* portMode = nullptr,
    355              portreconfig fptr = nullptr, OMX_U32 kPortIndexInput = 0,
    356              OMX_U32 kPortIndexOutput = 1, void* args = nullptr);
    357 
    358 #endif  // MEDIA_HIDL_TEST_COMMON_H
    359