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 ANDROID_HARDWARE_MEDIA_OMX_V1_0_IMPL_CONVERSION_H
18 #define ANDROID_HARDWARE_MEDIA_OMX_V1_0_IMPL_CONVERSION_H
19
20 #include <vector>
21 #include <list>
22
23 #include <cinttypes>
24 #include <unistd.h>
25
26 #include <hidl/MQDescriptor.h>
27 #include <hidl/Status.h>
28 #include <hidlmemory/mapping.h>
29
30 #include <binder/Binder.h>
31 #include <binder/Status.h>
32 #include <ui/BufferQueueDefs.h>
33 #include <ui/FenceTime.h>
34 #include <cutils/native_handle.h>
35
36 #include <media/OMXFenceParcelable.h>
37 #include <media/OMXBuffer.h>
38 #include <media/omx/1.0/Conversion.h>
39 #include <media/hardware/VideoAPI.h>
40 #include <media/stagefright/MediaErrors.h>
41
42 #include <android/hidl/memory/1.0/IMemory.h>
43 #include <android/hardware/graphics/bufferqueue/1.0/IProducerListener.h>
44 #include <android/hardware/media/omx/1.0/types.h>
45 #include <android/hardware/media/omx/1.0/IOmx.h>
46 #include <android/hardware/media/omx/1.0/IOmxNode.h>
47 #include <android/hardware/media/omx/1.0/IOmxBufferSource.h>
48 #include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
49 #include <android/hardware/media/omx/1.0/IOmxObserver.h>
50
51 #include <android/IGraphicBufferSource.h>
52 #include <android/IOMXBufferSource.h>
53
54 namespace android {
55 namespace hardware {
56 namespace media {
57 namespace omx {
58 namespace V1_0 {
59 namespace implementation {
60
61 using ::android::hardware::hidl_array;
62 using ::android::hardware::hidl_string;
63 using ::android::hardware::hidl_vec;
64 using ::android::hardware::hidl_handle;
65 using ::android::hardware::Return;
66 using ::android::hardware::Void;
67 using ::android::sp;
68
69 using ::android::String8;
70 using ::android::OMXFenceParcelable;
71
72 using ::android::hardware::media::omx::V1_0::Message;
73 using ::android::omx_message;
74
75 using ::android::hardware::media::omx::V1_0::ColorAspects;
76 using ::android::hardware::media::V1_0::Rect;
77 using ::android::hardware::media::V1_0::Region;
78
79 using ::android::hardware::graphics::common::V1_0::Dataspace;
80
81 using ::android::hardware::graphics::common::V1_0::PixelFormat;
82
83 using ::android::OMXBuffer;
84
85 using ::android::hardware::media::V1_0::AnwBuffer;
86 using ::android::GraphicBuffer;
87
88 using ::android::hardware::media::omx::V1_0::IOmx;
89 using ::android::IOMX;
90
91 using ::android::hardware::media::omx::V1_0::IOmxNode;
92 using ::android::IOMXNode;
93
94 using ::android::hardware::media::omx::V1_0::IOmxObserver;
95 using ::android::IOMXObserver;
96
97 using ::android::hardware::media::omx::V1_0::IOmxBufferSource;
98 using ::android::IOMXBufferSource;
99
100 typedef ::android::hardware::graphics::bufferqueue::V1_0::IGraphicBufferProducer
101 HGraphicBufferProducer;
102
103 // Use the conversion functions from libmedia_omx so that we don't need libgui
104 using namespace ::android::hardware::media::omx::V1_0::utils;
105
106 /**
107 * Conversion functions
108 * ====================
109 *
110 * There are two main directions of conversion:
111 * - `inTargetType(...)`: Create a wrapper whose lifetime depends on the
112 * input. The wrapper has type `TargetType`.
113 * - `toTargetType(...)`: Create a standalone object of type `TargetType` that
114 * corresponds to the input. The lifetime of the output does not depend on the
115 * lifetime of the input.
116 * - `wrapIn(TargetType*, ...)`: Same as `inTargetType()`, but for `TargetType`
117 * that cannot be copied and/or moved efficiently, or when there are multiple
118 * output arguments.
119 * - `convertTo(TargetType*, ...)`: Same as `toTargetType()`, but for
120 * `TargetType` that cannot be copied and/or moved efficiently, or when there
121 * are multiple output arguments.
122 *
123 * `wrapIn()` and `convertTo()` functions will take output arguments before
124 * input arguments. Some of these functions might return a value to indicate
125 * success or error.
126 *
127 * In converting or wrapping something as a Treble type that contains a
128 * `hidl_handle`, `native_handle_t*` will need to be created and returned as
129 * an additional output argument, hence only `wrapIn()` or `convertTo()` would
130 * be available. The caller must call `native_handle_delete()` to deallocate the
131 * returned native handle when it is no longer needed.
132 *
133 * For types that contain file descriptors, `inTargetType()` and `wrapAs()` do
134 * not perform duplication of file descriptors, while `toTargetType()` and
135 * `convertTo()` do.
136 */
137
138 /**
139 * \brief Convert `status_t` to `Status`.
140 *
141 * \param[in] l The source `status_t`.
142 * \return The corresponding `Status`.
143 */
144 // convert: status_t -> Status
toStatus(status_t l)145 inline Status toStatus(status_t l) {
146 switch (l) {
147 case NO_ERROR:
148 case NAME_NOT_FOUND:
149 case WOULD_BLOCK:
150 case NO_MEMORY:
151 case ALREADY_EXISTS:
152 case NO_INIT:
153 case BAD_VALUE:
154 case DEAD_OBJECT:
155 case INVALID_OPERATION:
156 case TIMED_OUT:
157 case ERROR_UNSUPPORTED:
158 case UNKNOWN_ERROR:
159 case BufferQueueDefs::RELEASE_ALL_BUFFERS:
160 case BufferQueueDefs::BUFFER_NEEDS_REALLOCATION:
161 return static_cast<Status>(l);
162 case NOT_ENOUGH_DATA:
163 return Status::BUFFER_NEEDS_REALLOCATION;
164 default:
165 ALOGW("Unrecognized status value: %" PRId32, static_cast<int32_t>(l));
166 return static_cast<Status>(l);
167 }
168 }
169
170 /**
171 * \brief Wrap an `omx_message` and construct the corresponding `Message`.
172 *
173 * \param[out] t The wrapper of type `Message`.
174 * \param[out] nh The native_handle_t referred to by `t->fence`.
175 * \param[in] l The source `omx_message`.
176 * \return `true` if the wrapping is successful; `false` otherwise.
177 *
178 * Upon success, \p nh will be created to hold the file descriptor stored in
179 * `l.fenceFd`, and `t->fence` will point to \p nh. \p nh will need to be
180 * destroyed manually by `native_handle_delete()` when \p t is no longer needed.
181 *
182 * Upon failure, \p nh will not be created and will not need to be deleted. \p t
183 * will be invalid.
184 */
185 // wrap, omx_message -> Message, native_handle_t*
wrapAs(Message * t,native_handle_t ** nh,omx_message const & l)186 inline bool wrapAs(Message* t, native_handle_t** nh, omx_message const& l) {
187 *nh = native_handle_create_from_fd(l.fenceFd);
188 if (!*nh) {
189 return false;
190 }
191 t->fence = *nh;
192 switch (l.type) {
193 case omx_message::EVENT:
194 t->type = Message::Type::EVENT;
195 t->data.eventData.event = uint32_t(l.u.event_data.event);
196 t->data.eventData.data1 = l.u.event_data.data1;
197 t->data.eventData.data2 = l.u.event_data.data2;
198 t->data.eventData.data3 = l.u.event_data.data3;
199 t->data.eventData.data4 = l.u.event_data.data4;
200 break;
201 case omx_message::EMPTY_BUFFER_DONE:
202 t->type = Message::Type::EMPTY_BUFFER_DONE;
203 t->data.bufferData.buffer = l.u.buffer_data.buffer;
204 break;
205 case omx_message::FILL_BUFFER_DONE:
206 t->type = Message::Type::FILL_BUFFER_DONE;
207 t->data.extendedBufferData.buffer = l.u.extended_buffer_data.buffer;
208 t->data.extendedBufferData.rangeOffset =
209 l.u.extended_buffer_data.range_offset;
210 t->data.extendedBufferData.rangeLength =
211 l.u.extended_buffer_data.range_length;
212 t->data.extendedBufferData.flags = l.u.extended_buffer_data.flags;
213 t->data.extendedBufferData.timestampUs =
214 l.u.extended_buffer_data.timestamp;
215 break;
216 case omx_message::FRAME_RENDERED:
217 t->type = Message::Type::FRAME_RENDERED;
218 t->data.renderData.timestampUs = l.u.render_data.timestamp;
219 t->data.renderData.systemTimeNs = l.u.render_data.nanoTime;
220 break;
221 default:
222 native_handle_delete(*nh);
223 return false;
224 }
225 return true;
226 }
227
228 /**
229 * \brief Wrap a `Message` inside an `omx_message`.
230 *
231 * \param[out] l The wrapper of type `omx_message`.
232 * \param[in] t The source `Message`.
233 * \return `true` if the wrapping is successful; `false` otherwise.
234 */
235 // wrap: Message -> omx_message
wrapAs(omx_message * l,Message const & t)236 inline bool wrapAs(omx_message* l, Message const& t) {
237 l->fenceFd = native_handle_read_fd(t.fence);
238 switch (t.type) {
239 case Message::Type::EVENT:
240 l->type = omx_message::EVENT;
241 l->u.event_data.event = OMX_EVENTTYPE(t.data.eventData.event);
242 l->u.event_data.data1 = t.data.eventData.data1;
243 l->u.event_data.data2 = t.data.eventData.data2;
244 l->u.event_data.data3 = t.data.eventData.data3;
245 l->u.event_data.data4 = t.data.eventData.data4;
246 break;
247 case Message::Type::EMPTY_BUFFER_DONE:
248 l->type = omx_message::EMPTY_BUFFER_DONE;
249 l->u.buffer_data.buffer = t.data.bufferData.buffer;
250 break;
251 case Message::Type::FILL_BUFFER_DONE:
252 l->type = omx_message::FILL_BUFFER_DONE;
253 l->u.extended_buffer_data.buffer = t.data.extendedBufferData.buffer;
254 l->u.extended_buffer_data.range_offset =
255 t.data.extendedBufferData.rangeOffset;
256 l->u.extended_buffer_data.range_length =
257 t.data.extendedBufferData.rangeLength;
258 l->u.extended_buffer_data.flags = t.data.extendedBufferData.flags;
259 l->u.extended_buffer_data.timestamp =
260 t.data.extendedBufferData.timestampUs;
261 break;
262 case Message::Type::FRAME_RENDERED:
263 l->type = omx_message::FRAME_RENDERED;
264 l->u.render_data.timestamp = t.data.renderData.timestampUs;
265 l->u.render_data.nanoTime = t.data.renderData.systemTimeNs;
266 break;
267 default:
268 return false;
269 }
270 return true;
271 }
272
273 /**
274 * \brief Similar to `wrapTo(omx_message*, Message const&)`, but the output will
275 * have an extended lifetime.
276 *
277 * \param[out] l The output `omx_message`.
278 * \param[in] t The source `Message`.
279 * \return `true` if the conversion is successful; `false` otherwise.
280 *
281 * This function calls `wrapto()`, then attempts to duplicate the file
282 * descriptor for the fence if it is not `-1`. If duplication fails, `false`
283 * will be returned.
284 */
285 // convert: Message -> omx_message
convertTo(omx_message * l,Message const & t)286 inline bool convertTo(omx_message* l, Message const& t) {
287 if (!wrapAs(l, t)) {
288 return false;
289 }
290 if (l->fenceFd == -1) {
291 return true;
292 }
293 l->fenceFd = dup(l->fenceFd);
294 return l->fenceFd != -1;
295 }
296
297 /**
298 * \brief Wrap an `OMXFenceParcelable` inside a `hidl_handle`.
299 *
300 * \param[out] t The wrapper of type `hidl_handle`.
301 * \param[out] nh The native handle created to hold the file descriptor inside
302 * \p l.
303 * \param[in] l The source `OMXFenceParcelable`, which essentially contains one
304 * file descriptor.
305 * \return `true` if \p t and \p nh are successfully created to wrap around \p
306 * l; `false` otherwise.
307 *
308 * On success, \p nh needs to be deleted by the caller with
309 * `native_handle_delete()` after \p t and \p nh are no longer needed.
310 *
311 * On failure, \p nh will not need to be deleted, and \p t will hold an invalid
312 * value.
313 */
314 // wrap: OMXFenceParcelable -> hidl_handle, native_handle_t*
wrapAs(hidl_handle * t,native_handle_t ** nh,OMXFenceParcelable const & l)315 inline bool wrapAs(hidl_handle* t, native_handle_t** nh,
316 OMXFenceParcelable const& l) {
317 *nh = native_handle_create_from_fd(l.get());
318 if (!*nh) {
319 return false;
320 }
321 *t = *nh;
322 return true;
323 }
324
325 /**
326 * \brief Wrap a `hidl_handle` inside an `OMXFenceParcelable`.
327 *
328 * \param[out] l The wrapper of type `OMXFenceParcelable`.
329 * \param[in] t The source `hidl_handle`.
330 */
331 // wrap: hidl_handle -> OMXFenceParcelable
wrapAs(OMXFenceParcelable * l,hidl_handle const & t)332 inline void wrapAs(OMXFenceParcelable* l, hidl_handle const& t) {
333 l->mFenceFd = native_handle_read_fd(t);
334 }
335
336 /**
337 * \brief Convert a `hidl_handle` to `OMXFenceParcelable`. If `hidl_handle`
338 * contains file descriptors, the first file descriptor will be duplicated and
339 * stored in the output `OMXFenceParcelable`.
340 *
341 * \param[out] l The output `OMXFenceParcelable`.
342 * \param[in] t The input `hidl_handle`.
343 * \return `false` if \p t contains a valid file descriptor but duplication
344 * fails; `true` otherwise.
345 */
346 // convert: hidl_handle -> OMXFenceParcelable
convertTo(OMXFenceParcelable * l,hidl_handle const & t)347 inline bool convertTo(OMXFenceParcelable* l, hidl_handle const& t) {
348 int fd = native_handle_read_fd(t);
349 if (fd != -1) {
350 fd = dup(fd);
351 if (fd == -1) {
352 return false;
353 }
354 }
355 l->mFenceFd = fd;
356 return true;
357 }
358
359 /**
360 * \brief Convert `::android::ColorAspects` to `ColorAspects`.
361 *
362 * \param[in] l The source `::android::ColorAspects`.
363 * \return The corresponding `ColorAspects`.
364 */
365 // convert: ::android::ColorAspects -> ColorAspects
toHardwareColorAspects(::android::ColorAspects const & l)366 inline ColorAspects toHardwareColorAspects(::android::ColorAspects const& l) {
367 return ColorAspects{
368 static_cast<ColorAspects::Range>(l.mRange),
369 static_cast<ColorAspects::Primaries>(l.mPrimaries),
370 static_cast<ColorAspects::Transfer>(l.mTransfer),
371 static_cast<ColorAspects::MatrixCoeffs>(l.mMatrixCoeffs)};
372 }
373
374 /**
375 * \brief Convert `int32_t` to `ColorAspects`.
376 *
377 * \param[in] l The source `int32_t`.
378 * \return The corresponding `ColorAspects`.
379 */
380 // convert: int32_t -> ColorAspects
toHardwareColorAspects(int32_t l)381 inline ColorAspects toHardwareColorAspects(int32_t l) {
382 return ColorAspects{
383 static_cast<ColorAspects::Range>((l >> 24) & 0xFF),
384 static_cast<ColorAspects::Primaries>((l >> 16) & 0xFF),
385 static_cast<ColorAspects::Transfer>(l & 0xFF),
386 static_cast<ColorAspects::MatrixCoeffs>((l >> 8) & 0xFF)};
387 }
388
389 /**
390 * \brief Convert `ColorAspects` to `::android::ColorAspects`.
391 *
392 * \param[in] t The source `ColorAspects`.
393 * \return The corresponding `::android::ColorAspects`.
394 */
395 // convert: ColorAspects -> ::android::ColorAspects
toCompactColorAspects(ColorAspects const & t)396 inline int32_t toCompactColorAspects(ColorAspects const& t) {
397 return static_cast<int32_t>(
398 (static_cast<uint32_t>(t.range) << 24) |
399 (static_cast<uint32_t>(t.primaries) << 16) |
400 (static_cast<uint32_t>(t.transfer)) |
401 (static_cast<uint32_t>(t.matrixCoeffs) << 8));
402 }
403
404 /**
405 * \brief Wrap `GraphicBuffer` in `CodecBuffer`.
406 *
407 * \param[out] t The wrapper of type `CodecBuffer`.
408 * \param[in] l The source `GraphicBuffer`.
409 */
410 // wrap: OMXBuffer -> CodecBuffer
wrapAs(CodecBuffer * t,sp<GraphicBuffer> const & graphicBuffer)411 inline CodecBuffer *wrapAs(CodecBuffer *t, sp<GraphicBuffer> const& graphicBuffer) {
412 t->sharedMemory = hidl_memory();
413 t->nativeHandle = hidl_handle();
414 t->type = CodecBuffer::Type::ANW_BUFFER;
415 if (graphicBuffer == nullptr) {
416 t->attr.anwBuffer.width = 0;
417 t->attr.anwBuffer.height = 0;
418 t->attr.anwBuffer.stride = 0;
419 t->attr.anwBuffer.format = static_cast<PixelFormat>(1);
420 t->attr.anwBuffer.layerCount = 0;
421 t->attr.anwBuffer.usage = 0;
422 return t;
423 }
424 t->attr.anwBuffer.width = graphicBuffer->getWidth();
425 t->attr.anwBuffer.height = graphicBuffer->getHeight();
426 t->attr.anwBuffer.stride = graphicBuffer->getStride();
427 t->attr.anwBuffer.format = static_cast<PixelFormat>(
428 graphicBuffer->getPixelFormat());
429 t->attr.anwBuffer.layerCount = graphicBuffer->getLayerCount();
430 t->attr.anwBuffer.usage = graphicBuffer->getUsage();
431 t->nativeHandle = graphicBuffer->handle;
432 return t;
433 }
434
435 /**
436 * \brief Wrap `OMXBuffer` in `CodecBuffer`.
437 *
438 * \param[out] t The wrapper of type `CodecBuffer`.
439 * \param[in] l The source `OMXBuffer`.
440 * \return `true` if the wrapping is successful; `false` otherwise.
441 */
442 // wrap: OMXBuffer -> CodecBuffer
wrapAs(CodecBuffer * t,OMXBuffer const & l)443 inline bool wrapAs(CodecBuffer* t, OMXBuffer const& l) {
444 t->sharedMemory = hidl_memory();
445 t->nativeHandle = hidl_handle();
446 switch (l.mBufferType) {
447 case OMXBuffer::kBufferTypeInvalid: {
448 t->type = CodecBuffer::Type::INVALID;
449 return true;
450 }
451 case OMXBuffer::kBufferTypePreset: {
452 t->type = CodecBuffer::Type::PRESET;
453 t->attr.preset.rangeLength = static_cast<uint32_t>(l.mRangeLength);
454 t->attr.preset.rangeOffset = static_cast<uint32_t>(l.mRangeOffset);
455 return true;
456 }
457 case OMXBuffer::kBufferTypeHidlMemory: {
458 t->type = CodecBuffer::Type::SHARED_MEM;
459 t->sharedMemory = l.mHidlMemory;
460 return true;
461 }
462 case OMXBuffer::kBufferTypeSharedMem: {
463 // This is not supported.
464 return false;
465 }
466 case OMXBuffer::kBufferTypeANWBuffer: {
467 wrapAs(t, l.mGraphicBuffer);
468 return true;
469 }
470 case OMXBuffer::kBufferTypeNativeHandle: {
471 t->type = CodecBuffer::Type::NATIVE_HANDLE;
472 t->nativeHandle = l.mNativeHandle->handle();
473 return true;
474 }
475 }
476 return false;
477 }
478
479 /**
480 * \brief Convert `CodecBuffer` to `OMXBuffer`.
481 *
482 * \param[out] l The destination `OMXBuffer`.
483 * \param[in] t The source `CodecBuffer`.
484 * \return `true` if successful; `false` otherwise.
485 */
486 // convert: CodecBuffer -> OMXBuffer
convertTo(OMXBuffer * l,CodecBuffer const & t)487 inline bool convertTo(OMXBuffer* l, CodecBuffer const& t) {
488 switch (t.type) {
489 case CodecBuffer::Type::INVALID: {
490 *l = OMXBuffer();
491 return true;
492 }
493 case CodecBuffer::Type::PRESET: {
494 *l = OMXBuffer(
495 t.attr.preset.rangeOffset,
496 t.attr.preset.rangeLength);
497 return true;
498 }
499 case CodecBuffer::Type::SHARED_MEM: {
500 *l = OMXBuffer(t.sharedMemory);
501 return true;
502 }
503 case CodecBuffer::Type::ANW_BUFFER: {
504 if (t.nativeHandle.getNativeHandle() == nullptr) {
505 *l = OMXBuffer(sp<GraphicBuffer>(nullptr));
506 return true;
507 }
508 AnwBuffer anwBuffer;
509 anwBuffer.nativeHandle = t.nativeHandle;
510 anwBuffer.attr = t.attr.anwBuffer;
511 sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
512 if (!::android::hardware::media::omx::V1_0::utils::convertTo(
513 graphicBuffer.get(), anwBuffer)) {
514 return false;
515 }
516 *l = OMXBuffer(graphicBuffer);
517 return true;
518 }
519 case CodecBuffer::Type::NATIVE_HANDLE: {
520 *l = OMXBuffer(NativeHandle::create(
521 native_handle_clone(t.nativeHandle), true));
522 return true;
523 }
524 }
525 return false;
526 }
527
528 /**
529 * \brief Convert `IOMX::ComponentInfo` to `IOmx::ComponentInfo`.
530 *
531 * \param[out] t The destination `IOmx::ComponentInfo`.
532 * \param[in] l The source `IOMX::ComponentInfo`.
533 */
534 // convert: IOMX::ComponentInfo -> IOmx::ComponentInfo
convertTo(IOmx::ComponentInfo * t,IOMX::ComponentInfo const & l)535 inline bool convertTo(IOmx::ComponentInfo* t, IOMX::ComponentInfo const& l) {
536 t->mName = l.mName.string();
537 t->mRoles.resize(l.mRoles.size());
538 size_t i = 0;
539 for (auto& role : l.mRoles) {
540 t->mRoles[i++] = role.string();
541 }
542 return true;
543 }
544
545 /**
546 * \brief Convert `IOmx::ComponentInfo` to `IOMX::ComponentInfo`.
547 *
548 * \param[out] l The destination `IOMX::ComponentInfo`.
549 * \param[in] t The source `IOmx::ComponentInfo`.
550 */
551 // convert: IOmx::ComponentInfo -> IOMX::ComponentInfo
convertTo(IOMX::ComponentInfo * l,IOmx::ComponentInfo const & t)552 inline bool convertTo(IOMX::ComponentInfo* l, IOmx::ComponentInfo const& t) {
553 l->mName = t.mName.c_str();
554 l->mRoles.clear();
555 for (size_t i = 0; i < t.mRoles.size(); ++i) {
556 l->mRoles.push_back(String8(t.mRoles[i].c_str()));
557 }
558 return true;
559 }
560
561 /**
562 * \brief Convert `OMX_BOOL` to `bool`.
563 *
564 * \param[in] l The source `OMX_BOOL`.
565 * \return The destination `bool`.
566 */
567 // convert: OMX_BOOL -> bool
toRawBool(OMX_BOOL l)568 inline bool toRawBool(OMX_BOOL l) {
569 return l == OMX_FALSE ? false : true;
570 }
571
572 /**
573 * \brief Convert `bool` to `OMX_BOOL`.
574 *
575 * \param[in] t The source `bool`.
576 * \return The destination `OMX_BOOL`.
577 */
578 // convert: bool -> OMX_BOOL
toEnumBool(bool t)579 inline OMX_BOOL toEnumBool(bool t) {
580 return t ? OMX_TRUE : OMX_FALSE;
581 }
582
583 /**
584 * \brief Convert `OMX_COMMANDTYPE` to `uint32_t`.
585 *
586 * \param[in] l The source `OMX_COMMANDTYPE`.
587 * \return The underlying value of type `uint32_t`.
588 *
589 * `OMX_COMMANDTYPE` is an enum type whose underlying type is `uint32_t`.
590 */
591 // convert: OMX_COMMANDTYPE -> uint32_t
toRawCommandType(OMX_COMMANDTYPE l)592 inline uint32_t toRawCommandType(OMX_COMMANDTYPE l) {
593 return static_cast<uint32_t>(l);
594 }
595
596 /**
597 * \brief Convert `uint32_t` to `OMX_COMMANDTYPE`.
598 *
599 * \param[in] t The source `uint32_t`.
600 * \return The corresponding enum value of type `OMX_COMMANDTYPE`.
601 *
602 * `OMX_COMMANDTYPE` is an enum type whose underlying type is `uint32_t`.
603 */
604 // convert: uint32_t -> OMX_COMMANDTYPE
toEnumCommandType(uint32_t t)605 inline OMX_COMMANDTYPE toEnumCommandType(uint32_t t) {
606 return static_cast<OMX_COMMANDTYPE>(t);
607 }
608
609 /**
610 * \brief Convert `OMX_INDEXTYPE` to `uint32_t`.
611 *
612 * \param[in] l The source `OMX_INDEXTYPE`.
613 * \return The underlying value of type `uint32_t`.
614 *
615 * `OMX_INDEXTYPE` is an enum type whose underlying type is `uint32_t`.
616 */
617 // convert: OMX_INDEXTYPE -> uint32_t
toRawIndexType(OMX_INDEXTYPE l)618 inline uint32_t toRawIndexType(OMX_INDEXTYPE l) {
619 return static_cast<uint32_t>(l);
620 }
621
622 /**
623 * \brief Convert `uint32_t` to `OMX_INDEXTYPE`.
624 *
625 * \param[in] t The source `uint32_t`.
626 * \return The corresponding enum value of type `OMX_INDEXTYPE`.
627 *
628 * `OMX_INDEXTYPE` is an enum type whose underlying type is `uint32_t`.
629 */
630 // convert: uint32_t -> OMX_INDEXTYPE
toEnumIndexType(uint32_t t)631 inline OMX_INDEXTYPE toEnumIndexType(uint32_t t) {
632 return static_cast<OMX_INDEXTYPE>(t);
633 }
634
635 /**
636 * \brief Convert `IOMX::PortMode` to `PortMode`.
637 *
638 * \param[in] l The source `IOMX::PortMode`.
639 * \return The destination `PortMode`.
640 */
641 // convert: IOMX::PortMode -> PortMode
toHardwarePortMode(IOMX::PortMode l)642 inline PortMode toHardwarePortMode(IOMX::PortMode l) {
643 return static_cast<PortMode>(l);
644 }
645
646 /**
647 * \brief Convert `PortMode` to `IOMX::PortMode`.
648 *
649 * \param[in] t The source `PortMode`.
650 * \return The destination `IOMX::PortMode`.
651 */
652 // convert: PortMode -> IOMX::PortMode
toIOMXPortMode(PortMode t)653 inline IOMX::PortMode toIOMXPortMode(PortMode t) {
654 return static_cast<IOMX::PortMode>(t);
655 }
656
657 /**
658 * \brief Convert `OMX_TICKS` to `uint64_t`.
659 *
660 * \param[in] l The source `OMX_TICKS`.
661 * \return The destination `uint64_t`.
662 */
663 // convert: OMX_TICKS -> uint64_t
toRawTicks(OMX_TICKS l)664 inline uint64_t toRawTicks(OMX_TICKS l) {
665 #ifndef OMX_SKIP64BIT
666 return static_cast<uint64_t>(l);
667 #else
668 return static_cast<uint64_t>(l.nLowPart) |
669 static_cast<uint64_t>(l.nHighPart << 32);
670 #endif
671 }
672
673 /**
674 * \brief Convert `uint64_t` to `OMX_TICKS`.
675 *
676 * \param[in] l The source `uint64_t`.
677 * \return The destination `OMX_TICKS`.
678 */
679 // convert: uint64_t -> OMX_TICKS
toOMXTicks(uint64_t t)680 inline OMX_TICKS toOMXTicks(uint64_t t) {
681 #ifndef OMX_SKIP64BIT
682 return static_cast<OMX_TICKS>(t);
683 #else
684 return OMX_TICKS{
685 static_cast<uint32_t>(t & 0xFFFFFFFF),
686 static_cast<uint32_t>(t >> 32)};
687 #endif
688 }
689
690 } // namespace implementation
691 } // namespace V1_0
692 } // namespace omx
693 } // namespace media
694 } // namespace hardware
695 } // namespace android
696
697 #endif // ANDROID_HARDWARE_MEDIA_OMX_V1_0_IMPL_CONVERSION_H
698