1/* 2 * Copyright 2016, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#ifndef ANDROID_HARDWARE_MEDIA_OMX_V1_0__CONVERSION_H 18#define ANDROID_HARDWARE_MEDIA_OMX_V1_0__CONVERSION_H 19 20#include <vector> 21#include <list> 22 23#include <cinttypes> 24#include <unistd.h> 25 26#include <hidl/MQDescriptor.h> 27#include <hidl/Status.h> 28#include <hidlmemory/mapping.h> 29 30#include <binder/Binder.h> 31#include <binder/Status.h> 32#include <ui/FenceTime.h> 33#include <cutils/native_handle.h> 34#include <gui/IGraphicBufferProducer.h> 35 36#include <media/OMXFenceParcelable.h> 37#include <media/OMXBuffer.h> 38#include <media/hardware/VideoAPI.h> 39#include <media/stagefright/MediaErrors.h> 40#include <media/stagefright/bqhelper/Conversion.h> 41 42#include <android/hidl/memory/1.0/IMemory.h> 43#include <android/hardware/graphics/bufferqueue/1.0/IProducerListener.h> 44#include <android/hardware/media/omx/1.0/types.h> 45#include <android/hardware/media/omx/1.0/IOmx.h> 46#include <android/hardware/media/omx/1.0/IOmxNode.h> 47#include <android/hardware/media/omx/1.0/IOmxBufferSource.h> 48#include <android/hardware/media/omx/1.0/IGraphicBufferSource.h> 49#include <android/hardware/media/omx/1.0/IOmxObserver.h> 50 51#include <android/IGraphicBufferSource.h> 52#include <android/IOMXBufferSource.h> 53 54namespace android { 55namespace hardware { 56namespace media { 57namespace omx { 58namespace V1_0 { 59namespace implementation { 60 61using ::android::hardware::hidl_array; 62using ::android::hardware::hidl_string; 63using ::android::hardware::hidl_vec; 64using ::android::hardware::hidl_handle; 65using ::android::hardware::Return; 66using ::android::hardware::Void; 67using ::android::sp; 68 69using ::android::String8; 70using ::android::OMXFenceParcelable; 71 72using ::android::hardware::media::omx::V1_0::Message; 73using ::android::omx_message; 74 75using ::android::hardware::media::omx::V1_0::ColorAspects; 76using ::android::hardware::media::V1_0::Rect; 77using ::android::hardware::media::V1_0::Region; 78 79using ::android::hardware::graphics::common::V1_0::Dataspace; 80 81using ::android::hardware::graphics::common::V1_0::PixelFormat; 82 83using ::android::OMXBuffer; 84 85using ::android::hardware::media::V1_0::AnwBuffer; 86using ::android::GraphicBuffer; 87 88using ::android::hardware::media::omx::V1_0::IOmx; 89using ::android::IOMX; 90 91using ::android::hardware::media::omx::V1_0::IOmxNode; 92using ::android::IOMXNode; 93 94using ::android::hardware::media::omx::V1_0::IOmxObserver; 95using ::android::IOMXObserver; 96 97using ::android::hardware::media::omx::V1_0::IOmxBufferSource; 98using ::android::IOMXBufferSource; 99 100typedef ::android::hardware::graphics::bufferqueue::V1_0::IGraphicBufferProducer 101 HGraphicBufferProducer; 102typedef ::android::IGraphicBufferProducer 103 BGraphicBufferProducer; 104 105// We want to use all functions declared in ::android::conversion 106using namespace ::android::conversion; 107 108// Now specifically inject these two functions here, because we're going to 109// declare functions with the same name in this namespace. 110using ::android::conversion::convertTo; 111using ::android::conversion::toStatusT; 112 113/** 114 * Conversion functions 115 * ==================== 116 * 117 * There are two main directions of conversion: 118 * - `inTargetType(...)`: Create a wrapper whose lifetime depends on the 119 * input. The wrapper has type `TargetType`. 120 * - `toTargetType(...)`: Create a standalone object of type `TargetType` that 121 * corresponds to the input. The lifetime of the output does not depend on the 122 * lifetime of the input. 123 * - `wrapIn(TargetType*, ...)`: Same as `inTargetType()`, but for `TargetType` 124 * that cannot be copied and/or moved efficiently, or when there are multiple 125 * output arguments. 126 * - `convertTo(TargetType*, ...)`: Same as `toTargetType()`, but for 127 * `TargetType` that cannot be copied and/or moved efficiently, or when there 128 * are multiple output arguments. 129 * 130 * `wrapIn()` and `convertTo()` functions will take output arguments before 131 * input arguments. Some of these functions might return a value to indicate 132 * success or error. 133 * 134 * In converting or wrapping something as a Treble type that contains a 135 * `hidl_handle`, `native_handle_t*` will need to be created and returned as 136 * an additional output argument, hence only `wrapIn()` or `convertTo()` would 137 * be available. The caller must call `native_handle_delete()` to deallocate the 138 * returned native handle when it is no longer needed. 139 * 140 * For types that contain file descriptors, `inTargetType()` and `wrapAs()` do 141 * not perform duplication of file descriptors, while `toTargetType()` and 142 * `convertTo()` do. 143 */ 144 145/** 146 * \brief Convert `Status` to `status_t`. This is for legacy binder calls. 147 * 148 * \param[in] t The source `Status`. 149 * \return the corresponding `status_t`. 150 */ 151// convert: Status -> status_t 152inline status_t toStatusT(Status const& t) { 153 switch (t) { 154 case Status::NO_ERROR: 155 case Status::NAME_NOT_FOUND: 156 case Status::WOULD_BLOCK: 157 case Status::NO_MEMORY: 158 case Status::ALREADY_EXISTS: 159 case Status::NO_INIT: 160 case Status::BAD_VALUE: 161 case Status::DEAD_OBJECT: 162 case Status::INVALID_OPERATION: 163 case Status::TIMED_OUT: 164 case Status::ERROR_UNSUPPORTED: 165 case Status::UNKNOWN_ERROR: 166 case Status::RELEASE_ALL_BUFFERS: 167 return static_cast<status_t>(t); 168 case Status::BUFFER_NEEDS_REALLOCATION: 169 return NOT_ENOUGH_DATA; 170 default: 171 ALOGW("Unrecognized status value: %" PRId32, static_cast<int32_t>(t)); 172 return static_cast<status_t>(t); 173 } 174} 175 176/** 177 * \brief Convert `Return<Status>` to `status_t`. This is for legacy binder 178 * calls. 179 * 180 * \param[in] t The source `Return<Status>`. 181 * \return The corresponding `status_t`. 182 * 183 * This function first check if \p t has a transport error. If it does, then the 184 * return value is the transport error code. Otherwise, the return value is 185 * converted from `Status` contained inside \p t. 186 * 187 * Note: 188 * - This `Status` is omx-specific. It is defined in `types.hal`. 189 * - The name of this function is not `convert`. 190 */ 191// convert: Status -> status_t 192inline status_t toStatusT(Return<Status> const& t) { 193 return t.isOk() ? toStatusT(static_cast<Status>(t)) : UNKNOWN_ERROR; 194} 195 196/** 197 * \brief Convert `status_t` to `Status`. 198 * 199 * \param[in] l The source `status_t`. 200 * \return The corresponding `Status`. 201 */ 202// convert: status_t -> Status 203inline Status toStatus(status_t l) { 204 switch (l) { 205 case NO_ERROR: 206 case NAME_NOT_FOUND: 207 case WOULD_BLOCK: 208 case NO_MEMORY: 209 case ALREADY_EXISTS: 210 case NO_INIT: 211 case BAD_VALUE: 212 case DEAD_OBJECT: 213 case INVALID_OPERATION: 214 case TIMED_OUT: 215 case ERROR_UNSUPPORTED: 216 case UNKNOWN_ERROR: 217 case IGraphicBufferProducer::RELEASE_ALL_BUFFERS: 218 case IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION: 219 return static_cast<Status>(l); 220 case NOT_ENOUGH_DATA: 221 return Status::BUFFER_NEEDS_REALLOCATION; 222 default: 223 ALOGW("Unrecognized status value: %" PRId32, static_cast<int32_t>(l)); 224 return static_cast<Status>(l); 225 } 226} 227 228/** 229 * \brief Wrap an `omx_message` and construct the corresponding `Message`. 230 * 231 * \param[out] t The wrapper of type `Message`. 232 * \param[out] nh The native_handle_t referred to by `t->fence`. 233 * \param[in] l The source `omx_message`. 234 * \return `true` if the wrapping is successful; `false` otherwise. 235 * 236 * Upon success, \p nh will be created to hold the file descriptor stored in 237 * `l.fenceFd`, and `t->fence` will point to \p nh. \p nh will need to be 238 * destroyed manually by `native_handle_delete()` when \p t is no longer needed. 239 * 240 * Upon failure, \p nh will not be created and will not need to be deleted. \p t 241 * will be invalid. 242 */ 243// wrap, omx_message -> Message, native_handle_t* 244inline bool wrapAs(Message* t, native_handle_t** nh, omx_message const& l) { 245 *nh = native_handle_create_from_fd(l.fenceFd); 246 if (!*nh) { 247 return false; 248 } 249 t->fence = *nh; 250 switch (l.type) { 251 case omx_message::EVENT: 252 t->type = Message::Type::EVENT; 253 t->data.eventData.event = uint32_t(l.u.event_data.event); 254 t->data.eventData.data1 = l.u.event_data.data1; 255 t->data.eventData.data2 = l.u.event_data.data2; 256 t->data.eventData.data3 = l.u.event_data.data3; 257 t->data.eventData.data4 = l.u.event_data.data4; 258 break; 259 case omx_message::EMPTY_BUFFER_DONE: 260 t->type = Message::Type::EMPTY_BUFFER_DONE; 261 t->data.bufferData.buffer = l.u.buffer_data.buffer; 262 break; 263 case omx_message::FILL_BUFFER_DONE: 264 t->type = Message::Type::FILL_BUFFER_DONE; 265 t->data.extendedBufferData.buffer = l.u.extended_buffer_data.buffer; 266 t->data.extendedBufferData.rangeOffset = 267 l.u.extended_buffer_data.range_offset; 268 t->data.extendedBufferData.rangeLength = 269 l.u.extended_buffer_data.range_length; 270 t->data.extendedBufferData.flags = l.u.extended_buffer_data.flags; 271 t->data.extendedBufferData.timestampUs = 272 l.u.extended_buffer_data.timestamp; 273 break; 274 case omx_message::FRAME_RENDERED: 275 t->type = Message::Type::FRAME_RENDERED; 276 t->data.renderData.timestampUs = l.u.render_data.timestamp; 277 t->data.renderData.systemTimeNs = l.u.render_data.nanoTime; 278 break; 279 default: 280 native_handle_delete(*nh); 281 return false; 282 } 283 return true; 284} 285 286/** 287 * \brief Wrap a `Message` inside an `omx_message`. 288 * 289 * \param[out] l The wrapper of type `omx_message`. 290 * \param[in] t The source `Message`. 291 * \return `true` if the wrapping is successful; `false` otherwise. 292 */ 293// wrap: Message -> omx_message 294inline bool wrapAs(omx_message* l, Message const& t) { 295 l->fenceFd = native_handle_read_fd(t.fence); 296 switch (t.type) { 297 case Message::Type::EVENT: 298 l->type = omx_message::EVENT; 299 l->u.event_data.event = OMX_EVENTTYPE(t.data.eventData.event); 300 l->u.event_data.data1 = t.data.eventData.data1; 301 l->u.event_data.data2 = t.data.eventData.data2; 302 l->u.event_data.data3 = t.data.eventData.data3; 303 l->u.event_data.data4 = t.data.eventData.data4; 304 break; 305 case Message::Type::EMPTY_BUFFER_DONE: 306 l->type = omx_message::EMPTY_BUFFER_DONE; 307 l->u.buffer_data.buffer = t.data.bufferData.buffer; 308 break; 309 case Message::Type::FILL_BUFFER_DONE: 310 l->type = omx_message::FILL_BUFFER_DONE; 311 l->u.extended_buffer_data.buffer = t.data.extendedBufferData.buffer; 312 l->u.extended_buffer_data.range_offset = 313 t.data.extendedBufferData.rangeOffset; 314 l->u.extended_buffer_data.range_length = 315 t.data.extendedBufferData.rangeLength; 316 l->u.extended_buffer_data.flags = t.data.extendedBufferData.flags; 317 l->u.extended_buffer_data.timestamp = 318 t.data.extendedBufferData.timestampUs; 319 break; 320 case Message::Type::FRAME_RENDERED: 321 l->type = omx_message::FRAME_RENDERED; 322 l->u.render_data.timestamp = t.data.renderData.timestampUs; 323 l->u.render_data.nanoTime = t.data.renderData.systemTimeNs; 324 break; 325 default: 326 return false; 327 } 328 return true; 329} 330 331/** 332 * \brief Similar to `wrapTo(omx_message*, Message const&)`, but the output will 333 * have an extended lifetime. 334 * 335 * \param[out] l The output `omx_message`. 336 * \param[in] t The source `Message`. 337 * \return `true` if the conversion is successful; `false` otherwise. 338 * 339 * This function calls `wrapto()`, then attempts to duplicate the file 340 * descriptor for the fence if it is not `-1`. If duplication fails, `false` 341 * will be returned. 342 */ 343// convert: Message -> omx_message 344inline bool convertTo(omx_message* l, Message const& t) { 345 if (!wrapAs(l, t)) { 346 return false; 347 } 348 if (l->fenceFd == -1) { 349 return true; 350 } 351 l->fenceFd = dup(l->fenceFd); 352 return l->fenceFd != -1; 353} 354 355/** 356 * \brief Wrap an `OMXFenceParcelable` inside a `hidl_handle`. 357 * 358 * \param[out] t The wrapper of type `hidl_handle`. 359 * \param[out] nh The native handle created to hold the file descriptor inside 360 * \p l. 361 * \param[in] l The source `OMXFenceParcelable`, which essentially contains one 362 * file descriptor. 363 * \return `true` if \p t and \p nh are successfully created to wrap around \p 364 * l; `false` otherwise. 365 * 366 * On success, \p nh needs to be deleted by the caller with 367 * `native_handle_delete()` after \p t and \p nh are no longer needed. 368 * 369 * On failure, \p nh will not need to be deleted, and \p t will hold an invalid 370 * value. 371 */ 372// wrap: OMXFenceParcelable -> hidl_handle, native_handle_t* 373inline bool wrapAs(hidl_handle* t, native_handle_t** nh, 374 OMXFenceParcelable const& l) { 375 *nh = native_handle_create_from_fd(l.get()); 376 if (!*nh) { 377 return false; 378 } 379 *t = *nh; 380 return true; 381} 382 383/** 384 * \brief Wrap a `hidl_handle` inside an `OMXFenceParcelable`. 385 * 386 * \param[out] l The wrapper of type `OMXFenceParcelable`. 387 * \param[in] t The source `hidl_handle`. 388 */ 389// wrap: hidl_handle -> OMXFenceParcelable 390inline void wrapAs(OMXFenceParcelable* l, hidl_handle const& t) { 391 l->mFenceFd = native_handle_read_fd(t); 392} 393 394/** 395 * \brief Convert a `hidl_handle` to `OMXFenceParcelable`. If `hidl_handle` 396 * contains file descriptors, the first file descriptor will be duplicated and 397 * stored in the output `OMXFenceParcelable`. 398 * 399 * \param[out] l The output `OMXFenceParcelable`. 400 * \param[in] t The input `hidl_handle`. 401 * \return `false` if \p t contains a valid file descriptor but duplication 402 * fails; `true` otherwise. 403 */ 404// convert: hidl_handle -> OMXFenceParcelable 405inline bool convertTo(OMXFenceParcelable* l, hidl_handle const& t) { 406 int fd = native_handle_read_fd(t); 407 if (fd != -1) { 408 fd = dup(fd); 409 if (fd == -1) { 410 return false; 411 } 412 } 413 l->mFenceFd = fd; 414 return true; 415} 416 417/** 418 * \brief Convert `::android::ColorAspects` to `ColorAspects`. 419 * 420 * \param[in] l The source `::android::ColorAspects`. 421 * \return The corresponding `ColorAspects`. 422 */ 423// convert: ::android::ColorAspects -> ColorAspects 424inline ColorAspects toHardwareColorAspects(::android::ColorAspects const& l) { 425 return ColorAspects{ 426 static_cast<ColorAspects::Range>(l.mRange), 427 static_cast<ColorAspects::Primaries>(l.mPrimaries), 428 static_cast<ColorAspects::Transfer>(l.mTransfer), 429 static_cast<ColorAspects::MatrixCoeffs>(l.mMatrixCoeffs)}; 430} 431 432/** 433 * \brief Convert `int32_t` to `ColorAspects`. 434 * 435 * \param[in] l The source `int32_t`. 436 * \return The corresponding `ColorAspects`. 437 */ 438// convert: int32_t -> ColorAspects 439inline ColorAspects toHardwareColorAspects(int32_t l) { 440 return ColorAspects{ 441 static_cast<ColorAspects::Range>((l >> 24) & 0xFF), 442 static_cast<ColorAspects::Primaries>((l >> 16) & 0xFF), 443 static_cast<ColorAspects::Transfer>(l & 0xFF), 444 static_cast<ColorAspects::MatrixCoeffs>((l >> 8) & 0xFF)}; 445} 446 447/** 448 * \brief Convert `ColorAspects` to `::android::ColorAspects`. 449 * 450 * \param[in] t The source `ColorAspects`. 451 * \return The corresponding `::android::ColorAspects`. 452 */ 453// convert: ColorAspects -> ::android::ColorAspects 454inline int32_t toCompactColorAspects(ColorAspects const& t) { 455 return static_cast<int32_t>( 456 (static_cast<uint32_t>(t.range) << 24) | 457 (static_cast<uint32_t>(t.primaries) << 16) | 458 (static_cast<uint32_t>(t.transfer)) | 459 (static_cast<uint32_t>(t.matrixCoeffs) << 8)); 460} 461 462/** 463 * \brief Wrap `GraphicBuffer` in `CodecBuffer`. 464 * 465 * \param[out] t The wrapper of type `CodecBuffer`. 466 * \param[in] l The source `GraphicBuffer`. 467 */ 468// wrap: OMXBuffer -> CodecBuffer 469inline CodecBuffer *wrapAs(CodecBuffer *t, sp<GraphicBuffer> const& graphicBuffer) { 470 t->sharedMemory = hidl_memory(); 471 t->nativeHandle = hidl_handle(); 472 t->type = CodecBuffer::Type::ANW_BUFFER; 473 if (graphicBuffer == nullptr) { 474 t->attr.anwBuffer.width = 0; 475 t->attr.anwBuffer.height = 0; 476 t->attr.anwBuffer.stride = 0; 477 t->attr.anwBuffer.format = static_cast<PixelFormat>(1); 478 t->attr.anwBuffer.layerCount = 0; 479 t->attr.anwBuffer.usage = 0; 480 return t; 481 } 482 t->attr.anwBuffer.width = graphicBuffer->getWidth(); 483 t->attr.anwBuffer.height = graphicBuffer->getHeight(); 484 t->attr.anwBuffer.stride = graphicBuffer->getStride(); 485 t->attr.anwBuffer.format = static_cast<PixelFormat>( 486 graphicBuffer->getPixelFormat()); 487 t->attr.anwBuffer.layerCount = graphicBuffer->getLayerCount(); 488 t->attr.anwBuffer.usage = graphicBuffer->getUsage(); 489 t->nativeHandle = graphicBuffer->handle; 490 return t; 491} 492 493/** 494 * \brief Wrap `OMXBuffer` in `CodecBuffer`. 495 * 496 * \param[out] t The wrapper of type `CodecBuffer`. 497 * \param[in] l The source `OMXBuffer`. 498 * \return `true` if the wrapping is successful; `false` otherwise. 499 */ 500// wrap: OMXBuffer -> CodecBuffer 501inline bool wrapAs(CodecBuffer* t, OMXBuffer const& l) { 502 t->sharedMemory = hidl_memory(); 503 t->nativeHandle = hidl_handle(); 504 switch (l.mBufferType) { 505 case OMXBuffer::kBufferTypeInvalid: { 506 t->type = CodecBuffer::Type::INVALID; 507 return true; 508 } 509 case OMXBuffer::kBufferTypePreset: { 510 t->type = CodecBuffer::Type::PRESET; 511 t->attr.preset.rangeLength = static_cast<uint32_t>(l.mRangeLength); 512 t->attr.preset.rangeOffset = static_cast<uint32_t>(l.mRangeOffset); 513 return true; 514 } 515 case OMXBuffer::kBufferTypeHidlMemory: { 516 t->type = CodecBuffer::Type::SHARED_MEM; 517 t->sharedMemory = l.mHidlMemory; 518 return true; 519 } 520 case OMXBuffer::kBufferTypeSharedMem: { 521 // This is not supported. 522 return false; 523 } 524 case OMXBuffer::kBufferTypeANWBuffer: { 525 wrapAs(t, l.mGraphicBuffer); 526 return true; 527 } 528 case OMXBuffer::kBufferTypeNativeHandle: { 529 t->type = CodecBuffer::Type::NATIVE_HANDLE; 530 t->nativeHandle = l.mNativeHandle->handle(); 531 return true; 532 } 533 } 534 return false; 535} 536 537/** 538 * \brief Convert `CodecBuffer` to `OMXBuffer`. 539 * 540 * \param[out] l The destination `OMXBuffer`. 541 * \param[in] t The source `CodecBuffer`. 542 * \return `true` if successful; `false` otherwise. 543 */ 544// convert: CodecBuffer -> OMXBuffer 545inline bool convertTo(OMXBuffer* l, CodecBuffer const& t) { 546 switch (t.type) { 547 case CodecBuffer::Type::INVALID: { 548 *l = OMXBuffer(); 549 return true; 550 } 551 case CodecBuffer::Type::PRESET: { 552 *l = OMXBuffer( 553 t.attr.preset.rangeOffset, 554 t.attr.preset.rangeLength); 555 return true; 556 } 557 case CodecBuffer::Type::SHARED_MEM: { 558 *l = OMXBuffer(t.sharedMemory); 559 return true; 560 } 561 case CodecBuffer::Type::ANW_BUFFER: { 562 if (t.nativeHandle.getNativeHandle() == nullptr) { 563 *l = OMXBuffer(sp<GraphicBuffer>(nullptr)); 564 return true; 565 } 566 AnwBuffer anwBuffer; 567 anwBuffer.nativeHandle = t.nativeHandle; 568 anwBuffer.attr = t.attr.anwBuffer; 569 sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(); 570 if (!convertTo(graphicBuffer.get(), anwBuffer)) { 571 return false; 572 } 573 *l = OMXBuffer(graphicBuffer); 574 return true; 575 } 576 case CodecBuffer::Type::NATIVE_HANDLE: { 577 *l = OMXBuffer(NativeHandle::create( 578 native_handle_clone(t.nativeHandle), true)); 579 return true; 580 } 581 } 582 return false; 583} 584 585/** 586 * \brief Convert `IOMX::ComponentInfo` to `IOmx::ComponentInfo`. 587 * 588 * \param[out] t The destination `IOmx::ComponentInfo`. 589 * \param[in] l The source `IOMX::ComponentInfo`. 590 */ 591// convert: IOMX::ComponentInfo -> IOmx::ComponentInfo 592inline bool convertTo(IOmx::ComponentInfo* t, IOMX::ComponentInfo const& l) { 593 t->mName = l.mName.string(); 594 t->mRoles.resize(l.mRoles.size()); 595 size_t i = 0; 596 for (auto& role : l.mRoles) { 597 t->mRoles[i++] = role.string(); 598 } 599 return true; 600} 601 602/** 603 * \brief Convert `IOmx::ComponentInfo` to `IOMX::ComponentInfo`. 604 * 605 * \param[out] l The destination `IOMX::ComponentInfo`. 606 * \param[in] t The source `IOmx::ComponentInfo`. 607 */ 608// convert: IOmx::ComponentInfo -> IOMX::ComponentInfo 609inline bool convertTo(IOMX::ComponentInfo* l, IOmx::ComponentInfo const& t) { 610 l->mName = t.mName.c_str(); 611 l->mRoles.clear(); 612 for (size_t i = 0; i < t.mRoles.size(); ++i) { 613 l->mRoles.push_back(String8(t.mRoles[i].c_str())); 614 } 615 return true; 616} 617 618/** 619 * \brief Convert `OMX_BOOL` to `bool`. 620 * 621 * \param[in] l The source `OMX_BOOL`. 622 * \return The destination `bool`. 623 */ 624// convert: OMX_BOOL -> bool 625inline bool toRawBool(OMX_BOOL l) { 626 return l == OMX_FALSE ? false : true; 627} 628 629/** 630 * \brief Convert `bool` to `OMX_BOOL`. 631 * 632 * \param[in] t The source `bool`. 633 * \return The destination `OMX_BOOL`. 634 */ 635// convert: bool -> OMX_BOOL 636inline OMX_BOOL toEnumBool(bool t) { 637 return t ? OMX_TRUE : OMX_FALSE; 638} 639 640/** 641 * \brief Convert `OMX_COMMANDTYPE` to `uint32_t`. 642 * 643 * \param[in] l The source `OMX_COMMANDTYPE`. 644 * \return The underlying value of type `uint32_t`. 645 * 646 * `OMX_COMMANDTYPE` is an enum type whose underlying type is `uint32_t`. 647 */ 648// convert: OMX_COMMANDTYPE -> uint32_t 649inline uint32_t toRawCommandType(OMX_COMMANDTYPE l) { 650 return static_cast<uint32_t>(l); 651} 652 653/** 654 * \brief Convert `uint32_t` to `OMX_COMMANDTYPE`. 655 * 656 * \param[in] t The source `uint32_t`. 657 * \return The corresponding enum value of type `OMX_COMMANDTYPE`. 658 * 659 * `OMX_COMMANDTYPE` is an enum type whose underlying type is `uint32_t`. 660 */ 661// convert: uint32_t -> OMX_COMMANDTYPE 662inline OMX_COMMANDTYPE toEnumCommandType(uint32_t t) { 663 return static_cast<OMX_COMMANDTYPE>(t); 664} 665 666/** 667 * \brief Convert `OMX_INDEXTYPE` to `uint32_t`. 668 * 669 * \param[in] l The source `OMX_INDEXTYPE`. 670 * \return The underlying value of type `uint32_t`. 671 * 672 * `OMX_INDEXTYPE` is an enum type whose underlying type is `uint32_t`. 673 */ 674// convert: OMX_INDEXTYPE -> uint32_t 675inline uint32_t toRawIndexType(OMX_INDEXTYPE l) { 676 return static_cast<uint32_t>(l); 677} 678 679/** 680 * \brief Convert `uint32_t` to `OMX_INDEXTYPE`. 681 * 682 * \param[in] t The source `uint32_t`. 683 * \return The corresponding enum value of type `OMX_INDEXTYPE`. 684 * 685 * `OMX_INDEXTYPE` is an enum type whose underlying type is `uint32_t`. 686 */ 687// convert: uint32_t -> OMX_INDEXTYPE 688inline OMX_INDEXTYPE toEnumIndexType(uint32_t t) { 689 return static_cast<OMX_INDEXTYPE>(t); 690} 691 692/** 693 * \brief Convert `IOMX::PortMode` to `PortMode`. 694 * 695 * \param[in] l The source `IOMX::PortMode`. 696 * \return The destination `PortMode`. 697 */ 698// convert: IOMX::PortMode -> PortMode 699inline PortMode toHardwarePortMode(IOMX::PortMode l) { 700 return static_cast<PortMode>(l); 701} 702 703/** 704 * \brief Convert `PortMode` to `IOMX::PortMode`. 705 * 706 * \param[in] t The source `PortMode`. 707 * \return The destination `IOMX::PortMode`. 708 */ 709// convert: PortMode -> IOMX::PortMode 710inline IOMX::PortMode toIOMXPortMode(PortMode t) { 711 return static_cast<IOMX::PortMode>(t); 712} 713 714/** 715 * \brief Convert `OMX_TICKS` to `uint64_t`. 716 * 717 * \param[in] l The source `OMX_TICKS`. 718 * \return The destination `uint64_t`. 719 */ 720// convert: OMX_TICKS -> uint64_t 721inline uint64_t toRawTicks(OMX_TICKS l) { 722#ifndef OMX_SKIP64BIT 723 return static_cast<uint64_t>(l); 724#else 725 return static_cast<uint64_t>(l.nLowPart) | 726 static_cast<uint64_t>(l.nHighPart << 32); 727#endif 728} 729 730/** 731 * \brief Convert `uint64_t` to `OMX_TICKS`. 732 * 733 * \param[in] l The source `uint64_t`. 734 * \return The destination `OMX_TICKS`. 735 */ 736// convert: uint64_t -> OMX_TICKS 737inline OMX_TICKS toOMXTicks(uint64_t t) { 738#ifndef OMX_SKIP64BIT 739 return static_cast<OMX_TICKS>(t); 740#else 741 return OMX_TICKS{ 742 static_cast<uint32_t>(t & 0xFFFFFFFF), 743 static_cast<uint32_t>(t >> 32)}; 744#endif 745} 746 747} // namespace implementation 748} // namespace V1_0 749} // namespace omx 750} // namespace media 751} // namespace hardware 752} // namespace android 753 754#endif // ANDROID_HARDWARE_MEDIA_OMX_V1_0__CONVERSION_H 755