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