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 <unistd.h> 24 25#include <hidl/MQDescriptor.h> 26#include <hidl/Status.h> 27#include <hidlmemory/mapping.h> 28 29#include <binder/Binder.h> 30#include <binder/Status.h> 31#include <ui/FenceTime.h> 32#include <cutils/native_handle.h> 33 34#include <ui/GraphicBuffer.h> 35#include <media/OMXFenceParcelable.h> 36#include <media/OMXBuffer.h> 37#include <media/hardware/VideoAPI.h> 38 39#include <android/hidl/memory/1.0/IMemory.h> 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> 43#include <android/hardware/media/omx/1.0/IOmxBufferSource.h> 44#include <android/hardware/media/omx/1.0/IOmxObserver.h> 45#include <android/hardware/media/omx/1.0/IGraphicBufferSource.h> 46 47#include <android/IGraphicBufferSource.h> 48#include <android/IOMXBufferSource.h> 49 50namespace android { 51namespace hardware { 52namespace media { 53namespace omx { 54namespace V1_0 { 55namespace utils { 56 57using ::android::hardware::hidl_array; 58using ::android::hardware::hidl_string; 59using ::android::hardware::hidl_vec; 60using ::android::hardware::hidl_handle; 61using ::android::hardware::Return; 62using ::android::hardware::Void; 63using ::android::sp; 64 65using ::android::String8; 66using ::android::OMXFenceParcelable; 67 68using ::android::hardware::media::omx::V1_0::Message; 69using ::android::omx_message; 70 71using ::android::hardware::media::omx::V1_0::ColorAspects; 72using ::android::hardware::media::V1_0::Rect; 73using ::android::hardware::media::V1_0::Region; 74 75using ::android::hardware::graphics::common::V1_0::Dataspace; 76 77using ::android::hardware::graphics::common::V1_0::PixelFormat; 78 79using ::android::OMXBuffer; 80 81using ::android::hardware::media::V1_0::AnwBuffer; 82using ::android::GraphicBuffer; 83 84using ::android::hardware::media::omx::V1_0::IOmx; 85using ::android::IOMX; 86 87using ::android::hardware::media::omx::V1_0::IOmxNode; 88using ::android::IOMXNode; 89 90using ::android::hardware::media::omx::V1_0::IOmxObserver; 91using ::android::IOMXObserver; 92 93using ::android::hardware::media::omx::V1_0::IOmxBufferSource; 94using ::android::IOMXBufferSource; 95 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 */ 113inline 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 */ 136inline 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/** 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 181inline ::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/** 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 195inline ::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/** 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 217inline 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 228inline 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 239inline 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 250inline 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 261inline 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* 281inline 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 } 286 t->fence = *nh; 287 switch (l.type) { 288 case omx_message::EVENT: 289 t->type = Message::Type::EVENT; 290 t->data.eventData.event = uint32_t(l.u.event_data.event); 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 331inline 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; 336 l->u.event_data.event = OMX_EVENTTYPE(t.data.eventData.event); 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 381inline 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* 410inline 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 427inline 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 442inline 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 461inline 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 476inline 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 491inline 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 506inline 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 517inline 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> 529inline 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> 543inline 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/** 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 558inline 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 580inline 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/** 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 629inline bool wrapAs(CodecBuffer* t, OMXBuffer const& l) { 630 t->sharedMemory = hidl_memory(); 631 t->nativeHandle = hidl_handle(); 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; 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; 661 return true; 662 } 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(); 670 t->nativeHandle = l.mGraphicBuffer->handle; 671 return true; 672 } 673 case OMXBuffer::kBufferTypeNativeHandle: { 674 t->type = CodecBuffer::Type::NATIVE_HANDLE; 675 t->nativeHandle = l.mNativeHandle->handle(); 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 690inline 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: { 707 if (t.nativeHandle.getNativeHandle() == nullptr) { 708 *l = OMXBuffer(sp<GraphicBuffer>(nullptr)); 709 return true; 710 } 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); 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 737inline 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 754inline 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 770inline 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 781inline 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 794inline 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 807inline 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 820inline 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 833inline 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 844inline 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 855inline 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 866inline 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 882inline 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 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 900