Pawin Vongmasa | eeac97b | 2017-01-18 05:03:07 -0800 | [diff] [blame] | 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 | |
Pawin Vongmasa | 0d3a5ed | 2017-02-22 03:19:35 -0800 | [diff] [blame] | 20 | #include <vector> |
| 21 | #include <list> |
| 22 | |
| 23 | #include <unistd.h> |
| 24 | |
Pawin Vongmasa | eeac97b | 2017-01-18 05:03:07 -0800 | [diff] [blame] | 25 | #include <hidl/MQDescriptor.h> |
| 26 | #include <hidl/Status.h> |
| 27 | #include <hidlmemory/mapping.h> |
Pawin Vongmasa | eeac97b | 2017-01-18 05:03:07 -0800 | [diff] [blame] | 28 | |
| 29 | #include <binder/Binder.h> |
| 30 | #include <binder/Status.h> |
| 31 | #include <ui/FenceTime.h> |
Pawin Vongmasa | eeac97b | 2017-01-18 05:03:07 -0800 | [diff] [blame] | 32 | #include <cutils/native_handle.h> |
Pawin Vongmasa | eeac97b | 2017-01-18 05:03:07 -0800 | [diff] [blame] | 33 | |
Pawin Vongmasa | 04563aa | 2017-03-09 07:02:01 -0800 | [diff] [blame^] | 34 | #include <ui/GraphicBuffer.h> |
Pawin Vongmasa | ac7d412 | 2017-03-01 05:48:42 -0800 | [diff] [blame] | 35 | #include <media/OMXFenceParcelable.h> |
Pawin Vongmasa | 0d3a5ed | 2017-02-22 03:19:35 -0800 | [diff] [blame] | 36 | #include <media/OMXBuffer.h> |
Pawin Vongmasa | ac7d412 | 2017-03-01 05:48:42 -0800 | [diff] [blame] | 37 | #include <media/hardware/VideoAPI.h> |
Pawin Vongmasa | eeac97b | 2017-01-18 05:03:07 -0800 | [diff] [blame] | 38 | |
Pawin Vongmasa | 0d3a5ed | 2017-02-22 03:19:35 -0800 | [diff] [blame] | 39 | #include <android/hidl/memory/1.0/IMemory.h> |
Pawin Vongmasa | eeac97b | 2017-01-18 05:03:07 -0800 | [diff] [blame] | 40 | #include <android/hardware/media/omx/1.0/types.h> |
| 41 | #include <android/hardware/media/omx/1.0/IOmx.h> |
| 42 | #include <android/hardware/media/omx/1.0/IOmxNode.h> |
Pawin Vongmasa | eeac97b | 2017-01-18 05:03:07 -0800 | [diff] [blame] | 43 | #include <android/hardware/media/omx/1.0/IOmxBufferSource.h> |
| 44 | #include <android/hardware/media/omx/1.0/IOmxObserver.h> |
Pawin Vongmasa | eeac97b | 2017-01-18 05:03:07 -0800 | [diff] [blame] | 45 | #include <android/hardware/media/omx/1.0/IGraphicBufferSource.h> |
| 46 | |
Pawin Vongmasa | 0d3a5ed | 2017-02-22 03:19:35 -0800 | [diff] [blame] | 47 | #include <android/IGraphicBufferSource.h> |
| 48 | #include <android/IOMXBufferSource.h> |
| 49 | |
Pawin Vongmasa | eeac97b | 2017-01-18 05:03:07 -0800 | [diff] [blame] | 50 | namespace android { |
| 51 | namespace hardware { |
| 52 | namespace media { |
| 53 | namespace omx { |
| 54 | namespace V1_0 { |
| 55 | namespace utils { |
| 56 | |
| 57 | using ::android::hardware::hidl_array; |
| 58 | using ::android::hardware::hidl_string; |
| 59 | using ::android::hardware::hidl_vec; |
| 60 | using ::android::hardware::hidl_handle; |
| 61 | using ::android::hardware::Return; |
| 62 | using ::android::hardware::Void; |
| 63 | using ::android::sp; |
| 64 | |
| 65 | using ::android::String8; |
| 66 | using ::android::OMXFenceParcelable; |
| 67 | |
| 68 | using ::android::hardware::media::omx::V1_0::Message; |
| 69 | using ::android::omx_message; |
| 70 | |
| 71 | using ::android::hardware::media::omx::V1_0::ColorAspects; |
| 72 | using ::android::hardware::media::V1_0::Rect; |
| 73 | using ::android::hardware::media::V1_0::Region; |
| 74 | |
| 75 | using ::android::hardware::graphics::common::V1_0::Dataspace; |
| 76 | |
| 77 | using ::android::hardware::graphics::common::V1_0::PixelFormat; |
| 78 | |
| 79 | using ::android::OMXBuffer; |
| 80 | |
| 81 | using ::android::hardware::media::V1_0::AnwBuffer; |
| 82 | using ::android::GraphicBuffer; |
| 83 | |
| 84 | using ::android::hardware::media::omx::V1_0::IOmx; |
| 85 | using ::android::IOMX; |
| 86 | |
| 87 | using ::android::hardware::media::omx::V1_0::IOmxNode; |
| 88 | using ::android::IOMXNode; |
| 89 | |
| 90 | using ::android::hardware::media::omx::V1_0::IOmxObserver; |
| 91 | using ::android::IOMXObserver; |
| 92 | |
| 93 | using ::android::hardware::media::omx::V1_0::IOmxBufferSource; |
| 94 | using ::android::IOMXBufferSource; |
| 95 | |
Pawin Vongmasa | eeac97b | 2017-01-18 05:03:07 -0800 | [diff] [blame] | 96 | // native_handle_t helper functions. |
| 97 | |
| 98 | /** |
| 99 | * \brief Take an fd and create a native handle containing only the given fd. |
| 100 | * The created handle will need to be deleted manually with |
| 101 | * `native_handle_delete()`. |
| 102 | * |
| 103 | * \param[in] fd The source file descriptor (of type `int`). |
| 104 | * \return The create `native_handle_t*` that contains the given \p fd. If the |
| 105 | * supplied \p fd is negative, the created native handle will contain no file |
| 106 | * descriptors. |
| 107 | * |
| 108 | * If the native handle cannot be created, the return value will be |
| 109 | * `nullptr`. |
| 110 | * |
| 111 | * This function does not duplicate the file descriptor. |
| 112 | */ |
| 113 | inline native_handle_t* native_handle_create_from_fd(int fd) { |
| 114 | if (fd < 0) { |
| 115 | return native_handle_create(0, 0); |
| 116 | } |
| 117 | native_handle_t* nh = native_handle_create(1, 0); |
| 118 | if (nh == nullptr) { |
| 119 | return nullptr; |
| 120 | } |
| 121 | nh->data[0] = fd; |
| 122 | return nh; |
| 123 | } |
| 124 | |
| 125 | /** |
| 126 | * \brief Extract a file descriptor from a native handle. |
| 127 | * |
| 128 | * \param[in] nh The source `native_handle_t*`. |
| 129 | * \param[in] index The index of the file descriptor in \p nh to read from. This |
| 130 | * input has the default value of `0`. |
| 131 | * \return The `index`-th file descriptor in \p nh. If \p nh does not have |
| 132 | * enough file descriptors, the returned value will be `-1`. |
| 133 | * |
| 134 | * This function does not duplicate the file descriptor. |
| 135 | */ |
| 136 | inline int native_handle_read_fd(native_handle_t const* nh, int index = 0) { |
| 137 | return ((nh == nullptr) || (nh->numFds == 0) || |
| 138 | (nh->numFds <= index) || (index < 0)) ? |
| 139 | -1 : nh->data[index]; |
| 140 | } |
| 141 | |
| 142 | /** |
| 143 | * Conversion functions |
| 144 | * ==================== |
| 145 | * |
| 146 | * There are two main directions of conversion: |
| 147 | * - `inTargetType(...)`: Create a wrapper whose lifetime depends on the |
| 148 | * input. The wrapper has type `TargetType`. |
| 149 | * - `toTargetType(...)`: Create a standalone object of type `TargetType` that |
| 150 | * corresponds to the input. The lifetime of the output does not depend on the |
| 151 | * lifetime of the input. |
| 152 | * - `wrapIn(TargetType*, ...)`: Same as `inTargetType()`, but for `TargetType` |
| 153 | * that cannot be copied and/or moved efficiently, or when there are multiple |
| 154 | * output arguments. |
| 155 | * - `convertTo(TargetType*, ...)`: Same as `toTargetType()`, but for |
| 156 | * `TargetType` that cannot be copied and/or moved efficiently, or when there |
| 157 | * are multiple output arguments. |
| 158 | * |
| 159 | * `wrapIn()` and `convertTo()` functions will take output arguments before |
| 160 | * input arguments. Some of these functions might return a value to indicate |
| 161 | * success or error. |
| 162 | * |
| 163 | * In converting or wrapping something as a Treble type that contains a |
| 164 | * `hidl_handle`, `native_handle_t*` will need to be created and returned as |
| 165 | * an additional output argument, hence only `wrapIn()` or `convertTo()` would |
| 166 | * be available. The caller must call `native_handle_delete()` to deallocate the |
| 167 | * returned native handle when it is no longer needed. |
| 168 | * |
| 169 | * For types that contain file descriptors, `inTargetType()` and `wrapAs()` do |
| 170 | * not perform duplication of file descriptors, while `toTargetType()` and |
| 171 | * `convertTo()` do. |
| 172 | */ |
| 173 | |
| 174 | /** |
Pawin Vongmasa | eeac97b | 2017-01-18 05:03:07 -0800 | [diff] [blame] | 175 | * \brief Convert `Return<void>` to `binder::Status`. |
| 176 | * |
| 177 | * \param[in] t The source `Return<void>`. |
| 178 | * \return The corresponding `binder::Status`. |
| 179 | */ |
| 180 | // convert: Return<void> -> ::android::binder::Status |
| 181 | inline ::android::binder::Status toBinderStatus( |
| 182 | Return<void> const& t) { |
| 183 | return ::android::binder::Status::fromExceptionCode( |
| 184 | t.isOk() ? OK : UNKNOWN_ERROR, |
| 185 | t.description().c_str()); |
| 186 | } |
| 187 | |
| 188 | /** |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 189 | * \brief Convert `Return<Status>` to `binder::Status`. |
| 190 | * |
| 191 | * \param[in] t The source `Return<Status>`. |
| 192 | * \return The corresponding `binder::Status`. |
| 193 | */ |
| 194 | // convert: Return<Status> -> ::android::binder::Status |
| 195 | inline ::android::binder::Status toBinderStatus( |
| 196 | Return<Status> const& t) { |
| 197 | return ::android::binder::Status::fromStatusT( |
| 198 | t.isOk() ? static_cast<status_t>(static_cast<Status>(t)) : UNKNOWN_ERROR); |
| 199 | } |
| 200 | |
| 201 | /** |
Pawin Vongmasa | eeac97b | 2017-01-18 05:03:07 -0800 | [diff] [blame] | 202 | * \brief Convert `Return<Status>` to `status_t`. This is for legacy binder |
| 203 | * calls. |
| 204 | * |
| 205 | * \param[in] t The source `Return<Status>`. |
| 206 | * \return The corresponding `status_t`. |
| 207 | * |
| 208 | * This function first check if \p t has a transport error. If it does, then the |
| 209 | * return value is the transport error code. Otherwise, the return value is |
| 210 | * converted from `Status` contained inside \p t. |
| 211 | * |
| 212 | * Note: |
| 213 | * - This `Status` is omx-specific. It is defined in `types.hal`. |
| 214 | * - The name of this function is not `convert`. |
| 215 | */ |
| 216 | // convert: Status -> status_t |
| 217 | inline status_t toStatusT(Return<Status> const& t) { |
| 218 | return t.isOk() ? static_cast<status_t>(static_cast<Status>(t)) : UNKNOWN_ERROR; |
| 219 | } |
| 220 | |
| 221 | /** |
| 222 | * \brief Convert `Return<void>` to `status_t`. This is for legacy binder calls. |
| 223 | * |
| 224 | * \param[in] t The source `Return<void>`. |
| 225 | * \return The corresponding `status_t`. |
| 226 | */ |
| 227 | // convert: Return<void> -> status_t |
| 228 | inline status_t toStatusT(Return<void> const& t) { |
| 229 | return t.isOk() ? OK : UNKNOWN_ERROR; |
| 230 | } |
| 231 | |
| 232 | /** |
| 233 | * \brief Convert `Status` to `status_t`. This is for legacy binder calls. |
| 234 | * |
| 235 | * \param[in] t The source `Status`. |
| 236 | * \return the corresponding `status_t`. |
| 237 | */ |
| 238 | // convert: Status -> status_t |
| 239 | inline status_t toStatusT(Status const& t) { |
| 240 | return static_cast<status_t>(t); |
| 241 | } |
| 242 | |
| 243 | /** |
| 244 | * \brief Convert `status_t` to `Status`. |
| 245 | * |
| 246 | * \param[in] l The source `status_t`. |
| 247 | * \return The corresponding `Status`. |
| 248 | */ |
| 249 | // convert: status_t -> Status |
| 250 | inline Status toStatus(status_t l) { |
| 251 | return static_cast<Status>(l); |
| 252 | } |
| 253 | |
| 254 | /** |
| 255 | * \brief Wrap `native_handle_t*` in `hidl_handle`. |
| 256 | * |
| 257 | * \param[in] nh The source `native_handle_t*`. |
| 258 | * \return The `hidl_handle` that points to \p nh. |
| 259 | */ |
| 260 | // wrap: native_handle_t* -> hidl_handle |
| 261 | inline hidl_handle inHidlHandle(native_handle_t const* nh) { |
| 262 | return hidl_handle(nh); |
| 263 | } |
| 264 | |
| 265 | /** |
| 266 | * \brief Wrap an `omx_message` and construct the corresponding `Message`. |
| 267 | * |
| 268 | * \param[out] t The wrapper of type `Message`. |
| 269 | * \param[out] nh The native_handle_t referred to by `t->fence`. |
| 270 | * \param[in] l The source `omx_message`. |
| 271 | * \return `true` if the wrapping is successful; `false` otherwise. |
| 272 | * |
| 273 | * Upon success, \p nh will be created to hold the file descriptor stored in |
| 274 | * `l.fenceFd`, and `t->fence` will point to \p nh. \p nh will need to be |
| 275 | * destroyed manually by `native_handle_delete()` when \p t is no longer needed. |
| 276 | * |
| 277 | * Upon failure, \p nh will not be created and will not need to be deleted. \p t |
| 278 | * will be invalid. |
| 279 | */ |
| 280 | // wrap, omx_message -> Message, native_handle_t* |
| 281 | inline bool wrapAs(Message* t, native_handle_t** nh, omx_message const& l) { |
| 282 | *nh = native_handle_create_from_fd(l.fenceFd); |
| 283 | if (!*nh) { |
| 284 | return false; |
| 285 | } |
Pawin Vongmasa | 8ff4018 | 2017-02-07 02:22:34 -0800 | [diff] [blame] | 286 | t->fence = *nh; |
Pawin Vongmasa | eeac97b | 2017-01-18 05:03:07 -0800 | [diff] [blame] | 287 | switch (l.type) { |
| 288 | case omx_message::EVENT: |
| 289 | t->type = Message::Type::EVENT; |
Pawin Vongmasa | 8a21c01 | 2016-12-27 04:30:54 +0700 | [diff] [blame] | 290 | t->data.eventData.event = uint32_t(l.u.event_data.event); |
Pawin Vongmasa | eeac97b | 2017-01-18 05:03:07 -0800 | [diff] [blame] | 291 | t->data.eventData.data1 = l.u.event_data.data1; |
| 292 | t->data.eventData.data2 = l.u.event_data.data2; |
| 293 | t->data.eventData.data3 = l.u.event_data.data3; |
| 294 | t->data.eventData.data4 = l.u.event_data.data4; |
| 295 | break; |
| 296 | case omx_message::EMPTY_BUFFER_DONE: |
| 297 | t->type = Message::Type::EMPTY_BUFFER_DONE; |
| 298 | t->data.bufferData.buffer = l.u.buffer_data.buffer; |
| 299 | break; |
| 300 | case omx_message::FILL_BUFFER_DONE: |
| 301 | t->type = Message::Type::FILL_BUFFER_DONE; |
| 302 | t->data.extendedBufferData.buffer = l.u.extended_buffer_data.buffer; |
| 303 | t->data.extendedBufferData.rangeOffset = |
| 304 | l.u.extended_buffer_data.range_offset; |
| 305 | t->data.extendedBufferData.rangeLength = |
| 306 | l.u.extended_buffer_data.range_length; |
| 307 | t->data.extendedBufferData.flags = l.u.extended_buffer_data.flags; |
| 308 | t->data.extendedBufferData.timestampUs = |
| 309 | l.u.extended_buffer_data.timestamp; |
| 310 | break; |
| 311 | case omx_message::FRAME_RENDERED: |
| 312 | t->type = Message::Type::FRAME_RENDERED; |
| 313 | t->data.renderData.timestampUs = l.u.render_data.timestamp; |
| 314 | t->data.renderData.systemTimeNs = l.u.render_data.nanoTime; |
| 315 | break; |
| 316 | default: |
| 317 | native_handle_delete(*nh); |
| 318 | return false; |
| 319 | } |
| 320 | return true; |
| 321 | } |
| 322 | |
| 323 | /** |
| 324 | * \brief Wrap a `Message` inside an `omx_message`. |
| 325 | * |
| 326 | * \param[out] l The wrapper of type `omx_message`. |
| 327 | * \param[in] t The source `Message`. |
| 328 | * \return `true` if the wrapping is successful; `false` otherwise. |
| 329 | */ |
| 330 | // wrap: Message -> omx_message |
| 331 | inline bool wrapAs(omx_message* l, Message const& t) { |
| 332 | l->fenceFd = native_handle_read_fd(t.fence); |
| 333 | switch (t.type) { |
| 334 | case Message::Type::EVENT: |
| 335 | l->type = omx_message::EVENT; |
Pawin Vongmasa | 8a21c01 | 2016-12-27 04:30:54 +0700 | [diff] [blame] | 336 | l->u.event_data.event = OMX_EVENTTYPE(t.data.eventData.event); |
Pawin Vongmasa | eeac97b | 2017-01-18 05:03:07 -0800 | [diff] [blame] | 337 | l->u.event_data.data1 = t.data.eventData.data1; |
| 338 | l->u.event_data.data2 = t.data.eventData.data2; |
| 339 | l->u.event_data.data3 = t.data.eventData.data3; |
| 340 | l->u.event_data.data4 = t.data.eventData.data4; |
| 341 | break; |
| 342 | case Message::Type::EMPTY_BUFFER_DONE: |
| 343 | l->type = omx_message::EMPTY_BUFFER_DONE; |
| 344 | l->u.buffer_data.buffer = t.data.bufferData.buffer; |
| 345 | break; |
| 346 | case Message::Type::FILL_BUFFER_DONE: |
| 347 | l->type = omx_message::FILL_BUFFER_DONE; |
| 348 | l->u.extended_buffer_data.buffer = t.data.extendedBufferData.buffer; |
| 349 | l->u.extended_buffer_data.range_offset = |
| 350 | t.data.extendedBufferData.rangeOffset; |
| 351 | l->u.extended_buffer_data.range_length = |
| 352 | t.data.extendedBufferData.rangeLength; |
| 353 | l->u.extended_buffer_data.flags = t.data.extendedBufferData.flags; |
| 354 | l->u.extended_buffer_data.timestamp = |
| 355 | t.data.extendedBufferData.timestampUs; |
| 356 | break; |
| 357 | case Message::Type::FRAME_RENDERED: |
| 358 | l->type = omx_message::FRAME_RENDERED; |
| 359 | l->u.render_data.timestamp = t.data.renderData.timestampUs; |
| 360 | l->u.render_data.nanoTime = t.data.renderData.systemTimeNs; |
| 361 | break; |
| 362 | default: |
| 363 | return false; |
| 364 | } |
| 365 | return true; |
| 366 | } |
| 367 | |
| 368 | /** |
| 369 | * \brief Similar to `wrapTo(omx_message*, Message const&)`, but the output will |
| 370 | * have an extended lifetime. |
| 371 | * |
| 372 | * \param[out] l The output `omx_message`. |
| 373 | * \param[in] t The source `Message`. |
| 374 | * \return `true` if the conversion is successful; `false` otherwise. |
| 375 | * |
| 376 | * This function calls `wrapto()`, then attempts to duplicate the file |
| 377 | * descriptor for the fence if it is not `-1`. If duplication fails, `false` |
| 378 | * will be returned. |
| 379 | */ |
| 380 | // convert: Message -> omx_message |
| 381 | inline bool convertTo(omx_message* l, Message const& t) { |
| 382 | if (!wrapAs(l, t)) { |
| 383 | return false; |
| 384 | } |
| 385 | if (l->fenceFd == -1) { |
| 386 | return true; |
| 387 | } |
| 388 | l->fenceFd = dup(l->fenceFd); |
| 389 | return l->fenceFd != -1; |
| 390 | } |
| 391 | |
| 392 | /** |
| 393 | * \brief Wrap an `OMXFenceParcelable` inside a `hidl_handle`. |
| 394 | * |
| 395 | * \param[out] t The wrapper of type `hidl_handle`. |
| 396 | * \param[out] nh The native handle created to hold the file descriptor inside |
| 397 | * \p l. |
| 398 | * \param[in] l The source `OMXFenceParcelable`, which essentially contains one |
| 399 | * file descriptor. |
| 400 | * \return `true` if \p t and \p nh are successfully created to wrap around \p |
| 401 | * l; `false` otherwise. |
| 402 | * |
| 403 | * On success, \p nh needs to be deleted by the caller with |
| 404 | * `native_handle_delete()` after \p t and \p nh are no longer needed. |
| 405 | * |
| 406 | * On failure, \p nh will not need to be deleted, and \p t will hold an invalid |
| 407 | * value. |
| 408 | */ |
| 409 | // wrap: OMXFenceParcelable -> hidl_handle, native_handle_t* |
| 410 | inline bool wrapAs(hidl_handle* t, native_handle_t** nh, |
| 411 | OMXFenceParcelable const& l) { |
| 412 | *nh = native_handle_create_from_fd(l.get()); |
| 413 | if (!*nh) { |
| 414 | return false; |
| 415 | } |
| 416 | *t = *nh; |
| 417 | return true; |
| 418 | } |
| 419 | |
| 420 | /** |
| 421 | * \brief Wrap a `hidl_handle` inside an `OMXFenceParcelable`. |
| 422 | * |
| 423 | * \param[out] l The wrapper of type `OMXFenceParcelable`. |
| 424 | * \param[in] t The source `hidl_handle`. |
| 425 | */ |
| 426 | // wrap: hidl_handle -> OMXFenceParcelable |
| 427 | inline void wrapAs(OMXFenceParcelable* l, hidl_handle const& t) { |
| 428 | l->mFenceFd = native_handle_read_fd(t); |
| 429 | } |
| 430 | |
| 431 | /** |
| 432 | * \brief Convert a `hidl_handle` to `OMXFenceParcelable`. If `hidl_handle` |
| 433 | * contains file descriptors, the first file descriptor will be duplicated and |
| 434 | * stored in the output `OMXFenceParcelable`. |
| 435 | * |
| 436 | * \param[out] l The output `OMXFenceParcelable`. |
| 437 | * \param[in] t The input `hidl_handle`. |
| 438 | * \return `false` if \p t contains a valid file descriptor but duplication |
| 439 | * fails; `true` otherwise. |
| 440 | */ |
| 441 | // convert: hidl_handle -> OMXFenceParcelable |
| 442 | inline bool convertTo(OMXFenceParcelable* l, hidl_handle const& t) { |
| 443 | int fd = native_handle_read_fd(t); |
| 444 | if (fd != -1) { |
| 445 | fd = dup(fd); |
| 446 | if (fd == -1) { |
| 447 | return false; |
| 448 | } |
| 449 | } |
| 450 | l->mFenceFd = fd; |
| 451 | return true; |
| 452 | } |
| 453 | |
| 454 | /** |
| 455 | * \brief Convert `::android::ColorAspects` to `ColorAspects`. |
| 456 | * |
| 457 | * \param[in] l The source `::android::ColorAspects`. |
| 458 | * \return The corresponding `ColorAspects`. |
| 459 | */ |
| 460 | // convert: ::android::ColorAspects -> ColorAspects |
| 461 | inline ColorAspects toHardwareColorAspects(::android::ColorAspects const& l) { |
| 462 | return ColorAspects{ |
| 463 | static_cast<ColorAspects::Range>(l.mRange), |
| 464 | static_cast<ColorAspects::Primaries>(l.mPrimaries), |
| 465 | static_cast<ColorAspects::Transfer>(l.mTransfer), |
| 466 | static_cast<ColorAspects::MatrixCoeffs>(l.mMatrixCoeffs)}; |
| 467 | } |
| 468 | |
| 469 | /** |
| 470 | * \brief Convert `int32_t` to `ColorAspects`. |
| 471 | * |
| 472 | * \param[in] l The source `int32_t`. |
| 473 | * \return The corresponding `ColorAspects`. |
| 474 | */ |
| 475 | // convert: int32_t -> ColorAspects |
| 476 | inline ColorAspects toHardwareColorAspects(int32_t l) { |
| 477 | return ColorAspects{ |
| 478 | static_cast<ColorAspects::Range>((l >> 24) & 0xFF), |
| 479 | static_cast<ColorAspects::Primaries>((l >> 16) & 0xFF), |
| 480 | static_cast<ColorAspects::Transfer>(l & 0xFF), |
| 481 | static_cast<ColorAspects::MatrixCoeffs>((l >> 8) & 0xFF)}; |
| 482 | } |
| 483 | |
| 484 | /** |
| 485 | * \brief Convert `ColorAspects` to `::android::ColorAspects`. |
| 486 | * |
| 487 | * \param[in] t The source `ColorAspects`. |
| 488 | * \return The corresponding `::android::ColorAspects`. |
| 489 | */ |
| 490 | // convert: ColorAspects -> ::android::ColorAspects |
| 491 | inline int32_t toCompactColorAspects(ColorAspects const& t) { |
| 492 | return static_cast<int32_t>( |
| 493 | (static_cast<uint32_t>(t.range) << 24) | |
| 494 | (static_cast<uint32_t>(t.primaries) << 16) | |
| 495 | (static_cast<uint32_t>(t.transfer)) | |
| 496 | (static_cast<uint32_t>(t.matrixCoeffs) << 8)); |
| 497 | } |
| 498 | |
| 499 | /** |
| 500 | * \brief Convert `int32_t` to `Dataspace`. |
| 501 | * |
| 502 | * \param[in] l The source `int32_t`. |
| 503 | * \result The corresponding `Dataspace`. |
| 504 | */ |
| 505 | // convert: int32_t -> Dataspace |
| 506 | inline Dataspace toHardwareDataspace(int32_t l) { |
| 507 | return static_cast<Dataspace>(l); |
| 508 | } |
| 509 | |
| 510 | /** |
| 511 | * \brief Convert `Dataspace` to `int32_t`. |
| 512 | * |
| 513 | * \param[in] t The source `Dataspace`. |
| 514 | * \result The corresponding `int32_t`. |
| 515 | */ |
| 516 | // convert: Dataspace -> int32_t |
| 517 | inline int32_t toRawDataspace(Dataspace const& t) { |
| 518 | return static_cast<int32_t>(t); |
| 519 | } |
| 520 | |
| 521 | /** |
| 522 | * \brief Wrap an opaque buffer inside a `hidl_vec<uint8_t>`. |
| 523 | * |
| 524 | * \param[in] l The pointer to the beginning of the opaque buffer. |
| 525 | * \param[in] size The size of the buffer. |
| 526 | * \return A `hidl_vec<uint8_t>` that points to the buffer. |
| 527 | */ |
| 528 | // wrap: void*, size_t -> hidl_vec<uint8_t> |
| 529 | inline hidl_vec<uint8_t> inHidlBytes(void const* l, size_t size) { |
| 530 | hidl_vec<uint8_t> t; |
| 531 | t.setToExternal(static_cast<uint8_t*>(const_cast<void*>(l)), size, false); |
| 532 | return t; |
| 533 | } |
| 534 | |
| 535 | /** |
| 536 | * \brief Create a `hidl_vec<uint8_t>` that is a copy of an opaque buffer. |
| 537 | * |
| 538 | * \param[in] l The pointer to the beginning of the opaque buffer. |
| 539 | * \param[in] size The size of the buffer. |
| 540 | * \return A `hidl_vec<uint8_t>` that is a copy of the input buffer. |
| 541 | */ |
| 542 | // convert: void*, size_t -> hidl_vec<uint8_t> |
| 543 | inline hidl_vec<uint8_t> toHidlBytes(void const* l, size_t size) { |
| 544 | hidl_vec<uint8_t> t; |
| 545 | t.resize(size); |
| 546 | uint8_t const* src = static_cast<uint8_t const*>(l); |
| 547 | std::copy(src, src + size, t.data()); |
| 548 | return t; |
| 549 | } |
| 550 | |
| 551 | /** |
Pawin Vongmasa | 9c47c97 | 2017-02-08 04:09:38 -0800 | [diff] [blame] | 552 | * \brief Wrap `GraphicBuffer` in `AnwBuffer`. |
| 553 | * |
| 554 | * \param[out] t The wrapper of type `AnwBuffer`. |
| 555 | * \param[in] l The source `GraphicBuffer`. |
| 556 | */ |
| 557 | // wrap: GraphicBuffer -> AnwBuffer |
| 558 | inline void wrapAs(AnwBuffer* t, GraphicBuffer const& l) { |
| 559 | t->attr.width = l.getWidth(); |
| 560 | t->attr.height = l.getHeight(); |
| 561 | t->attr.stride = l.getStride(); |
| 562 | t->attr.format = static_cast<PixelFormat>(l.getPixelFormat()); |
| 563 | t->attr.layerCount = l.getLayerCount(); |
| 564 | t->attr.usage = l.getUsage(); |
| 565 | t->attr.id = l.getId(); |
| 566 | t->attr.generationNumber = l.getGenerationNumber(); |
| 567 | t->nativeHandle = hidl_handle(l.handle); |
| 568 | } |
| 569 | |
| 570 | /** |
| 571 | * \brief Convert `AnwBuffer` to `GraphicBuffer`. |
| 572 | * |
| 573 | * \param[out] l The destination `GraphicBuffer`. |
| 574 | * \param[in] t The source `AnwBuffer`. |
| 575 | * |
| 576 | * This function will duplicate all file descriptors in \p t. |
| 577 | */ |
| 578 | // convert: AnwBuffer -> GraphicBuffer |
| 579 | // Ref: frameworks/native/libs/ui/GraphicBuffer.cpp: GraphicBuffer::flatten |
| 580 | inline bool convertTo(GraphicBuffer* l, AnwBuffer const& t) { |
| 581 | native_handle_t* handle = t.nativeHandle == nullptr ? |
| 582 | nullptr : native_handle_clone(t.nativeHandle); |
| 583 | |
| 584 | size_t const numInts = 12 + (handle ? handle->numInts : 0); |
| 585 | int32_t* ints = new int32_t[numInts]; |
| 586 | |
| 587 | size_t numFds = static_cast<size_t>(handle ? handle->numFds : 0); |
| 588 | int* fds = new int[numFds]; |
| 589 | |
| 590 | ints[0] = 'GBFR'; |
| 591 | ints[1] = static_cast<int32_t>(t.attr.width); |
| 592 | ints[2] = static_cast<int32_t>(t.attr.height); |
| 593 | ints[3] = static_cast<int32_t>(t.attr.stride); |
| 594 | ints[4] = static_cast<int32_t>(t.attr.format); |
| 595 | ints[5] = static_cast<int32_t>(t.attr.layerCount); |
| 596 | ints[6] = static_cast<int32_t>(t.attr.usage); |
| 597 | ints[7] = static_cast<int32_t>(t.attr.id >> 32); |
| 598 | ints[8] = static_cast<int32_t>(t.attr.id & 0xFFFFFFFF); |
| 599 | ints[9] = static_cast<int32_t>(t.attr.generationNumber); |
| 600 | ints[10] = 0; |
| 601 | ints[11] = 0; |
| 602 | if (handle) { |
| 603 | ints[10] = static_cast<int32_t>(handle->numFds); |
| 604 | ints[11] = static_cast<int32_t>(handle->numInts); |
| 605 | int* intsStart = handle->data + handle->numFds; |
| 606 | std::copy(handle->data, intsStart, fds); |
| 607 | std::copy(intsStart, intsStart + handle->numInts, &ints[12]); |
| 608 | } |
| 609 | |
| 610 | void const* constBuffer = static_cast<void const*>(ints); |
| 611 | size_t size = numInts * sizeof(int32_t); |
| 612 | int const* constFds = static_cast<int const*>(fds); |
| 613 | status_t status = l->unflatten(constBuffer, size, constFds, numFds); |
| 614 | |
| 615 | delete [] fds; |
| 616 | delete [] ints; |
| 617 | native_handle_delete(handle); |
| 618 | return status == NO_ERROR; |
| 619 | } |
| 620 | |
| 621 | /** |
Pawin Vongmasa | eeac97b | 2017-01-18 05:03:07 -0800 | [diff] [blame] | 622 | * \brief Wrap `OMXBuffer` in `CodecBuffer`. |
| 623 | * |
| 624 | * \param[out] t The wrapper of type `CodecBuffer`. |
| 625 | * \param[in] l The source `OMXBuffer`. |
| 626 | * \return `true` if the wrapping is successful; `false` otherwise. |
| 627 | */ |
| 628 | // wrap: OMXBuffer -> CodecBuffer |
| 629 | inline bool wrapAs(CodecBuffer* t, OMXBuffer const& l) { |
Pawin Vongmasa | eeac97b | 2017-01-18 05:03:07 -0800 | [diff] [blame] | 630 | t->sharedMemory = hidl_memory(); |
Pawin Vongmasa | 9c47c97 | 2017-02-08 04:09:38 -0800 | [diff] [blame] | 631 | t->nativeHandle = hidl_handle(); |
Pawin Vongmasa | eeac97b | 2017-01-18 05:03:07 -0800 | [diff] [blame] | 632 | switch (l.mBufferType) { |
| 633 | case OMXBuffer::kBufferTypeInvalid: { |
| 634 | t->type = CodecBuffer::Type::INVALID; |
| 635 | return true; |
| 636 | } |
| 637 | case OMXBuffer::kBufferTypePreset: { |
| 638 | t->type = CodecBuffer::Type::PRESET; |
| 639 | t->attr.preset.rangeLength = static_cast<uint32_t>(l.mRangeLength); |
| 640 | t->attr.preset.rangeOffset = static_cast<uint32_t>(l.mRangeOffset); |
| 641 | return true; |
| 642 | } |
| 643 | case OMXBuffer::kBufferTypeHidlMemory: { |
| 644 | t->type = CodecBuffer::Type::SHARED_MEM; |
| 645 | t->sharedMemory = l.mHidlMemory; |
| 646 | return true; |
| 647 | } |
| 648 | case OMXBuffer::kBufferTypeSharedMem: { |
| 649 | // This is not supported. |
| 650 | return false; |
| 651 | } |
| 652 | case OMXBuffer::kBufferTypeANWBuffer: { |
| 653 | t->type = CodecBuffer::Type::ANW_BUFFER; |
Pawin Vongmasa | 8ff4018 | 2017-02-07 02:22:34 -0800 | [diff] [blame] | 654 | if (l.mGraphicBuffer == nullptr) { |
| 655 | t->attr.anwBuffer.width = 0; |
| 656 | t->attr.anwBuffer.height = 0; |
| 657 | t->attr.anwBuffer.stride = 0; |
| 658 | t->attr.anwBuffer.format = static_cast<PixelFormat>(1); |
| 659 | t->attr.anwBuffer.layerCount = 0; |
| 660 | t->attr.anwBuffer.usage = 0; |
Pawin Vongmasa | 8ff4018 | 2017-02-07 02:22:34 -0800 | [diff] [blame] | 661 | return true; |
| 662 | } |
Pawin Vongmasa | eeac97b | 2017-01-18 05:03:07 -0800 | [diff] [blame] | 663 | t->attr.anwBuffer.width = l.mGraphicBuffer->getWidth(); |
| 664 | t->attr.anwBuffer.height = l.mGraphicBuffer->getHeight(); |
| 665 | t->attr.anwBuffer.stride = l.mGraphicBuffer->getStride(); |
| 666 | t->attr.anwBuffer.format = static_cast<PixelFormat>( |
| 667 | l.mGraphicBuffer->getPixelFormat()); |
| 668 | t->attr.anwBuffer.layerCount = l.mGraphicBuffer->getLayerCount(); |
| 669 | t->attr.anwBuffer.usage = l.mGraphicBuffer->getUsage(); |
Pawin Vongmasa | 9c47c97 | 2017-02-08 04:09:38 -0800 | [diff] [blame] | 670 | t->nativeHandle = l.mGraphicBuffer->handle; |
Pawin Vongmasa | eeac97b | 2017-01-18 05:03:07 -0800 | [diff] [blame] | 671 | return true; |
| 672 | } |
| 673 | case OMXBuffer::kBufferTypeNativeHandle: { |
| 674 | t->type = CodecBuffer::Type::NATIVE_HANDLE; |
Pawin Vongmasa | 9c47c97 | 2017-02-08 04:09:38 -0800 | [diff] [blame] | 675 | t->nativeHandle = l.mNativeHandle->handle(); |
Pawin Vongmasa | eeac97b | 2017-01-18 05:03:07 -0800 | [diff] [blame] | 676 | return true; |
| 677 | } |
| 678 | } |
| 679 | return false; |
| 680 | } |
| 681 | |
| 682 | /** |
| 683 | * \brief Convert `CodecBuffer` to `OMXBuffer`. |
| 684 | * |
| 685 | * \param[out] l The destination `OMXBuffer`. |
| 686 | * \param[in] t The source `CodecBuffer`. |
| 687 | * \return `true` if successful; `false` otherwise. |
| 688 | */ |
| 689 | // convert: CodecBuffer -> OMXBuffer |
| 690 | inline bool convertTo(OMXBuffer* l, CodecBuffer const& t) { |
| 691 | switch (t.type) { |
| 692 | case CodecBuffer::Type::INVALID: { |
| 693 | *l = OMXBuffer(); |
| 694 | return true; |
| 695 | } |
| 696 | case CodecBuffer::Type::PRESET: { |
| 697 | *l = OMXBuffer( |
| 698 | t.attr.preset.rangeOffset, |
| 699 | t.attr.preset.rangeLength); |
| 700 | return true; |
| 701 | } |
| 702 | case CodecBuffer::Type::SHARED_MEM: { |
| 703 | *l = OMXBuffer(t.sharedMemory); |
| 704 | return true; |
| 705 | } |
| 706 | case CodecBuffer::Type::ANW_BUFFER: { |
Pawin Vongmasa | 8ff4018 | 2017-02-07 02:22:34 -0800 | [diff] [blame] | 707 | if (t.nativeHandle.getNativeHandle() == nullptr) { |
| 708 | *l = OMXBuffer(sp<GraphicBuffer>(nullptr)); |
| 709 | return true; |
| 710 | } |
Pawin Vongmasa | 9c47c97 | 2017-02-08 04:09:38 -0800 | [diff] [blame] | 711 | AnwBuffer anwBuffer; |
| 712 | anwBuffer.nativeHandle = t.nativeHandle; |
| 713 | anwBuffer.attr = t.attr.anwBuffer; |
| 714 | sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(); |
| 715 | if (!convertTo(graphicBuffer.get(), anwBuffer)) { |
| 716 | return false; |
| 717 | } |
| 718 | *l = OMXBuffer(graphicBuffer); |
Pawin Vongmasa | eeac97b | 2017-01-18 05:03:07 -0800 | [diff] [blame] | 719 | return true; |
| 720 | } |
| 721 | case CodecBuffer::Type::NATIVE_HANDLE: { |
| 722 | *l = OMXBuffer(NativeHandle::create( |
| 723 | native_handle_clone(t.nativeHandle), true)); |
| 724 | return true; |
| 725 | } |
| 726 | } |
| 727 | return false; |
| 728 | } |
| 729 | |
| 730 | /** |
| 731 | * \brief Convert `IOMX::ComponentInfo` to `IOmx::ComponentInfo`. |
| 732 | * |
| 733 | * \param[out] t The destination `IOmx::ComponentInfo`. |
| 734 | * \param[in] l The source `IOMX::ComponentInfo`. |
| 735 | */ |
| 736 | // convert: IOMX::ComponentInfo -> IOmx::ComponentInfo |
| 737 | inline bool convertTo(IOmx::ComponentInfo* t, IOMX::ComponentInfo const& l) { |
| 738 | t->mName = l.mName.string(); |
| 739 | t->mRoles.resize(l.mRoles.size()); |
| 740 | size_t i = 0; |
| 741 | for (auto& role : l.mRoles) { |
| 742 | t->mRoles[i++] = role.string(); |
| 743 | } |
| 744 | return true; |
| 745 | } |
| 746 | |
| 747 | /** |
| 748 | * \brief Convert `IOmx::ComponentInfo` to `IOMX::ComponentInfo`. |
| 749 | * |
| 750 | * \param[out] l The destination `IOMX::ComponentInfo`. |
| 751 | * \param[in] t The source `IOmx::ComponentInfo`. |
| 752 | */ |
| 753 | // convert: IOmx::ComponentInfo -> IOMX::ComponentInfo |
| 754 | inline bool convertTo(IOMX::ComponentInfo* l, IOmx::ComponentInfo const& t) { |
| 755 | l->mName = t.mName.c_str(); |
| 756 | l->mRoles.clear(); |
| 757 | for (size_t i = 0; i < t.mRoles.size(); ++i) { |
| 758 | l->mRoles.push_back(String8(t.mRoles[i].c_str())); |
| 759 | } |
| 760 | return true; |
| 761 | } |
| 762 | |
| 763 | /** |
| 764 | * \brief Convert `OMX_BOOL` to `bool`. |
| 765 | * |
| 766 | * \param[in] l The source `OMX_BOOL`. |
| 767 | * \return The destination `bool`. |
| 768 | */ |
| 769 | // convert: OMX_BOOL -> bool |
| 770 | inline bool toRawBool(OMX_BOOL l) { |
| 771 | return l == OMX_FALSE ? false : true; |
| 772 | } |
| 773 | |
| 774 | /** |
| 775 | * \brief Convert `bool` to `OMX_BOOL`. |
| 776 | * |
| 777 | * \param[in] t The source `bool`. |
| 778 | * \return The destination `OMX_BOOL`. |
| 779 | */ |
| 780 | // convert: bool -> OMX_BOOL |
| 781 | inline OMX_BOOL toEnumBool(bool t) { |
| 782 | return t ? OMX_TRUE : OMX_FALSE; |
| 783 | } |
| 784 | |
| 785 | /** |
| 786 | * \brief Convert `OMX_COMMANDTYPE` to `uint32_t`. |
| 787 | * |
| 788 | * \param[in] l The source `OMX_COMMANDTYPE`. |
| 789 | * \return The underlying value of type `uint32_t`. |
| 790 | * |
| 791 | * `OMX_COMMANDTYPE` is an enum type whose underlying type is `uint32_t`. |
| 792 | */ |
| 793 | // convert: OMX_COMMANDTYPE -> uint32_t |
| 794 | inline uint32_t toRawCommandType(OMX_COMMANDTYPE l) { |
| 795 | return static_cast<uint32_t>(l); |
| 796 | } |
| 797 | |
| 798 | /** |
| 799 | * \brief Convert `uint32_t` to `OMX_COMMANDTYPE`. |
| 800 | * |
| 801 | * \param[in] t The source `uint32_t`. |
| 802 | * \return The corresponding enum value of type `OMX_COMMANDTYPE`. |
| 803 | * |
| 804 | * `OMX_COMMANDTYPE` is an enum type whose underlying type is `uint32_t`. |
| 805 | */ |
| 806 | // convert: uint32_t -> OMX_COMMANDTYPE |
| 807 | inline OMX_COMMANDTYPE toEnumCommandType(uint32_t t) { |
| 808 | return static_cast<OMX_COMMANDTYPE>(t); |
| 809 | } |
| 810 | |
| 811 | /** |
| 812 | * \brief Convert `OMX_INDEXTYPE` to `uint32_t`. |
| 813 | * |
| 814 | * \param[in] l The source `OMX_INDEXTYPE`. |
| 815 | * \return The underlying value of type `uint32_t`. |
| 816 | * |
| 817 | * `OMX_INDEXTYPE` is an enum type whose underlying type is `uint32_t`. |
| 818 | */ |
| 819 | // convert: OMX_INDEXTYPE -> uint32_t |
| 820 | inline uint32_t toRawIndexType(OMX_INDEXTYPE l) { |
| 821 | return static_cast<uint32_t>(l); |
| 822 | } |
| 823 | |
| 824 | /** |
| 825 | * \brief Convert `uint32_t` to `OMX_INDEXTYPE`. |
| 826 | * |
| 827 | * \param[in] t The source `uint32_t`. |
| 828 | * \return The corresponding enum value of type `OMX_INDEXTYPE`. |
| 829 | * |
| 830 | * `OMX_INDEXTYPE` is an enum type whose underlying type is `uint32_t`. |
| 831 | */ |
| 832 | // convert: uint32_t -> OMX_INDEXTYPE |
| 833 | inline OMX_INDEXTYPE toEnumIndexType(uint32_t t) { |
| 834 | return static_cast<OMX_INDEXTYPE>(t); |
| 835 | } |
| 836 | |
| 837 | /** |
| 838 | * \brief Convert `IOMX::PortMode` to `PortMode`. |
| 839 | * |
| 840 | * \param[in] l The source `IOMX::PortMode`. |
| 841 | * \return The destination `PortMode`. |
| 842 | */ |
| 843 | // convert: IOMX::PortMode -> PortMode |
| 844 | inline PortMode toHardwarePortMode(IOMX::PortMode l) { |
| 845 | return static_cast<PortMode>(l); |
| 846 | } |
| 847 | |
| 848 | /** |
| 849 | * \brief Convert `PortMode` to `IOMX::PortMode`. |
| 850 | * |
| 851 | * \param[in] t The source `PortMode`. |
| 852 | * \return The destination `IOMX::PortMode`. |
| 853 | */ |
| 854 | // convert: PortMode -> IOMX::PortMode |
| 855 | inline IOMX::PortMode toIOMXPortMode(PortMode t) { |
| 856 | return static_cast<IOMX::PortMode>(t); |
| 857 | } |
| 858 | |
| 859 | /** |
| 860 | * \brief Convert `OMX_TICKS` to `uint64_t`. |
| 861 | * |
| 862 | * \param[in] l The source `OMX_TICKS`. |
| 863 | * \return The destination `uint64_t`. |
| 864 | */ |
| 865 | // convert: OMX_TICKS -> uint64_t |
| 866 | inline uint64_t toRawTicks(OMX_TICKS l) { |
| 867 | #ifndef OMX_SKIP64BIT |
| 868 | return static_cast<uint64_t>(l); |
| 869 | #else |
| 870 | return static_cast<uint64_t>(l.nLowPart) | |
| 871 | static_cast<uint64_t>(l.nHighPart << 32); |
| 872 | #endif |
| 873 | } |
| 874 | |
| 875 | /** |
| 876 | * \brief Convert `uint64_t` to `OMX_TICKS`. |
| 877 | * |
| 878 | * \param[in] l The source `uint64_t`. |
| 879 | * \return The destination `OMX_TICKS`. |
| 880 | */ |
| 881 | // convert: uint64_t -> OMX_TICKS |
| 882 | inline OMX_TICKS toOMXTicks(uint64_t t) { |
| 883 | #ifndef OMX_SKIP64BIT |
| 884 | return static_cast<OMX_TICKS>(t); |
| 885 | #else |
| 886 | return OMX_TICKS{ |
| 887 | static_cast<uint32_t>(t & 0xFFFFFFFF), |
| 888 | static_cast<uint32_t>(t >> 32)}; |
| 889 | #endif |
| 890 | } |
| 891 | |
Pawin Vongmasa | eeac97b | 2017-01-18 05:03:07 -0800 | [diff] [blame] | 892 | } // namespace utils |
| 893 | } // namespace V1_0 |
| 894 | } // namespace omx |
| 895 | } // namespace media |
| 896 | } // namespace hardware |
| 897 | } // namespace android |
| 898 | |
| 899 | #endif // ANDROID_HARDWARE_MEDIA_OMX_V1_0__CONVERSION_H |