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