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