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