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, ¶ms](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, ¶ms](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, ¶ms](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