OSDN Git Service

94a0194db9980ef584820ef472853f15fa6f2550
[android-x86/hardware-interfaces.git] / media / omx / 1.0 / vts / functional / common / media_hidl_test_common.h
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 /* 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         android::Mutex::Autolock autoLock(msgLock);
130         for (;;) {
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                     it = msgQueue.erase(it);
137                     // OMX_EventBufferFlag event is sent when the component has
138                     // processed a buffer with its EOS flag set. This event is
139                     // not sent by soft omx components. Vendor components can
140                     // send this. From IOMX point of view, we will ignore this
141                     // event.
142                     if (msg->data.eventData.event == OMX_EventBufferFlag)
143                         continue;
144                     return ::android::hardware::media::omx::V1_0::Status::OK;
145                 } else if (it->type == android::hardware::media::omx::V1_0::
146                                            Message::Type::FILL_BUFFER_DONE) {
147                     if (oBuffers) {
148                         size_t i;
149                         for (i = 0; i < oBuffers->size(); ++i) {
150                             if ((*oBuffers)[i].id ==
151                                 it->data.bufferData.buffer) {
152                                 if (callBack) callBack(*it, &(*oBuffers)[i]);
153                                 oBuffers->editItemAt(i).owner = client;
154                                 it = msgQueue.erase(it);
155                                 break;
156                             }
157                         }
158                         EXPECT_LE(i, oBuffers->size());
159                     }
160                 } else if (it->type == android::hardware::media::omx::V1_0::
161                                            Message::Type::EMPTY_BUFFER_DONE) {
162                     if (iBuffers) {
163                         size_t i;
164                         for (i = 0; i < iBuffers->size(); ++i) {
165                             if ((*iBuffers)[i].id ==
166                                 it->data.bufferData.buffer) {
167                                 if (callBack) callBack(*it, &(*iBuffers)[i]);
168                                 iBuffers->editItemAt(i).owner = client;
169                                 it = msgQueue.erase(it);
170                                 break;
171                             }
172                         }
173                         EXPECT_LE(i, iBuffers->size());
174                     }
175                 } else {
176                     EXPECT_TRUE(false) << "Received unexpected message";
177                     ++it;
178                 }
179             }
180             int64_t delayUs = finishBy - android::ALooper::GetNowUs();
181             if (delayUs < 0) return toStatus(android::TIMED_OUT);
182             (timeoutUs < 0)
183                 ? msgCondition.wait(msgLock)
184                 : msgCondition.waitRelative(msgLock, delayUs * 1000ll);
185         }
186     }
187
188     android::List<Message> msgQueue;
189     android::Mutex msgLock;
190     android::Condition msgCondition;
191     std::function<void(Message, const BufferInfo*)> callBack;
192 };
193
194 /*
195  * Useful Wrapper utilities
196  */
197 template <class T>
198 void InitOMXParams(T* params) {
199     params->nSize = sizeof(T);
200     params->nVersion.s.nVersionMajor = 1;
201     params->nVersion.s.nVersionMinor = 0;
202     params->nVersion.s.nRevision = 0;
203     params->nVersion.s.nStep = 0;
204 }
205
206 template <class T>
207 Return<android::hardware::media::omx::V1_0::Status> getParam(
208     sp<IOmxNode> omxNode, OMX_INDEXTYPE omxIdx, T* params) {
209     android::hardware::media::omx::V1_0::Status status;
210     InitOMXParams(params);
211     omxNode->getParameter(
212         toRawIndexType(omxIdx), inHidlBytes(params, sizeof(*params)),
213         [&status, &params](android::hardware::media::omx::V1_0::Status _s,
214                            hidl_vec<uint8_t> const& outParams) {
215             status = _s;
216             std::copy(outParams.data(), outParams.data() + outParams.size(),
217                       static_cast<uint8_t*>(static_cast<void*>(params)));
218         });
219     return status;
220 }
221
222 template <class T>
223 Return<android::hardware::media::omx::V1_0::Status> setParam(
224     sp<IOmxNode> omxNode, OMX_INDEXTYPE omxIdx, T* params) {
225     InitOMXParams(params);
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> getPortParam(
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->getParameter(
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> setPortParam(
249     sp<IOmxNode> omxNode, OMX_INDEXTYPE omxIdx, OMX_U32 nPortIndex, T* params) {
250     InitOMXParams(params);
251     params->nPortIndex = nPortIndex;
252     return omxNode->setParameter(toRawIndexType(omxIdx),
253                                  inHidlBytes(params, sizeof(*params)));
254 }
255
256 template <class T>
257 Return<android::hardware::media::omx::V1_0::Status> getPortConfig(
258     sp<IOmxNode> omxNode, OMX_INDEXTYPE omxIdx, OMX_U32 nPortIndex, T* params) {
259     android::hardware::media::omx::V1_0::Status status;
260     InitOMXParams(params);
261     params->nPortIndex = nPortIndex;
262     omxNode->getConfig(
263         toRawIndexType(omxIdx), inHidlBytes(params, sizeof(*params)),
264         [&status, &params](android::hardware::media::omx::V1_0::Status _s,
265                            hidl_vec<uint8_t> const& outParams) {
266             status = _s;
267             std::copy(outParams.data(), outParams.data() + outParams.size(),
268                       static_cast<uint8_t*>(static_cast<void*>(params)));
269         });
270     return status;
271 }
272
273 template <class T>
274 Return<android::hardware::media::omx::V1_0::Status> setPortConfig(
275     sp<IOmxNode> omxNode, OMX_INDEXTYPE omxIdx, OMX_U32 nPortIndex, T* params) {
276     InitOMXParams(params);
277     params->nPortIndex = nPortIndex;
278     return omxNode->setConfig(toRawIndexType(omxIdx),
279                               inHidlBytes(params, sizeof(*params)));
280 }
281
282 /*
283  * common functions declarations
284  */
285 Return<android::hardware::media::omx::V1_0::Status> setRole(
286     sp<IOmxNode> omxNode, const char* role);
287
288 Return<android::hardware::media::omx::V1_0::Status> setPortBufferSize(
289     sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_U32 size);
290
291 Return<android::hardware::media::omx::V1_0::Status> setVideoPortFormat(
292     sp<IOmxNode> omxNode, OMX_U32 portIndex,
293     OMX_VIDEO_CODINGTYPE eCompressionFormat, OMX_COLOR_FORMATTYPE eColorFormat,
294     OMX_U32 xFramerate);
295
296 Return<android::hardware::media::omx::V1_0::Status> setAudioPortFormat(
297     sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE eEncoding);
298
299 void allocateBuffer(sp<IOmxNode> omxNode, BufferInfo* buffer, OMX_U32 portIndex,
300                     OMX_U32 nBufferSize, PortMode portMode);
301
302 void allocatePortBuffers(sp<IOmxNode> omxNode,
303                          android::Vector<BufferInfo>* buffArray,
304                          OMX_U32 portIndex,
305                          PortMode portMode = PortMode::PRESET_BYTE_BUFFER);
306
307 void changeStateLoadedtoIdle(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
308                              android::Vector<BufferInfo>* iBuffer,
309                              android::Vector<BufferInfo>* oBuffer,
310                              OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
311                              PortMode* portMode = nullptr);
312
313 void changeStateIdletoLoaded(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
314                              android::Vector<BufferInfo>* iBuffer,
315                              android::Vector<BufferInfo>* oBuffer,
316                              OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput);
317
318 void changeStateIdletoExecute(sp<IOmxNode> omxNode, sp<CodecObserver> observer);
319
320 void changeStateExecutetoIdle(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
321                               android::Vector<BufferInfo>* iBuffer,
322                               android::Vector<BufferInfo>* oBuffer);
323
324 size_t getEmptyBufferID(android::Vector<BufferInfo>* buffArray);
325
326 void dispatchOutputBuffer(sp<IOmxNode> omxNode,
327                           android::Vector<BufferInfo>* buffArray,
328                           size_t bufferIndex,
329                           PortMode portMode = PortMode::PRESET_BYTE_BUFFER);
330
331 void dispatchInputBuffer(sp<IOmxNode> omxNode,
332                          android::Vector<BufferInfo>* buffArray,
333                          size_t bufferIndex, int bytesCount, uint32_t flags,
334                          uint64_t timestamp,
335                          PortMode portMode = PortMode::PRESET_BYTE_BUFFER);
336
337 void flushPorts(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
338                 android::Vector<BufferInfo>* iBuffer,
339                 android::Vector<BufferInfo>* oBuffer, OMX_U32 kPortIndexInput,
340                 OMX_U32 kPortIndexOutput,
341                 int64_t timeoutUs = DEFAULT_TIMEOUT_PE);
342
343 typedef void (*portreconfig)(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
344                              android::Vector<BufferInfo>* iBuffer,
345                              android::Vector<BufferInfo>* oBuffer,
346                              OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
347                              Message msg, PortMode oPortMode, void* args);
348 void testEOS(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
349              android::Vector<BufferInfo>* iBuffer,
350              android::Vector<BufferInfo>* oBuffer, bool signalEOS,
351              bool& eosFlag, PortMode* portMode = nullptr,
352              portreconfig fptr = nullptr, OMX_U32 kPortIndexInput = 0,
353              OMX_U32 kPortIndexOutput = 1, void* args = nullptr);
354
355 #endif  // MEDIA_HIDL_TEST_COMMON_H