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) ? msgCondition.wait(msgLock)
207 : msgCondition.waitRelative(msgLock, delayUs * 1000LL);
208 }
209 }
210
211 android::List<Message> msgQueue;
212 android::Mutex msgLock;
213 android::Condition msgCondition;
214 std::function<void(Message, const BufferInfo*)> callBack;
215 };
216
217 /*
218 * Useful Wrapper utilities
219 */
220 template <class T>
InitOMXParams(T * params)221 void InitOMXParams(T* params) {
222 params->nSize = sizeof(T);
223 params->nVersion.s.nVersionMajor = 1;
224 params->nVersion.s.nVersionMinor = 0;
225 params->nVersion.s.nRevision = 0;
226 params->nVersion.s.nStep = 0;
227 }
228
229 template <class T>
getParam(sp<IOmxNode> omxNode,OMX_INDEXTYPE omxIdx,T * params)230 Return<android::hardware::media::omx::V1_0::Status> getParam(
231 sp<IOmxNode> omxNode, OMX_INDEXTYPE omxIdx, T* params) {
232 android::hardware::media::omx::V1_0::Status status;
233 InitOMXParams(params);
234 omxNode->getParameter(
235 toRawIndexType(omxIdx), inHidlBytes(params, sizeof(*params)),
236 [&status, ¶ms](android::hardware::media::omx::V1_0::Status _s,
237 hidl_vec<uint8_t> const& outParams) {
238 status = _s;
239 std::copy(outParams.data(), outParams.data() + outParams.size(),
240 static_cast<uint8_t*>(static_cast<void*>(params)));
241 });
242 return status;
243 }
244
245 template <class T>
setParam(sp<IOmxNode> omxNode,OMX_INDEXTYPE omxIdx,T * params)246 Return<android::hardware::media::omx::V1_0::Status> setParam(
247 sp<IOmxNode> omxNode, OMX_INDEXTYPE omxIdx, T* params) {
248 InitOMXParams(params);
249 return omxNode->setParameter(toRawIndexType(omxIdx),
250 inHidlBytes(params, sizeof(*params)));
251 }
252
253 template <class T>
getPortParam(sp<IOmxNode> omxNode,OMX_INDEXTYPE omxIdx,OMX_U32 nPortIndex,T * params)254 Return<android::hardware::media::omx::V1_0::Status> getPortParam(
255 sp<IOmxNode> omxNode, OMX_INDEXTYPE omxIdx, OMX_U32 nPortIndex, T* params) {
256 android::hardware::media::omx::V1_0::Status status;
257 InitOMXParams(params);
258 params->nPortIndex = nPortIndex;
259 omxNode->getParameter(
260 toRawIndexType(omxIdx), inHidlBytes(params, sizeof(*params)),
261 [&status, ¶ms](android::hardware::media::omx::V1_0::Status _s,
262 hidl_vec<uint8_t> const& outParams) {
263 status = _s;
264 std::copy(outParams.data(), outParams.data() + outParams.size(),
265 static_cast<uint8_t*>(static_cast<void*>(params)));
266 });
267 return status;
268 }
269
270 template <class T>
setPortParam(sp<IOmxNode> omxNode,OMX_INDEXTYPE omxIdx,OMX_U32 nPortIndex,T * params)271 Return<android::hardware::media::omx::V1_0::Status> setPortParam(
272 sp<IOmxNode> omxNode, OMX_INDEXTYPE omxIdx, OMX_U32 nPortIndex, T* params) {
273 InitOMXParams(params);
274 params->nPortIndex = nPortIndex;
275 return omxNode->setParameter(toRawIndexType(omxIdx),
276 inHidlBytes(params, sizeof(*params)));
277 }
278
279 template <class T>
getPortConfig(sp<IOmxNode> omxNode,OMX_INDEXTYPE omxIdx,OMX_U32 nPortIndex,T * params)280 Return<android::hardware::media::omx::V1_0::Status> getPortConfig(
281 sp<IOmxNode> omxNode, OMX_INDEXTYPE omxIdx, OMX_U32 nPortIndex, T* params) {
282 android::hardware::media::omx::V1_0::Status status;
283 InitOMXParams(params);
284 params->nPortIndex = nPortIndex;
285 omxNode->getConfig(
286 toRawIndexType(omxIdx), inHidlBytes(params, sizeof(*params)),
287 [&status, ¶ms](android::hardware::media::omx::V1_0::Status _s,
288 hidl_vec<uint8_t> const& outParams) {
289 status = _s;
290 std::copy(outParams.data(), outParams.data() + outParams.size(),
291 static_cast<uint8_t*>(static_cast<void*>(params)));
292 });
293 return status;
294 }
295
296 template <class T>
setPortConfig(sp<IOmxNode> omxNode,OMX_INDEXTYPE omxIdx,OMX_U32 nPortIndex,T * params)297 Return<android::hardware::media::omx::V1_0::Status> setPortConfig(
298 sp<IOmxNode> omxNode, OMX_INDEXTYPE omxIdx, OMX_U32 nPortIndex, T* params) {
299 InitOMXParams(params);
300 params->nPortIndex = nPortIndex;
301 return omxNode->setConfig(toRawIndexType(omxIdx),
302 inHidlBytes(params, sizeof(*params)));
303 }
304
305 /*
306 * common functions declarations
307 */
308
309 Return<android::hardware::media::omx::V1_0::Status> setRole(sp<IOmxNode> omxNode,
310 const std::string& role);
311
312 Return<android::hardware::media::omx::V1_0::Status> setPortBufferSize(
313 sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_U32 size);
314
315 Return<android::hardware::media::omx::V1_0::Status> setVideoPortFormat(
316 sp<IOmxNode> omxNode, OMX_U32 portIndex,
317 OMX_VIDEO_CODINGTYPE eCompressionFormat, OMX_COLOR_FORMATTYPE eColorFormat,
318 OMX_U32 xFramerate);
319
320 Return<android::hardware::media::omx::V1_0::Status> setAudioPortFormat(
321 sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE eEncoding);
322
323 void allocateBuffer(sp<IOmxNode> omxNode, BufferInfo* buffer, OMX_U32 portIndex,
324 OMX_U32 nBufferSize, PortMode portMode);
325
326 void allocatePortBuffers(sp<IOmxNode> omxNode,
327 android::Vector<BufferInfo>* buffArray,
328 OMX_U32 portIndex,
329 PortMode portMode = PortMode::PRESET_BYTE_BUFFER,
330 bool allocGrap = false);
331
332 void freePortBuffers(android::Vector<BufferInfo>* buffArray, PortMode portMode,
333 bool allocGrap = false);
334
335 void changeStateLoadedtoIdle(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
336 android::Vector<BufferInfo>* iBuffer,
337 android::Vector<BufferInfo>* oBuffer,
338 OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
339 PortMode* portMode = nullptr,
340 bool allocGrap = false);
341
342 void changeStateIdletoLoaded(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
343 android::Vector<BufferInfo>* iBuffer,
344 android::Vector<BufferInfo>* oBuffer, OMX_U32 kPortIndexInput,
345 OMX_U32 kPortIndexOutput, PortMode* portMode = nullptr,
346 bool allocGrap = false);
347
348 void changeStateIdletoExecute(sp<IOmxNode> omxNode, sp<CodecObserver> observer);
349
350 void changeStateExecutetoIdle(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
351 android::Vector<BufferInfo>* iBuffer,
352 android::Vector<BufferInfo>* oBuffer);
353
354 size_t getEmptyBufferID(android::Vector<BufferInfo>* buffArray);
355
356 void dispatchOutputBuffer(sp<IOmxNode> omxNode,
357 android::Vector<BufferInfo>* buffArray,
358 size_t bufferIndex,
359 PortMode portMode = PortMode::PRESET_BYTE_BUFFER);
360
361 void dispatchInputBuffer(sp<IOmxNode> omxNode,
362 android::Vector<BufferInfo>* buffArray,
363 size_t bufferIndex, int bytesCount, uint32_t flags,
364 uint64_t timestamp,
365 PortMode portMode = PortMode::PRESET_BYTE_BUFFER);
366
367 void flushPorts(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
368 android::Vector<BufferInfo>* iBuffer,
369 android::Vector<BufferInfo>* oBuffer, OMX_U32 kPortIndexInput,
370 OMX_U32 kPortIndexOutput,
371 int64_t timeoutUs = DEFAULT_TIMEOUT_PE);
372
373 typedef void (*portreconfig)(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
374 android::Vector<BufferInfo>* iBuffer,
375 android::Vector<BufferInfo>* oBuffer,
376 OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
377 Message msg, PortMode oPortMode, void* args);
378 void testEOS(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
379 android::Vector<BufferInfo>* iBuffer,
380 android::Vector<BufferInfo>* oBuffer, bool signalEOS,
381 bool& eosFlag, PortMode* portMode = nullptr,
382 portreconfig fptr = nullptr, OMX_U32 kPortIndexInput = 0,
383 OMX_U32 kPortIndexOutput = 1, void* args = nullptr);
384
385 hidl_vec<IOmx::ComponentInfo> getComponentInfoList(sp<IOmx> omx);
386
387 // Return all test parameters, a list of tuple of <instance, component, role>
388 const std::vector<std::tuple<std::string, std::string, std::string>>& getTestParameters(
389 const std::string& filter);
390
391 #endif // MEDIA_HIDL_TEST_COMMON_H
392