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