Home | History | Annotate | Download | only in common
      1 /*
      2  * Copyright 2016, 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 #define DEFAULT_TIMEOUT 100000
     37 #define TIMEOUT_COUNTER (10000000 / DEFAULT_TIMEOUT)
     38 
     39 enum bufferOwner {
     40     client,
     41     component,
     42     unknown,
     43 };
     44 
     45 /*
     46  * TODO: below definitions are borrowed from Conversion.h.
     47  * This is not the ideal way to do it. Loose these definitions once you
     48  * include Conversion.h
     49  */
     50 inline uint32_t toRawIndexType(OMX_INDEXTYPE l) {
     51     return static_cast<uint32_t>(l);
     52 }
     53 
     54 inline android::hardware::media::omx::V1_0::Status toStatus(
     55     android::status_t l) {
     56     return static_cast<android::hardware::media::omx::V1_0::Status>(l);
     57 }
     58 
     59 inline hidl_vec<uint8_t> inHidlBytes(void const* l, size_t size) {
     60     hidl_vec<uint8_t> t;
     61     t.setToExternal(static_cast<uint8_t*>(const_cast<void*>(l)), size, false);
     62     return t;
     63 }
     64 
     65 inline uint32_t toRawCommandType(OMX_COMMANDTYPE l) {
     66     return static_cast<uint32_t>(l);
     67 }
     68 
     69 /*
     70  * struct definitions
     71  */
     72 struct BufferInfo {
     73     uint32_t id;
     74     bufferOwner owner;
     75     android::hardware::media::omx::V1_0::CodecBuffer omxBuffer;
     76     ::android::sp<IMemory> mMemory;
     77     int32_t slot;
     78 };
     79 
     80 struct FrameData {
     81     int bytesCount;
     82     uint32_t flags;
     83     uint32_t timestamp;
     84 };
     85 
     86 /*
     87  * Handle Callback functions EmptythisBuffer(), FillthisBuffer(),
     88  * EventHandler()
     89  */
     90 struct CodecObserver : public IOmxObserver {
     91    public:
     92     CodecObserver(std::function<void(Message, const BufferInfo*)> fn)
     93         : callBack(fn) {}
     94     Return<void> onMessages(const hidl_vec<Message>& messages) override {
     95         android::Mutex::Autolock autoLock(msgLock);
     96         for (hidl_vec<Message>::const_iterator it = messages.begin();
     97              it != messages.end(); ++it) {
     98             msgQueue.push_back(*it);
     99         }
    100         msgCondition.signal();
    101         return Void();
    102     }
    103     android::hardware::media::omx::V1_0::Status dequeueMessage(
    104         Message* msg, int64_t timeoutUs,
    105         android::Vector<BufferInfo>* iBuffers = nullptr,
    106         android::Vector<BufferInfo>* oBuffers = nullptr) {
    107         int64_t finishBy = android::ALooper::GetNowUs() + timeoutUs;
    108         for (;;) {
    109             android::Mutex::Autolock autoLock(msgLock);
    110             android::List<Message>::iterator it = msgQueue.begin();
    111             while (it != msgQueue.end()) {
    112                 if (it->type ==
    113                     android::hardware::media::omx::V1_0::Message::Type::EVENT) {
    114                     *msg = *it;
    115                     msgQueue.erase(it);
    116                     return ::android::hardware::media::omx::V1_0::Status::OK;
    117                 } else if (it->type == android::hardware::media::omx::V1_0::
    118                                            Message::Type::FILL_BUFFER_DONE) {
    119                     if (oBuffers) {
    120                         size_t i;
    121                         for (i = 0; i < oBuffers->size(); ++i) {
    122                             if ((*oBuffers)[i].id ==
    123                                 it->data.bufferData.buffer) {
    124                                 if (callBack) callBack(*it, &(*oBuffers)[i]);
    125                                 oBuffers->editItemAt(i).owner = client;
    126                                 msgQueue.erase(it);
    127                                 break;
    128                             }
    129                         }
    130                         EXPECT_LE(i, oBuffers->size());
    131                     }
    132                 } else if (it->type == android::hardware::media::omx::V1_0::
    133                                            Message::Type::EMPTY_BUFFER_DONE) {
    134                     if (iBuffers) {
    135                         size_t i;
    136                         for (i = 0; i < iBuffers->size(); ++i) {
    137                             if ((*iBuffers)[i].id ==
    138                                 it->data.bufferData.buffer) {
    139                                 if (callBack) callBack(*it, &(*iBuffers)[i]);
    140                                 iBuffers->editItemAt(i).owner = client;
    141                                 msgQueue.erase(it);
    142                                 break;
    143                             }
    144                         }
    145                         EXPECT_LE(i, iBuffers->size());
    146                     }
    147                 }
    148                 ++it;
    149             }
    150             if (finishBy - android::ALooper::GetNowUs() < 0)
    151                 return toStatus(android::TIMED_OUT);
    152             android::status_t err =
    153                 (timeoutUs < 0)
    154                     ? msgCondition.wait(msgLock)
    155                     : msgCondition.waitRelative(
    156                           msgLock,
    157                           (finishBy - android::ALooper::GetNowUs()) * 1000ll);
    158             if (err == android::TIMED_OUT) return toStatus(err);
    159         }
    160     }
    161 
    162     android::List<Message> msgQueue;
    163     android::Mutex msgLock;
    164     android::Condition msgCondition;
    165     std::function<void(Message, const BufferInfo*)> callBack;
    166 };
    167 
    168 /*
    169  * Useful Wrapper utilities
    170  */
    171 template <class T>
    172 void InitOMXParams(T* params) {
    173     params->nSize = sizeof(T);
    174     params->nVersion.s.nVersionMajor = 1;
    175     params->nVersion.s.nVersionMinor = 0;
    176     params->nVersion.s.nRevision = 0;
    177     params->nVersion.s.nStep = 0;
    178 }
    179 
    180 template <class T>
    181 Return<android::hardware::media::omx::V1_0::Status> getParam(
    182     sp<IOmxNode> omxNode, OMX_INDEXTYPE omxIdx, T* params) {
    183     android::hardware::media::omx::V1_0::Status status;
    184     InitOMXParams(params);
    185     omxNode->getParameter(
    186         toRawIndexType(omxIdx), inHidlBytes(params, sizeof(*params)),
    187         [&status, &params](android::hardware::media::omx::V1_0::Status _s,
    188                            hidl_vec<uint8_t> const& outParams) {
    189             status = _s;
    190             std::copy(outParams.data(), outParams.data() + outParams.size(),
    191                       static_cast<uint8_t*>(static_cast<void*>(params)));
    192         });
    193     return status;
    194 }
    195 
    196 template <class T>
    197 Return<android::hardware::media::omx::V1_0::Status> setParam(
    198     sp<IOmxNode> omxNode, OMX_INDEXTYPE omxIdx, T* params) {
    199     InitOMXParams(params);
    200     return omxNode->setParameter(toRawIndexType(omxIdx),
    201                                  inHidlBytes(params, sizeof(*params)));
    202 }
    203 
    204 template <class T>
    205 Return<android::hardware::media::omx::V1_0::Status> getPortParam(
    206     sp<IOmxNode> omxNode, OMX_INDEXTYPE omxIdx, OMX_U32 nPortIndex, T* params) {
    207     android::hardware::media::omx::V1_0::Status status;
    208     InitOMXParams(params);
    209     params->nPortIndex = nPortIndex;
    210     omxNode->getParameter(
    211         toRawIndexType(omxIdx), inHidlBytes(params, sizeof(*params)),
    212         [&status, &params](android::hardware::media::omx::V1_0::Status _s,
    213                            hidl_vec<uint8_t> const& outParams) {
    214             status = _s;
    215             std::copy(outParams.data(), outParams.data() + outParams.size(),
    216                       static_cast<uint8_t*>(static_cast<void*>(params)));
    217         });
    218     return status;
    219 }
    220 
    221 template <class T>
    222 Return<android::hardware::media::omx::V1_0::Status> setPortParam(
    223     sp<IOmxNode> omxNode, OMX_INDEXTYPE omxIdx, OMX_U32 nPortIndex, T* params) {
    224     InitOMXParams(params);
    225     params->nPortIndex = nPortIndex;
    226     return omxNode->setParameter(toRawIndexType(omxIdx),
    227                                  inHidlBytes(params, sizeof(*params)));
    228 }
    229 
    230 template <class T>
    231 Return<android::hardware::media::omx::V1_0::Status> getPortConfig(
    232     sp<IOmxNode> omxNode, OMX_INDEXTYPE omxIdx, OMX_U32 nPortIndex, T* params) {
    233     android::hardware::media::omx::V1_0::Status status;
    234     InitOMXParams(params);
    235     params->nPortIndex = nPortIndex;
    236     omxNode->getConfig(
    237         toRawIndexType(omxIdx), inHidlBytes(params, sizeof(*params)),
    238         [&status, &params](android::hardware::media::omx::V1_0::Status _s,
    239                            hidl_vec<uint8_t> const& outParams) {
    240             status = _s;
    241             std::copy(outParams.data(), outParams.data() + outParams.size(),
    242                       static_cast<uint8_t*>(static_cast<void*>(params)));
    243         });
    244     return status;
    245 }
    246 
    247 template <class T>
    248 Return<android::hardware::media::omx::V1_0::Status> setPortConfig(
    249     sp<IOmxNode> omxNode, OMX_INDEXTYPE omxIdx, OMX_U32 nPortIndex, T* params) {
    250     InitOMXParams(params);
    251     params->nPortIndex = nPortIndex;
    252     return omxNode->setConfig(toRawIndexType(omxIdx),
    253                               inHidlBytes(params, sizeof(*params)));
    254 }
    255 
    256 /*
    257  * common functions declarations
    258  */
    259 Return<android::hardware::media::omx::V1_0::Status> setRole(
    260     sp<IOmxNode> omxNode, const char* role);
    261 
    262 void allocatePortBuffers(sp<IOmxNode> omxNode,
    263                          android::Vector<BufferInfo>* buffArray,
    264                          OMX_U32 portIndex,
    265                          PortMode portMode = PortMode::PRESET_BYTE_BUFFER);
    266 
    267 void changeStateLoadedtoIdle(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
    268                              android::Vector<BufferInfo>* iBuffer,
    269                              android::Vector<BufferInfo>* oBuffer,
    270                              OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
    271                              PortMode* portMode = nullptr);
    272 
    273 void changeStateIdletoLoaded(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
    274                              android::Vector<BufferInfo>* iBuffer,
    275                              android::Vector<BufferInfo>* oBuffer,
    276                              OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput);
    277 
    278 void changeStateIdletoExecute(sp<IOmxNode> omxNode, sp<CodecObserver> observer);
    279 
    280 void changeStateExecutetoIdle(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
    281                               android::Vector<BufferInfo>* iBuffer,
    282                               android::Vector<BufferInfo>* oBuffer);
    283 
    284 size_t getEmptyBufferID(android::Vector<BufferInfo>* buffArray);
    285 
    286 void dispatchOutputBuffer(sp<IOmxNode> omxNode,
    287                           android::Vector<BufferInfo>* buffArray,
    288                           size_t bufferIndex,
    289                           PortMode portMode = PortMode::PRESET_BYTE_BUFFER);
    290 
    291 void dispatchInputBuffer(sp<IOmxNode> omxNode,
    292                          android::Vector<BufferInfo>* buffArray,
    293                          size_t bufferIndex, int bytesCount, uint32_t flags,
    294                          uint64_t timestamp,
    295                          PortMode portMode = PortMode::PRESET_BYTE_BUFFER);
    296 
    297 void flushPorts(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
    298                 android::Vector<BufferInfo>* iBuffer,
    299                 android::Vector<BufferInfo>* oBuffer, OMX_U32 kPortIndexInput,
    300                 OMX_U32 kPortIndexOutput, int64_t timeoutUs = DEFAULT_TIMEOUT);
    301 
    302 void testEOS(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
    303              android::Vector<BufferInfo>* iBuffer,
    304              android::Vector<BufferInfo>* oBuffer, bool signalEOS,
    305              bool& eosFlag, PortMode* portMode = nullptr);
    306 
    307 #endif  // MEDIA_HIDL_TEST_COMMON_H
    308