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