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