/* * Copyright 2016, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ANDROID_HARDWARE_MEDIA_OMX_V1_0__CONVERSION_H #define ANDROID_HARDWARE_MEDIA_OMX_V1_0__CONVERSION_H #include <vector> #include <list> #include <unistd.h> #include <hidl/MQDescriptor.h> #include <hidl/Status.h> #include <hidlmemory/mapping.h> #include <binder/Binder.h> #include <binder/Status.h> #include <ui/FenceTime.h> #include <cutils/native_handle.h> #include <ui/GraphicBuffer.h> #include <media/OMXFenceParcelable.h> #include <media/OMXBuffer.h> #include <media/hardware/VideoAPI.h> #include <android/hidl/memory/1.0/IMemory.h> #include <android/hardware/media/omx/1.0/types.h> #include <android/hardware/media/omx/1.0/IOmx.h> #include <android/hardware/media/omx/1.0/IOmxNode.h> #include <android/hardware/media/omx/1.0/IOmxBufferSource.h> #include <android/hardware/media/omx/1.0/IOmxObserver.h> #include <android/hardware/media/omx/1.0/IGraphicBufferSource.h> #include <android/IGraphicBufferSource.h> #include <android/IOMXBufferSource.h> namespace android { namespace hardware { namespace media { namespace omx { namespace V1_0 { namespace utils { using ::android::hardware::hidl_array; using ::android::hardware::hidl_string; using ::android::hardware::hidl_vec; using ::android::hardware::hidl_handle; using ::android::hardware::Return; using ::android::hardware::Void; using ::android::sp; using ::android::String8; using ::android::OMXFenceParcelable; using ::android::hardware::media::omx::V1_0::Message; using ::android::omx_message; using ::android::hardware::media::omx::V1_0::ColorAspects; using ::android::hardware::media::V1_0::Rect; using ::android::hardware::media::V1_0::Region; using ::android::hardware::graphics::common::V1_0::Dataspace; using ::android::hardware::graphics::common::V1_0::PixelFormat; using ::android::OMXBuffer; using ::android::hardware::media::V1_0::AnwBuffer; using ::android::GraphicBuffer; using ::android::hardware::media::omx::V1_0::IOmx; using ::android::IOMX; using ::android::hardware::media::omx::V1_0::IOmxNode; using ::android::IOMXNode; using ::android::hardware::media::omx::V1_0::IOmxObserver; using ::android::IOMXObserver; using ::android::hardware::media::omx::V1_0::IOmxBufferSource; using ::android::IOMXBufferSource; // native_handle_t helper functions. /** * \brief Take an fd and create a native handle containing only the given fd. * The created handle will need to be deleted manually with * `native_handle_delete()`. * * \param[in] fd The source file descriptor (of type `int`). * \return The create `native_handle_t*` that contains the given \p fd. If the * supplied \p fd is negative, the created native handle will contain no file * descriptors. * * If the native handle cannot be created, the return value will be * `nullptr`. * * This function does not duplicate the file descriptor. */ inline native_handle_t* native_handle_create_from_fd(int fd) { if (fd < 0) { return native_handle_create(0, 0); } native_handle_t* nh = native_handle_create(1, 0); if (nh == nullptr) { return nullptr; } nh->data[0] = fd; return nh; } /** * \brief Extract a file descriptor from a native handle. * * \param[in] nh The source `native_handle_t*`. * \param[in] index The index of the file descriptor in \p nh to read from. This * input has the default value of `0`. * \return The `index`-th file descriptor in \p nh. If \p nh does not have * enough file descriptors, the returned value will be `-1`. * * This function does not duplicate the file descriptor. */ inline int native_handle_read_fd(native_handle_t const* nh, int index = 0) { return ((nh == nullptr) || (nh->numFds == 0) || (nh->numFds <= index) || (index < 0)) ? -1 : nh->data[index]; } /** * Conversion functions * ==================== * * There are two main directions of conversion: * - `inTargetType(...)`: Create a wrapper whose lifetime depends on the * input. The wrapper has type `TargetType`. * - `toTargetType(...)`: Create a standalone object of type `TargetType` that * corresponds to the input. The lifetime of the output does not depend on the * lifetime of the input. * - `wrapIn(TargetType*, ...)`: Same as `inTargetType()`, but for `TargetType` * that cannot be copied and/or moved efficiently, or when there are multiple * output arguments. * - `convertTo(TargetType*, ...)`: Same as `toTargetType()`, but for * `TargetType` that cannot be copied and/or moved efficiently, or when there * are multiple output arguments. * * `wrapIn()` and `convertTo()` functions will take output arguments before * input arguments. Some of these functions might return a value to indicate * success or error. * * In converting or wrapping something as a Treble type that contains a * `hidl_handle`, `native_handle_t*` will need to be created and returned as * an additional output argument, hence only `wrapIn()` or `convertTo()` would * be available. The caller must call `native_handle_delete()` to deallocate the * returned native handle when it is no longer needed. * * For types that contain file descriptors, `inTargetType()` and `wrapAs()` do * not perform duplication of file descriptors, while `toTargetType()` and * `convertTo()` do. */ /** * \brief Convert `Return<void>` to `binder::Status`. * * \param[in] t The source `Return<void>`. * \return The corresponding `binder::Status`. */ // convert: Return<void> -> ::android::binder::Status inline ::android::binder::Status toBinderStatus( Return<void> const& t) { return ::android::binder::Status::fromExceptionCode( t.isOk() ? OK : UNKNOWN_ERROR, t.description().c_str()); } /** * \brief Convert `Return<Status>` to `binder::Status`. * * \param[in] t The source `Return<Status>`. * \return The corresponding `binder::Status`. */ // convert: Return<Status> -> ::android::binder::Status inline ::android::binder::Status toBinderStatus( Return<Status> const& t) { return ::android::binder::Status::fromStatusT( t.isOk() ? static_cast<status_t>(static_cast<Status>(t)) : UNKNOWN_ERROR); } /** * \brief Convert `Return<Status>` to `status_t`. This is for legacy binder * calls. * * \param[in] t The source `Return<Status>`. * \return The corresponding `status_t`. * * This function first check if \p t has a transport error. If it does, then the * return value is the transport error code. Otherwise, the return value is * converted from `Status` contained inside \p t. * * Note: * - This `Status` is omx-specific. It is defined in `types.hal`. * - The name of this function is not `convert`. */ // convert: Status -> status_t inline status_t toStatusT(Return<Status> const& t) { return t.isOk() ? static_cast<status_t>(static_cast<Status>(t)) : UNKNOWN_ERROR; } /** * \brief Convert `Return<void>` to `status_t`. This is for legacy binder calls. * * \param[in] t The source `Return<void>`. * \return The corresponding `status_t`. */ // convert: Return<void> -> status_t inline status_t toStatusT(Return<void> const& t) { return t.isOk() ? OK : UNKNOWN_ERROR; } /** * \brief Convert `Status` to `status_t`. This is for legacy binder calls. * * \param[in] t The source `Status`. * \return the corresponding `status_t`. */ // convert: Status -> status_t inline status_t toStatusT(Status const& t) { return static_cast<status_t>(t); } /** * \brief Convert `status_t` to `Status`. * * \param[in] l The source `status_t`. * \return The corresponding `Status`. */ // convert: status_t -> Status inline Status toStatus(status_t l) { return static_cast<Status>(l); } /** * \brief Wrap `native_handle_t*` in `hidl_handle`. * * \param[in] nh The source `native_handle_t*`. * \return The `hidl_handle` that points to \p nh. */ // wrap: native_handle_t* -> hidl_handle inline hidl_handle inHidlHandle(native_handle_t const* nh) { return hidl_handle(nh); } /** * \brief Wrap an `omx_message` and construct the corresponding `Message`. * * \param[out] t The wrapper of type `Message`. * \param[out] nh The native_handle_t referred to by `t->fence`. * \param[in] l The source `omx_message`. * \return `true` if the wrapping is successful; `false` otherwise. * * Upon success, \p nh will be created to hold the file descriptor stored in * `l.fenceFd`, and `t->fence` will point to \p nh. \p nh will need to be * destroyed manually by `native_handle_delete()` when \p t is no longer needed. * * Upon failure, \p nh will not be created and will not need to be deleted. \p t * will be invalid. */ // wrap, omx_message -> Message, native_handle_t* inline bool wrapAs(Message* t, native_handle_t** nh, omx_message const& l) { *nh = native_handle_create_from_fd(l.fenceFd); if (!*nh) { return false; } t->fence = *nh; switch (l.type) { case omx_message::EVENT: t->type = Message::Type::EVENT; t->data.eventData.event = uint32_t(l.u.event_data.event); t->data.eventData.data1 = l.u.event_data.data1; t->data.eventData.data2 = l.u.event_data.data2; t->data.eventData.data3 = l.u.event_data.data3; t->data.eventData.data4 = l.u.event_data.data4; break; case omx_message::EMPTY_BUFFER_DONE: t->type = Message::Type::EMPTY_BUFFER_DONE; t->data.bufferData.buffer = l.u.buffer_data.buffer; break; case omx_message::FILL_BUFFER_DONE: t->type = Message::Type::FILL_BUFFER_DONE; t->data.extendedBufferData.buffer = l.u.extended_buffer_data.buffer; t->data.extendedBufferData.rangeOffset = l.u.extended_buffer_data.range_offset; t->data.extendedBufferData.rangeLength = l.u.extended_buffer_data.range_length; t->data.extendedBufferData.flags = l.u.extended_buffer_data.flags; t->data.extendedBufferData.timestampUs = l.u.extended_buffer_data.timestamp; break; case omx_message::FRAME_RENDERED: t->type = Message::Type::FRAME_RENDERED; t->data.renderData.timestampUs = l.u.render_data.timestamp; t->data.renderData.systemTimeNs = l.u.render_data.nanoTime; break; default: native_handle_delete(*nh); return false; } return true; } /** * \brief Wrap a `Message` inside an `omx_message`. * * \param[out] l The wrapper of type `omx_message`. * \param[in] t The source `Message`. * \return `true` if the wrapping is successful; `false` otherwise. */ // wrap: Message -> omx_message inline bool wrapAs(omx_message* l, Message const& t) { l->fenceFd = native_handle_read_fd(t.fence); switch (t.type) { case Message::Type::EVENT: l->type = omx_message::EVENT; l->u.event_data.event = OMX_EVENTTYPE(t.data.eventData.event); l->u.event_data.data1 = t.data.eventData.data1; l->u.event_data.data2 = t.data.eventData.data2; l->u.event_data.data3 = t.data.eventData.data3; l->u.event_data.data4 = t.data.eventData.data4; break; case Message::Type::EMPTY_BUFFER_DONE: l->type = omx_message::EMPTY_BUFFER_DONE; l->u.buffer_data.buffer = t.data.bufferData.buffer; break; case Message::Type::FILL_BUFFER_DONE: l->type = omx_message::FILL_BUFFER_DONE; l->u.extended_buffer_data.buffer = t.data.extendedBufferData.buffer; l->u.extended_buffer_data.range_offset = t.data.extendedBufferData.rangeOffset; l->u.extended_buffer_data.range_length = t.data.extendedBufferData.rangeLength; l->u.extended_buffer_data.flags = t.data.extendedBufferData.flags; l->u.extended_buffer_data.timestamp = t.data.extendedBufferData.timestampUs; break; case Message::Type::FRAME_RENDERED: l->type = omx_message::FRAME_RENDERED; l->u.render_data.timestamp = t.data.renderData.timestampUs; l->u.render_data.nanoTime = t.data.renderData.systemTimeNs; break; default: return false; } return true; } /** * \brief Similar to `wrapTo(omx_message*, Message const&)`, but the output will * have an extended lifetime. * * \param[out] l The output `omx_message`. * \param[in] t The source `Message`. * \return `true` if the conversion is successful; `false` otherwise. * * This function calls `wrapto()`, then attempts to duplicate the file * descriptor for the fence if it is not `-1`. If duplication fails, `false` * will be returned. */ // convert: Message -> omx_message inline bool convertTo(omx_message* l, Message const& t) { if (!wrapAs(l, t)) { return false; } if (l->fenceFd == -1) { return true; } l->fenceFd = dup(l->fenceFd); return l->fenceFd != -1; } /** * \brief Wrap an `OMXFenceParcelable` inside a `hidl_handle`. * * \param[out] t The wrapper of type `hidl_handle`. * \param[out] nh The native handle created to hold the file descriptor inside * \p l. * \param[in] l The source `OMXFenceParcelable`, which essentially contains one * file descriptor. * \return `true` if \p t and \p nh are successfully created to wrap around \p * l; `false` otherwise. * * On success, \p nh needs to be deleted by the caller with * `native_handle_delete()` after \p t and \p nh are no longer needed. * * On failure, \p nh will not need to be deleted, and \p t will hold an invalid * value. */ // wrap: OMXFenceParcelable -> hidl_handle, native_handle_t* inline bool wrapAs(hidl_handle* t, native_handle_t** nh, OMXFenceParcelable const& l) { *nh = native_handle_create_from_fd(l.get()); if (!*nh) { return false; } *t = *nh; return true; } /** * \brief Wrap a `hidl_handle` inside an `OMXFenceParcelable`. * * \param[out] l The wrapper of type `OMXFenceParcelable`. * \param[in] t The source `hidl_handle`. */ // wrap: hidl_handle -> OMXFenceParcelable inline void wrapAs(OMXFenceParcelable* l, hidl_handle const& t) { l->mFenceFd = native_handle_read_fd(t); } /** * \brief Convert a `hidl_handle` to `OMXFenceParcelable`. If `hidl_handle` * contains file descriptors, the first file descriptor will be duplicated and * stored in the output `OMXFenceParcelable`. * * \param[out] l The output `OMXFenceParcelable`. * \param[in] t The input `hidl_handle`. * \return `false` if \p t contains a valid file descriptor but duplication * fails; `true` otherwise. */ // convert: hidl_handle -> OMXFenceParcelable inline bool convertTo(OMXFenceParcelable* l, hidl_handle const& t) { int fd = native_handle_read_fd(t); if (fd != -1) { fd = dup(fd); if (fd == -1) { return false; } } l->mFenceFd = fd; return true; } /** * \brief Convert `::android::ColorAspects` to `ColorAspects`. * * \param[in] l The source `::android::ColorAspects`. * \return The corresponding `ColorAspects`. */ // convert: ::android::ColorAspects -> ColorAspects inline ColorAspects toHardwareColorAspects(::android::ColorAspects const& l) { return ColorAspects{ static_cast<ColorAspects::Range>(l.mRange), static_cast<ColorAspects::Primaries>(l.mPrimaries), static_cast<ColorAspects::Transfer>(l.mTransfer), static_cast<ColorAspects::MatrixCoeffs>(l.mMatrixCoeffs)}; } /** * \brief Convert `int32_t` to `ColorAspects`. * * \param[in] l The source `int32_t`. * \return The corresponding `ColorAspects`. */ // convert: int32_t -> ColorAspects inline ColorAspects toHardwareColorAspects(int32_t l) { return ColorAspects{ static_cast<ColorAspects::Range>((l >> 24) & 0xFF), static_cast<ColorAspects::Primaries>((l >> 16) & 0xFF), static_cast<ColorAspects::Transfer>(l & 0xFF), static_cast<ColorAspects::MatrixCoeffs>((l >> 8) & 0xFF)}; } /** * \brief Convert `ColorAspects` to `::android::ColorAspects`. * * \param[in] t The source `ColorAspects`. * \return The corresponding `::android::ColorAspects`. */ // convert: ColorAspects -> ::android::ColorAspects inline int32_t toCompactColorAspects(ColorAspects const& t) { return static_cast<int32_t>( (static_cast<uint32_t>(t.range) << 24) | (static_cast<uint32_t>(t.primaries) << 16) | (static_cast<uint32_t>(t.transfer)) | (static_cast<uint32_t>(t.matrixCoeffs) << 8)); } /** * \brief Convert `int32_t` to `Dataspace`. * * \param[in] l The source `int32_t`. * \result The corresponding `Dataspace`. */ // convert: int32_t -> Dataspace inline Dataspace toHardwareDataspace(int32_t l) { return static_cast<Dataspace>(l); } /** * \brief Convert `Dataspace` to `int32_t`. * * \param[in] t The source `Dataspace`. * \result The corresponding `int32_t`. */ // convert: Dataspace -> int32_t inline int32_t toRawDataspace(Dataspace const& t) { return static_cast<int32_t>(t); } /** * \brief Wrap an opaque buffer inside a `hidl_vec<uint8_t>`. * * \param[in] l The pointer to the beginning of the opaque buffer. * \param[in] size The size of the buffer. * \return A `hidl_vec<uint8_t>` that points to the buffer. */ // wrap: void*, size_t -> hidl_vec<uint8_t> inline hidl_vec<uint8_t> inHidlBytes(void const* l, size_t size) { hidl_vec<uint8_t> t; t.setToExternal(static_cast<uint8_t*>(const_cast<void*>(l)), size, false); return t; } /** * \brief Create a `hidl_vec<uint8_t>` that is a copy of an opaque buffer. * * \param[in] l The pointer to the beginning of the opaque buffer. * \param[in] size The size of the buffer. * \return A `hidl_vec<uint8_t>` that is a copy of the input buffer. */ // convert: void*, size_t -> hidl_vec<uint8_t> inline hidl_vec<uint8_t> toHidlBytes(void const* l, size_t size) { hidl_vec<uint8_t> t; t.resize(size); uint8_t const* src = static_cast<uint8_t const*>(l); std::copy(src, src + size, t.data()); return t; } /** * \brief Wrap `GraphicBuffer` in `AnwBuffer`. * * \param[out] t The wrapper of type `AnwBuffer`. * \param[in] l The source `GraphicBuffer`. */ // wrap: GraphicBuffer -> AnwBuffer inline void wrapAs(AnwBuffer* t, GraphicBuffer const& l) { t->attr.width = l.getWidth(); t->attr.height = l.getHeight(); t->attr.stride = l.getStride(); t->attr.format = static_cast<PixelFormat>(l.getPixelFormat()); t->attr.layerCount = l.getLayerCount(); t->attr.usage = l.getUsage(); t->attr.id = l.getId(); t->attr.generationNumber = l.getGenerationNumber(); t->nativeHandle = hidl_handle(l.handle); } /** * \brief Convert `AnwBuffer` to `GraphicBuffer`. * * \param[out] l The destination `GraphicBuffer`. * \param[in] t The source `AnwBuffer`. * * This function will duplicate all file descriptors in \p t. */ // convert: AnwBuffer -> GraphicBuffer // Ref: frameworks/native/libs/ui/GraphicBuffer.cpp: GraphicBuffer::flatten inline bool convertTo(GraphicBuffer* l, AnwBuffer const& t) { native_handle_t* handle = t.nativeHandle == nullptr ? nullptr : native_handle_clone(t.nativeHandle); size_t const numInts = 12 + (handle ? handle->numInts : 0); int32_t* ints = new int32_t[numInts]; size_t numFds = static_cast<size_t>(handle ? handle->numFds : 0); int* fds = new int[numFds]; ints[0] = 'GBFR'; ints[1] = static_cast<int32_t>(t.attr.width); ints[2] = static_cast<int32_t>(t.attr.height); ints[3] = static_cast<int32_t>(t.attr.stride); ints[4] = static_cast<int32_t>(t.attr.format); ints[5] = static_cast<int32_t>(t.attr.layerCount); ints[6] = static_cast<int32_t>(t.attr.usage); ints[7] = static_cast<int32_t>(t.attr.id >> 32); ints[8] = static_cast<int32_t>(t.attr.id & 0xFFFFFFFF); ints[9] = static_cast<int32_t>(t.attr.generationNumber); ints[10] = 0; ints[11] = 0; if (handle) { ints[10] = static_cast<int32_t>(handle->numFds); ints[11] = static_cast<int32_t>(handle->numInts); int* intsStart = handle->data + handle->numFds; std::copy(handle->data, intsStart, fds); std::copy(intsStart, intsStart + handle->numInts, &ints[12]); } void const* constBuffer = static_cast<void const*>(ints); size_t size = numInts * sizeof(int32_t); int const* constFds = static_cast<int const*>(fds); status_t status = l->unflatten(constBuffer, size, constFds, numFds); delete [] fds; delete [] ints; native_handle_delete(handle); return status == NO_ERROR; } /** * \brief Wrap `OMXBuffer` in `CodecBuffer`. * * \param[out] t The wrapper of type `CodecBuffer`. * \param[in] l The source `OMXBuffer`. * \return `true` if the wrapping is successful; `false` otherwise. */ // wrap: OMXBuffer -> CodecBuffer inline bool wrapAs(CodecBuffer* t, OMXBuffer const& l) { t->sharedMemory = hidl_memory(); t->nativeHandle = hidl_handle(); switch (l.mBufferType) { case OMXBuffer::kBufferTypeInvalid: { t->type = CodecBuffer::Type::INVALID; return true; } case OMXBuffer::kBufferTypePreset: { t->type = CodecBuffer::Type::PRESET; t->attr.preset.rangeLength = static_cast<uint32_t>(l.mRangeLength); t->attr.preset.rangeOffset = static_cast<uint32_t>(l.mRangeOffset); return true; } case OMXBuffer::kBufferTypeHidlMemory: { t->type = CodecBuffer::Type::SHARED_MEM; t->sharedMemory = l.mHidlMemory; return true; } case OMXBuffer::kBufferTypeSharedMem: { // This is not supported. return false; } case OMXBuffer::kBufferTypeANWBuffer: { t->type = CodecBuffer::Type::ANW_BUFFER; if (l.mGraphicBuffer == nullptr) { t->attr.anwBuffer.width = 0; t->attr.anwBuffer.height = 0; t->attr.anwBuffer.stride = 0; t->attr.anwBuffer.format = static_cast<PixelFormat>(1); t->attr.anwBuffer.layerCount = 0; t->attr.anwBuffer.usage = 0; return true; } t->attr.anwBuffer.width = l.mGraphicBuffer->getWidth(); t->attr.anwBuffer.height = l.mGraphicBuffer->getHeight(); t->attr.anwBuffer.stride = l.mGraphicBuffer->getStride(); t->attr.anwBuffer.format = static_cast<PixelFormat>( l.mGraphicBuffer->getPixelFormat()); t->attr.anwBuffer.layerCount = l.mGraphicBuffer->getLayerCount(); t->attr.anwBuffer.usage = l.mGraphicBuffer->getUsage(); t->nativeHandle = l.mGraphicBuffer->handle; return true; } case OMXBuffer::kBufferTypeNativeHandle: { t->type = CodecBuffer::Type::NATIVE_HANDLE; t->nativeHandle = l.mNativeHandle->handle(); return true; } } return false; } /** * \brief Convert `CodecBuffer` to `OMXBuffer`. * * \param[out] l The destination `OMXBuffer`. * \param[in] t The source `CodecBuffer`. * \return `true` if successful; `false` otherwise. */ // convert: CodecBuffer -> OMXBuffer inline bool convertTo(OMXBuffer* l, CodecBuffer const& t) { switch (t.type) { case CodecBuffer::Type::INVALID: { *l = OMXBuffer(); return true; } case CodecBuffer::Type::PRESET: { *l = OMXBuffer( t.attr.preset.rangeOffset, t.attr.preset.rangeLength); return true; } case CodecBuffer::Type::SHARED_MEM: { *l = OMXBuffer(t.sharedMemory); return true; } case CodecBuffer::Type::ANW_BUFFER: { if (t.nativeHandle.getNativeHandle() == nullptr) { *l = OMXBuffer(sp<GraphicBuffer>(nullptr)); return true; } AnwBuffer anwBuffer; anwBuffer.nativeHandle = t.nativeHandle; anwBuffer.attr = t.attr.anwBuffer; sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(); if (!convertTo(graphicBuffer.get(), anwBuffer)) { return false; } *l = OMXBuffer(graphicBuffer); return true; } case CodecBuffer::Type::NATIVE_HANDLE: { *l = OMXBuffer(NativeHandle::create( native_handle_clone(t.nativeHandle), true)); return true; } } return false; } /** * \brief Convert `IOMX::ComponentInfo` to `IOmx::ComponentInfo`. * * \param[out] t The destination `IOmx::ComponentInfo`. * \param[in] l The source `IOMX::ComponentInfo`. */ // convert: IOMX::ComponentInfo -> IOmx::ComponentInfo inline bool convertTo(IOmx::ComponentInfo* t, IOMX::ComponentInfo const& l) { t->mName = l.mName.string(); t->mRoles.resize(l.mRoles.size()); size_t i = 0; for (auto& role : l.mRoles) { t->mRoles[i++] = role.string(); } return true; } /** * \brief Convert `IOmx::ComponentInfo` to `IOMX::ComponentInfo`. * * \param[out] l The destination `IOMX::ComponentInfo`. * \param[in] t The source `IOmx::ComponentInfo`. */ // convert: IOmx::ComponentInfo -> IOMX::ComponentInfo inline bool convertTo(IOMX::ComponentInfo* l, IOmx::ComponentInfo const& t) { l->mName = t.mName.c_str(); l->mRoles.clear(); for (size_t i = 0; i < t.mRoles.size(); ++i) { l->mRoles.push_back(String8(t.mRoles[i].c_str())); } return true; } /** * \brief Convert `OMX_BOOL` to `bool`. * * \param[in] l The source `OMX_BOOL`. * \return The destination `bool`. */ // convert: OMX_BOOL -> bool inline bool toRawBool(OMX_BOOL l) { return l == OMX_FALSE ? false : true; } /** * \brief Convert `bool` to `OMX_BOOL`. * * \param[in] t The source `bool`. * \return The destination `OMX_BOOL`. */ // convert: bool -> OMX_BOOL inline OMX_BOOL toEnumBool(bool t) { return t ? OMX_TRUE : OMX_FALSE; } /** * \brief Convert `OMX_COMMANDTYPE` to `uint32_t`. * * \param[in] l The source `OMX_COMMANDTYPE`. * \return The underlying value of type `uint32_t`. * * `OMX_COMMANDTYPE` is an enum type whose underlying type is `uint32_t`. */ // convert: OMX_COMMANDTYPE -> uint32_t inline uint32_t toRawCommandType(OMX_COMMANDTYPE l) { return static_cast<uint32_t>(l); } /** * \brief Convert `uint32_t` to `OMX_COMMANDTYPE`. * * \param[in] t The source `uint32_t`. * \return The corresponding enum value of type `OMX_COMMANDTYPE`. * * `OMX_COMMANDTYPE` is an enum type whose underlying type is `uint32_t`. */ // convert: uint32_t -> OMX_COMMANDTYPE inline OMX_COMMANDTYPE toEnumCommandType(uint32_t t) { return static_cast<OMX_COMMANDTYPE>(t); } /** * \brief Convert `OMX_INDEXTYPE` to `uint32_t`. * * \param[in] l The source `OMX_INDEXTYPE`. * \return The underlying value of type `uint32_t`. * * `OMX_INDEXTYPE` is an enum type whose underlying type is `uint32_t`. */ // convert: OMX_INDEXTYPE -> uint32_t inline uint32_t toRawIndexType(OMX_INDEXTYPE l) { return static_cast<uint32_t>(l); } /** * \brief Convert `uint32_t` to `OMX_INDEXTYPE`. * * \param[in] t The source `uint32_t`. * \return The corresponding enum value of type `OMX_INDEXTYPE`. * * `OMX_INDEXTYPE` is an enum type whose underlying type is `uint32_t`. */ // convert: uint32_t -> OMX_INDEXTYPE inline OMX_INDEXTYPE toEnumIndexType(uint32_t t) { return static_cast<OMX_INDEXTYPE>(t); } /** * \brief Convert `IOMX::PortMode` to `PortMode`. * * \param[in] l The source `IOMX::PortMode`. * \return The destination `PortMode`. */ // convert: IOMX::PortMode -> PortMode inline PortMode toHardwarePortMode(IOMX::PortMode l) { return static_cast<PortMode>(l); } /** * \brief Convert `PortMode` to `IOMX::PortMode`. * * \param[in] t The source `PortMode`. * \return The destination `IOMX::PortMode`. */ // convert: PortMode -> IOMX::PortMode inline IOMX::PortMode toIOMXPortMode(PortMode t) { return static_cast<IOMX::PortMode>(t); } /** * \brief Convert `OMX_TICKS` to `uint64_t`. * * \param[in] l The source `OMX_TICKS`. * \return The destination `uint64_t`. */ // convert: OMX_TICKS -> uint64_t inline uint64_t toRawTicks(OMX_TICKS l) { #ifndef OMX_SKIP64BIT return static_cast<uint64_t>(l); #else return static_cast<uint64_t>(l.nLowPart) | static_cast<uint64_t>(l.nHighPart << 32); #endif } /** * \brief Convert `uint64_t` to `OMX_TICKS`. * * \param[in] l The source `uint64_t`. * \return The destination `OMX_TICKS`. */ // convert: uint64_t -> OMX_TICKS inline OMX_TICKS toOMXTicks(uint64_t t) { #ifndef OMX_SKIP64BIT return static_cast<OMX_TICKS>(t); #else return OMX_TICKS{ static_cast<uint32_t>(t & 0xFFFFFFFF), static_cast<uint32_t>(t >> 32)}; #endif } } // namespace utils } // namespace V1_0 } // namespace omx } // namespace media } // namespace hardware } // namespace android #endif // ANDROID_HARDWARE_MEDIA_OMX_V1_0__CONVERSION_H