1 /** 2 * @copyright 3 * 4 * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * * Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * * Neither the name of The Linux Foundation nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 19 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 28 * DAMAGE. 29 * 30 * @file 31 * 32 * omx_swvdec.cpp 33 * 34 * @brief 35 * 36 * OMX software video decoder component source. 37 */ 38 39 #include <assert.h> 40 #include <fcntl.h> 41 #include <sys/mman.h> 42 43 #include <cutils/properties.h> 44 45 #include <media/hardware/HardwareAPI.h> 46 #include <gralloc_priv.h> 47 48 #include "OMX_QCOMExtns.h" 49 50 #include "omx_swvdec.h" 51 52 #include "swvdec_api.h" 53 54 static unsigned int split_buffer_mpeg4(unsigned int *offset_array, 55 OMX_BUFFERHEADERTYPE *p_buffer_hdr); 56 57 /** 58 * ---------------- 59 * PUBLIC FUNCTIONS 60 * ---------------- 61 */ 62 63 /** 64 * @brief Create & return component class instance. 65 * 66 * @retval Pointer to new component class instance. 67 */ 68 void *get_omx_component_factory_fn(void) 69 { 70 return new omx_swvdec; 71 } 72 73 /** 74 * @brief Component constructor. 75 */ 76 omx_swvdec::omx_swvdec(): 77 m_state(OMX_StateInvalid), 78 m_status_flags(0), 79 m_swvdec_codec(SWVDEC_CODEC_INVALID), 80 m_swvdec_handle(NULL), 81 m_swvdec_created(false), 82 m_omx_video_codingtype(OMX_VIDEO_CodingUnused), 83 m_omx_color_formattype(OMX_COLOR_FormatUnused), 84 m_sync_frame_decoding_mode(false), 85 m_android_native_buffers(false), 86 m_meta_buffer_mode_disabled(false), 87 m_meta_buffer_mode(false), 88 m_adaptive_playback_mode(false), 89 m_arbitrary_bytes_mode(false), 90 m_port_reconfig_inprogress(false), 91 m_dimensions_update_inprogress(false), 92 m_buffer_array_ip(NULL), 93 m_buffer_array_op(NULL), 94 m_meta_buffer_array(NULL) 95 { 96 // memset all member variables that are composite structures 97 memset(&m_cmp, 0, sizeof(m_cmp)); // part of base class 98 memset(&m_cmp_name[0], 0, sizeof(m_cmp_name)); 99 memset(&m_role_name[0], 0, sizeof(m_role_name)); 100 memset(&m_frame_dimensions, 0, sizeof(m_frame_dimensions)); 101 memset(&m_frame_attributes, 0, sizeof(m_frame_attributes)); 102 memset(&m_frame_dimensions_max, 0, sizeof(m_frame_dimensions_max)); 103 memset(&m_async_thread, 0, sizeof(m_async_thread)); 104 memset(&m_port_ip, 0, sizeof(m_port_ip)); 105 memset(&m_port_op, 0, sizeof(m_port_op)); 106 memset(&m_callback, 0, sizeof(m_callback)); 107 memset(&m_app_data, 0, sizeof(m_app_data)); 108 memset(&m_prio_mgmt, 0, sizeof(m_prio_mgmt)); 109 memset(&m_sem_cmd, 0, sizeof(m_sem_cmd)); 110 memset(&m_meta_buffer_array_mutex, 0, sizeof(m_meta_buffer_array_mutex)); 111 112 // null-terminate component name & role name strings 113 m_cmp_name[0] = '\0'; 114 m_role_name[0] = '\0'; 115 116 // ports are enabled & unpopulated by default 117 m_port_ip.enabled = OMX_TRUE; 118 m_port_op.enabled = OMX_TRUE; 119 m_port_ip.unpopulated = OMX_TRUE; 120 m_port_op.unpopulated = OMX_TRUE; 121 } 122 123 /** 124 * @brief Component destructor. 125 */ 126 omx_swvdec::~omx_swvdec() 127 { 128 } 129 130 /** 131 * @brief Initialize component. 132 * 133 * @param[in] cmp_name: Component name string. 134 * 135 * @retval OMX_ERRORTYPE 136 */ 137 OMX_ERRORTYPE omx_swvdec::component_init(OMX_STRING cmp_name) 138 { 139 OMX_ERRORTYPE retval = OMX_ErrorNone; 140 141 OMX_SWVDEC_LOG_API("'%s', version date: %s", 142 cmp_name, 143 OMX_SWVDEC_VERSION_DATE); 144 145 omx_swvdec_log_init(); 146 147 { 148 char property_value[PROPERTY_VALUE_MAX] = {0}; 149 150 if (property_get("vendor.omx_swvdec.meta_buffer.disable", 151 property_value, 152 NULL)) 153 { 154 m_meta_buffer_mode_disabled = (bool) atoi(property_value); 155 156 OMX_SWVDEC_LOG_LOW("omx_swvdec.meta_buffer.disable: %d", 157 m_meta_buffer_mode_disabled ? 1 : 0); 158 } 159 } 160 161 if (m_state != OMX_StateInvalid) 162 { 163 OMX_SWVDEC_LOG_ERROR("disallowed in state %s", 164 OMX_STATETYPE_STRING(m_state)); 165 166 retval = OMX_ErrorIncorrectStateOperation; 167 goto component_init_exit; 168 } 169 170 if (!strncmp(cmp_name, 171 "OMX.qti.video.decoder.mpeg4sw", 172 OMX_MAX_STRINGNAME_SIZE)) 173 { 174 OMX_SWVDEC_LOG_LOW("'video_decoder.mpeg4'"); 175 176 strlcpy(m_cmp_name, cmp_name, OMX_MAX_STRINGNAME_SIZE); 177 strlcpy(m_role_name, "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE); 178 179 m_swvdec_codec = SWVDEC_CODEC_MPEG4; 180 m_omx_video_codingtype = OMX_VIDEO_CodingMPEG4; 181 } 182 else if (!strncmp(cmp_name, 183 "OMX.qti.video.decoder.h263sw", 184 OMX_MAX_STRINGNAME_SIZE)) 185 { 186 OMX_SWVDEC_LOG_LOW("video_decoder.h263"); 187 188 strlcpy(m_cmp_name, cmp_name, OMX_MAX_STRINGNAME_SIZE); 189 strlcpy(m_role_name, "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE); 190 191 m_swvdec_codec = SWVDEC_CODEC_H263; 192 m_omx_video_codingtype = OMX_VIDEO_CodingH263; 193 } 194 else if (((!strncmp(cmp_name, 195 "OMX.qti.video.decoder.divxsw", 196 OMX_MAX_STRINGNAME_SIZE))) || 197 ((!strncmp(cmp_name, 198 "OMX.qti.video.decoder.divx4sw", 199 OMX_MAX_STRINGNAME_SIZE)))) 200 { 201 OMX_SWVDEC_LOG_LOW("video_decoder.divx"); 202 203 strlcpy(m_cmp_name, cmp_name, OMX_MAX_STRINGNAME_SIZE); 204 strlcpy(m_role_name, "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE); 205 206 m_swvdec_codec = SWVDEC_CODEC_MPEG4; 207 m_omx_video_codingtype = ((OMX_VIDEO_CODINGTYPE) QOMX_VIDEO_CodingDivx); 208 } 209 else 210 { 211 OMX_SWVDEC_LOG_ERROR("'%s': invalid component name", cmp_name); 212 213 retval = OMX_ErrorInvalidComponentName; 214 goto component_init_exit; 215 } 216 217 { 218 SWVDEC_CALLBACK callback; 219 220 SWVDEC_STATUS retval_swvdec; 221 222 callback.pfn_empty_buffer_done = swvdec_empty_buffer_done_callback; 223 callback.pfn_fill_buffer_done = swvdec_fill_buffer_done_callback; 224 callback.pfn_event_notification = swvdec_event_handler_callback; 225 callback.p_client = this; 226 227 if ((retval_swvdec = swvdec_init(&m_swvdec_handle, 228 m_swvdec_codec, 229 &callback)) != 230 SWVDEC_STATUS_SUCCESS) 231 { 232 retval = retval_swvdec2omx(retval_swvdec); 233 goto component_init_exit; 234 } 235 236 m_swvdec_created = true; 237 238 if ((retval = set_frame_dimensions(DEFAULT_FRAME_WIDTH, 239 DEFAULT_FRAME_HEIGHT)) != 240 OMX_ErrorNone) 241 { 242 goto component_init_exit; 243 } 244 245 m_omx_color_formattype = 246 ((OMX_COLOR_FORMATTYPE) 247 OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m); 248 249 if ((retval = set_frame_attributes(m_omx_color_formattype)) != 250 OMX_ErrorNone) 251 { 252 goto component_init_exit; 253 } 254 } 255 256 if ((retval = get_buffer_requirements_swvdec(OMX_CORE_PORT_INDEX_IP)) != 257 OMX_ErrorNone) 258 { 259 goto component_init_exit; 260 } 261 262 if ((retval = get_buffer_requirements_swvdec(OMX_CORE_PORT_INDEX_OP)) != 263 OMX_ErrorNone) 264 { 265 goto component_init_exit; 266 } 267 268 if ((retval = async_thread_create()) != OMX_ErrorNone) 269 { 270 goto component_init_exit; 271 } 272 273 if (sem_init(&m_sem_cmd, 0, 0)) 274 { 275 OMX_SWVDEC_LOG_ERROR("failed to create command processing semaphore"); 276 277 retval = OMX_ErrorInsufficientResources; 278 goto component_init_exit; 279 } 280 281 if (pthread_mutex_init(&m_meta_buffer_array_mutex, NULL)) 282 { 283 OMX_SWVDEC_LOG_ERROR("failed to create meta buffer info array mutex"); 284 285 retval = OMX_ErrorInsufficientResources; 286 goto component_init_exit; 287 } 288 289 OMX_SWVDEC_LOG_HIGH("OMX_StateInvalid -> OMX_StateLoaded"); 290 291 m_state = OMX_StateLoaded; 292 293 component_init_exit: 294 return retval; 295 } 296 297 /** 298 * @brief De-initialize component. 299 * 300 * @param[in] cmp_handle: Component handle. 301 * 302 * @retval OMX_ERRORTYPE 303 */ 304 OMX_ERRORTYPE omx_swvdec::component_deinit(OMX_HANDLETYPE cmp_handle) 305 { 306 OMX_SWVDEC_LOG_API(""); 307 308 if (cmp_handle == NULL) 309 { 310 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); 311 } 312 313 pthread_mutex_destroy(&m_meta_buffer_array_mutex); 314 315 sem_destroy(&m_sem_cmd); 316 317 async_thread_destroy(); 318 319 if (m_swvdec_created) 320 { 321 swvdec_deinit(m_swvdec_handle); 322 323 m_swvdec_handle = NULL; 324 } 325 326 OMX_SWVDEC_LOG_HIGH("all done, goodbye!"); 327 328 return OMX_ErrorNone; 329 } 330 331 /** 332 * @brief Get component version. 333 * 334 * @param[in] cmp_handle: Component handle. 335 * @param[in] cmp_name: Component name string. 336 * @param[in,out] p_cmp_version: Pointer to component version variable. 337 * @param[in,out] p_spec_version: Pointer to OMX spec version variable. 338 * @param[in,out] p_cmp_UUID: Pointer to component UUID variable. 339 * 340 * @retval OMX_ERRORTYPE 341 */ 342 OMX_ERRORTYPE omx_swvdec::get_component_version(OMX_HANDLETYPE cmp_handle, 343 OMX_STRING cmp_name, 344 OMX_VERSIONTYPE *p_cmp_version, 345 OMX_VERSIONTYPE *p_spec_version, 346 OMX_UUIDTYPE *p_cmp_UUID) 347 { 348 OMX_ERRORTYPE retval = OMX_ErrorNone; 349 350 (void) p_cmp_UUID; 351 352 OMX_SWVDEC_LOG_API(""); 353 354 if (m_state == OMX_StateInvalid) 355 { 356 OMX_SWVDEC_LOG_ERROR("in invalid state"); 357 358 retval = OMX_ErrorInvalidState; 359 } 360 else if (cmp_handle == NULL) 361 { 362 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); 363 364 retval = OMX_ErrorInvalidComponent; 365 } 366 else if (strncmp(cmp_name, m_cmp_name, sizeof(m_cmp_name))) 367 { 368 OMX_SWVDEC_LOG_ERROR("'%s': invalid component name", cmp_name); 369 370 retval = OMX_ErrorInvalidComponentName; 371 } 372 else if (p_cmp_version == NULL) 373 { 374 OMX_SWVDEC_LOG_ERROR("p_cmp_version = NULL"); 375 376 retval = OMX_ErrorBadParameter; 377 } 378 else if (p_spec_version == NULL) 379 { 380 OMX_SWVDEC_LOG_ERROR("p_spec_version = NULL"); 381 382 retval = OMX_ErrorBadParameter; 383 } 384 else 385 { 386 p_spec_version->nVersion = OMX_SPEC_VERSION; 387 } 388 389 get_component_version_exit: 390 return retval; 391 } 392 393 /** 394 * @brief Send command to component. 395 * 396 * @param[in] cmp_handle: Component handle. 397 * @param[in] cmd: Command. 398 * @param[in] param: Command parameter. 399 * @param[in] p_cmd_data: Pointer to command data. 400 * 401 * @retval OMX_ERRORTYPE 402 */ 403 OMX_ERRORTYPE omx_swvdec::send_command(OMX_HANDLETYPE cmp_handle, 404 OMX_COMMANDTYPE cmd, 405 OMX_U32 param, 406 OMX_PTR p_cmd_data) 407 { 408 OMX_ERRORTYPE retval = OMX_ErrorNone; 409 410 (void) p_cmd_data; // prevent warning for unused function argument 411 412 if (m_state == OMX_StateInvalid) 413 { 414 OMX_SWVDEC_LOG_ERROR("in invalid state"); 415 416 retval = OMX_ErrorInvalidState; 417 goto send_command_exit; 418 } 419 else if (cmp_handle == NULL) 420 { 421 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); 422 423 retval = OMX_ErrorInvalidComponent; 424 goto send_command_exit; 425 } 426 427 switch (cmd) 428 { 429 430 case OMX_CommandStateSet: 431 { 432 OMX_SWVDEC_LOG_API("%s, %s", 433 OMX_COMMANDTYPE_STRING(cmd), 434 OMX_STATETYPE_STRING((OMX_STATETYPE) param)); 435 break; 436 } 437 438 case OMX_CommandFlush: 439 case OMX_CommandPortDisable: 440 case OMX_CommandPortEnable: 441 { 442 OMX_SWVDEC_LOG_API("%s, port index %d", 443 OMX_COMMANDTYPE_STRING(cmd), 444 param); 445 446 if ((param != OMX_CORE_PORT_INDEX_IP) && 447 (param != OMX_CORE_PORT_INDEX_OP) && 448 (param != OMX_ALL)) 449 { 450 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", param); 451 452 retval = OMX_ErrorBadPortIndex; 453 } 454 455 break; 456 } 457 458 default: 459 { 460 OMX_SWVDEC_LOG_API("cmd %d, param %d", cmd, param); 461 462 OMX_SWVDEC_LOG_ERROR("cmd '%d' invalid", cmd); 463 464 retval = OMX_ErrorBadParameter; 465 break; 466 } 467 468 } // switch (cmd) 469 470 if (retval == OMX_ErrorNone) 471 { 472 if (cmp_handle == NULL) 473 { 474 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); 475 476 retval = OMX_ErrorInvalidComponent; 477 } 478 else if (m_state == OMX_StateInvalid) 479 { 480 OMX_SWVDEC_LOG_ERROR("in invalid state"); 481 482 retval = OMX_ErrorInvalidState; 483 } 484 } 485 486 if (retval != OMX_ErrorNone) 487 { 488 async_post_event(OMX_SWVDEC_EVENT_ERROR, retval, 0); 489 } 490 else 491 { 492 async_post_event(OMX_SWVDEC_EVENT_CMD, cmd, param); 493 494 sem_wait(&m_sem_cmd); 495 } 496 497 send_command_exit: 498 return retval; 499 } 500 501 /** 502 * @brief Get a parameter from component. 503 * 504 * @param[in] cmp_handle: Component handle. 505 * @param[in] param_index: Parameter index. 506 * @param[in,out] p_param_data: Pointer to parameter data. 507 * 508 * @retval OMX_ERRORTYPE 509 */ 510 OMX_ERRORTYPE omx_swvdec::get_parameter(OMX_HANDLETYPE cmp_handle, 511 OMX_INDEXTYPE param_index, 512 OMX_PTR p_param_data) 513 { 514 OMX_ERRORTYPE retval = OMX_ErrorNone; 515 516 if (m_state == OMX_StateInvalid) 517 { 518 OMX_SWVDEC_LOG_ERROR("in invalid state"); 519 520 retval = OMX_ErrorInvalidState; 521 } 522 else if (cmp_handle == NULL) 523 { 524 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); 525 526 retval = OMX_ErrorInvalidComponent; 527 } 528 else if (p_param_data == NULL) 529 { 530 OMX_SWVDEC_LOG_ERROR("p_param_data = NULL"); 531 532 retval = OMX_ErrorBadParameter; 533 } 534 535 if (retval != OMX_ErrorNone) 536 { 537 goto get_parameter_exit; 538 } 539 540 switch (param_index) 541 { 542 543 case OMX_IndexParamAudioInit: 544 { 545 OMX_PORT_PARAM_TYPE *p_port_param = 546 (OMX_PORT_PARAM_TYPE *) p_param_data; 547 548 p_port_param->nPorts = 0; 549 p_port_param->nStartPortNumber = 0; 550 551 OMX_SWVDEC_LOG_API("OMX_IndexParamAudioInit: " 552 "%d port(s), start port index %d", 553 p_port_param->nPorts, 554 p_port_param->nStartPortNumber); 555 break; 556 } 557 558 case OMX_IndexParamImageInit: 559 { 560 OMX_PORT_PARAM_TYPE *p_port_param = 561 (OMX_PORT_PARAM_TYPE *) p_param_data; 562 563 p_port_param->nPorts = 0; 564 p_port_param->nStartPortNumber = 0; 565 566 OMX_SWVDEC_LOG_API("OMX_IndexParamImageInit: " 567 "%d port(s), start port index %d", 568 p_port_param->nPorts, 569 p_port_param->nStartPortNumber); 570 break; 571 } 572 573 case OMX_IndexParamVideoInit: 574 { 575 OMX_PORT_PARAM_TYPE *p_port_param = 576 (OMX_PORT_PARAM_TYPE *) p_param_data; 577 578 p_port_param->nPorts = 2; 579 p_port_param->nStartPortNumber = 0; 580 581 OMX_SWVDEC_LOG_API("OMX_IndexParamVideoInit: " 582 "%d port(s), start port index %d", 583 p_port_param->nPorts, 584 p_port_param->nStartPortNumber); 585 break; 586 } 587 588 case OMX_IndexParamOtherInit: 589 { 590 OMX_PORT_PARAM_TYPE *p_port_param = 591 (OMX_PORT_PARAM_TYPE *) p_param_data; 592 593 p_port_param->nPorts = 0; 594 p_port_param->nStartPortNumber = 0; 595 596 OMX_SWVDEC_LOG_API("OMX_IndexParamOtherInit: " 597 "%d port(s), start port index %d", 598 p_port_param->nPorts, 599 p_port_param->nStartPortNumber); 600 break; 601 } 602 603 case OMX_IndexConfigPriorityMgmt: 604 { 605 OMX_PRIORITYMGMTTYPE *p_prio_mgmt = 606 (OMX_PRIORITYMGMTTYPE *) p_param_data; 607 608 OMX_SWVDEC_LOG_API("OMX_IndexConfigPriorityMgmt"); 609 610 memcpy(p_prio_mgmt, &m_prio_mgmt, sizeof(OMX_PRIORITYMGMTTYPE)); 611 break; 612 } 613 614 case OMX_IndexParamStandardComponentRole: 615 { 616 OMX_PARAM_COMPONENTROLETYPE *p_cmp_role = 617 (OMX_PARAM_COMPONENTROLETYPE *) p_param_data; 618 619 strlcpy((char *) p_cmp_role->cRole, 620 m_role_name, 621 OMX_MAX_STRINGNAME_SIZE); 622 623 OMX_SWVDEC_LOG_API("OMX_IndexParamStandardComponentRole: %s", 624 p_cmp_role->cRole); 625 break; 626 } 627 628 case OMX_IndexParamPortDefinition: 629 { 630 OMX_PARAM_PORTDEFINITIONTYPE *p_port_def = 631 (OMX_PARAM_PORTDEFINITIONTYPE *) p_param_data; 632 633 OMX_SWVDEC_LOG_API("OMX_IndexParamPortDefinition, port index %d", 634 p_port_def->nPortIndex); 635 636 retval = get_port_definition(p_port_def); 637 break; 638 } 639 640 case OMX_IndexParamCompBufferSupplier: 641 { 642 OMX_PARAM_BUFFERSUPPLIERTYPE *p_buffer_supplier = 643 (OMX_PARAM_BUFFERSUPPLIERTYPE *) p_param_data; 644 645 OMX_SWVDEC_LOG_API("OMX_IndexParamCompBufferSupplier, port index %d", 646 p_buffer_supplier->nPortIndex); 647 648 if ((p_buffer_supplier->nPortIndex == OMX_CORE_PORT_INDEX_IP) || 649 (p_buffer_supplier->nPortIndex == OMX_CORE_PORT_INDEX_OP)) 650 { 651 p_buffer_supplier->eBufferSupplier = OMX_BufferSupplyUnspecified; 652 } 653 else 654 { 655 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", 656 p_buffer_supplier->nPortIndex); 657 658 retval = OMX_ErrorBadPortIndex; 659 } 660 661 break; 662 } 663 664 case OMX_IndexParamVideoPortFormat: 665 { 666 OMX_VIDEO_PARAM_PORTFORMATTYPE *p_port_format = 667 (OMX_VIDEO_PARAM_PORTFORMATTYPE *) p_param_data; 668 669 OMX_SWVDEC_LOG_API("OMX_IndexParamVideoPortFormat, " 670 "port index %d, index %d", 671 p_port_format->nPortIndex, 672 p_port_format->nIndex); 673 674 retval = get_video_port_format(p_port_format); 675 break; 676 } 677 678 case OMX_IndexParamVideoMpeg2: 679 { 680 OMX_SWVDEC_LOG_ERROR("OMX_IndexParamVideoMpeg2: unsupported"); 681 682 retval = OMX_ErrorUnsupportedIndex; 683 break; 684 } 685 686 case OMX_IndexParamVideoMpeg4: 687 { 688 OMX_SWVDEC_LOG_API("OMX_IndexParamVideoMpeg4: unsupported"); 689 690 retval = OMX_ErrorUnsupportedIndex; 691 break; 692 } 693 694 case OMX_IndexParamVideoAvc: 695 { 696 OMX_SWVDEC_LOG_API("OMX_IndexParamVideoAvc: unsupported"); 697 698 retval = OMX_ErrorUnsupportedIndex; 699 break; 700 } 701 702 case OMX_IndexParamVideoH263: 703 { 704 OMX_SWVDEC_LOG_API("OMX_IndexParamVideoH263: unsupported"); 705 706 retval = OMX_ErrorUnsupportedIndex; 707 break; 708 } 709 710 case OMX_IndexParamVideoProfileLevelQuerySupported: 711 { 712 OMX_VIDEO_PARAM_PROFILELEVELTYPE *p_profilelevel = 713 (OMX_VIDEO_PARAM_PROFILELEVELTYPE *) p_param_data; 714 715 OMX_SWVDEC_LOG_API("OMX_IndexParamVideoProfileLevelQuerySupported, " 716 "port index %d, profile index %d", 717 p_profilelevel->nPortIndex, 718 p_profilelevel->nProfileIndex); 719 720 retval = get_supported_profilelevel(p_profilelevel); 721 break; 722 } 723 724 default: 725 { 726 /** 727 * Vendor-specific extension indices checked here since they are not 728 * part of the OMX_INDEXTYPE enumerated type. 729 */ 730 731 switch ((OMX_QCOM_EXTN_INDEXTYPE) param_index) 732 { 733 734 case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage: 735 { 736 GetAndroidNativeBufferUsageParams *p_buffer_usage = 737 (GetAndroidNativeBufferUsageParams *) p_param_data; 738 739 OMX_SWVDEC_LOG_API( 740 "OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage, " 741 "port index %d", p_buffer_usage->nPortIndex); 742 743 if (p_buffer_usage->nPortIndex == OMX_CORE_PORT_INDEX_OP) 744 { 745 p_buffer_usage->nUsage = (GRALLOC_USAGE_PRIVATE_IOMMU_HEAP | 746 GRALLOC_USAGE_SW_READ_OFTEN | 747 GRALLOC_USAGE_SW_WRITE_OFTEN); 748 } 749 else 750 { 751 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", 752 p_buffer_usage->nPortIndex); 753 754 retval = OMX_ErrorBadPortIndex; 755 } 756 break; 757 } 758 759 case OMX_QcomIndexFlexibleYUVDescription: 760 { 761 OMX_SWVDEC_LOG_API("OMX_QcomIndexFlexibleYUVDescription"); 762 763 retval = describe_color_format((DescribeColorFormatParams *) 764 p_param_data); 765 break; 766 } 767 768 default: 769 { 770 OMX_SWVDEC_LOG_ERROR("param index '0x%08x' invalid", 771 (OMX_QCOM_EXTN_INDEXTYPE) param_index); 772 773 retval = OMX_ErrorBadParameter; 774 break; 775 } 776 777 } // switch ((OMX_QCOM_EXTN_INDEXTYPE) param_index) 778 779 } // default case 780 781 } // switch (param_index) 782 783 get_parameter_exit: 784 return retval; 785 } 786 787 /** 788 * @brief Set a parameter to component. 789 * 790 * @param[in] cmp_handle: Component handle. 791 * @param[in] param_index: Parameter index. 792 * @param[in] p_param_data: Pointer to parameter data. 793 * 794 * @retval OMX_ERRORTYPE 795 */ 796 OMX_ERRORTYPE omx_swvdec::set_parameter(OMX_HANDLETYPE cmp_handle, 797 OMX_INDEXTYPE param_index, 798 OMX_PTR p_param_data) 799 { 800 OMX_ERRORTYPE retval = OMX_ErrorNone; 801 802 if (m_state == OMX_StateInvalid) 803 { 804 OMX_SWVDEC_LOG_ERROR("in invalid state"); 805 806 retval = OMX_ErrorInvalidState; 807 } 808 else if (cmp_handle == NULL) 809 { 810 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); 811 812 retval = OMX_ErrorInvalidComponent; 813 } 814 else if (p_param_data == NULL) 815 { 816 OMX_SWVDEC_LOG_ERROR("p_param_data = NULL"); 817 818 retval = OMX_ErrorBadParameter; 819 } 820 else if ((m_state != OMX_StateLoaded) && 821 (m_port_reconfig_inprogress == false)) 822 { 823 OMX_SWVDEC_LOG_ERROR("disallowed in state %s", 824 OMX_STATETYPE_STRING(m_state)); 825 826 retval = OMX_ErrorIncorrectStateOperation; 827 } 828 829 if (retval != OMX_ErrorNone) 830 { 831 goto set_parameter_exit; 832 } 833 834 switch (param_index) 835 { 836 837 case OMX_IndexParamPriorityMgmt: 838 { 839 OMX_PRIORITYMGMTTYPE *p_prio_mgmt = 840 (OMX_PRIORITYMGMTTYPE *) p_param_data; 841 842 OMX_SWVDEC_LOG_API("OMX_IndexConfigPriorityMgmt: " 843 "group ID %d, group priority %d", 844 p_prio_mgmt->nGroupID, 845 p_prio_mgmt->nGroupPriority); 846 847 if (m_state != OMX_StateLoaded) 848 { 849 OMX_SWVDEC_LOG_ERROR("'%d' state invalid; " 850 "should be in loaded state", 851 m_state); 852 853 retval = OMX_ErrorIncorrectStateOperation; 854 } 855 else 856 { 857 memcpy(&m_prio_mgmt, p_prio_mgmt, sizeof(OMX_PRIORITYMGMTTYPE)); 858 } 859 860 break; 861 } 862 863 case OMX_IndexParamStandardComponentRole: 864 { 865 OMX_PARAM_COMPONENTROLETYPE *p_cmp_role = 866 (OMX_PARAM_COMPONENTROLETYPE *) p_param_data; 867 868 OMX_SWVDEC_LOG_API("OMX_IndexParamStandardComponentRole '%s'", 869 p_cmp_role->cRole); 870 871 if (m_state != OMX_StateLoaded) 872 { 873 OMX_SWVDEC_LOG_ERROR("'%d' state invalid; " 874 "should be in loaded state", 875 m_state); 876 877 retval = OMX_ErrorIncorrectStateOperation; 878 } 879 else 880 { 881 if (strncmp((char *) p_cmp_role->cRole, 882 m_role_name, 883 OMX_MAX_STRINGNAME_SIZE)) 884 { 885 OMX_SWVDEC_LOG_ERROR("'%s': invalid component role name", 886 p_cmp_role->cRole); 887 888 retval = OMX_ErrorBadParameter; 889 } 890 } 891 892 break; 893 } 894 895 case OMX_IndexParamPortDefinition: 896 { 897 OMX_PARAM_PORTDEFINITIONTYPE *p_port_def = 898 (OMX_PARAM_PORTDEFINITIONTYPE *) p_param_data; 899 900 OMX_SWVDEC_LOG_API("OMX_IndexParamPortDefinition, port index %d", 901 p_port_def->nPortIndex); 902 903 if ((m_state != OMX_StateLoaded) && 904 (((p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_IP) && 905 (m_port_ip.enabled == OMX_TRUE) && 906 (m_port_ip.populated == OMX_TRUE)) || 907 ((p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_OP) && 908 (m_port_op.enabled == OMX_TRUE) && 909 (m_port_op.populated == OMX_TRUE)))) 910 { 911 OMX_SWVDEC_LOG_ERROR("OMX_IndexParamPortDefinition " 912 "disallowed in state %s " 913 "while port index %d is enabled & populated", 914 OMX_STATETYPE_STRING(m_state), 915 p_port_def->nPortIndex); 916 917 retval = OMX_ErrorIncorrectStateOperation; 918 } 919 else 920 { 921 retval = set_port_definition(p_port_def); 922 } 923 924 break; 925 } 926 927 case OMX_IndexParamCompBufferSupplier: 928 { 929 OMX_PARAM_BUFFERSUPPLIERTYPE *p_buffer_supplier = 930 (OMX_PARAM_BUFFERSUPPLIERTYPE *) p_param_data; 931 932 OMX_SWVDEC_LOG_API("OMX_IndexParamCompBufferSupplier: " 933 "port index %d, buffer supplier %d", 934 p_buffer_supplier->nPortIndex, 935 (int) p_buffer_supplier->eBufferSupplier); 936 937 if ((p_buffer_supplier->nPortIndex != OMX_CORE_PORT_INDEX_IP) && 938 (p_buffer_supplier->nPortIndex != OMX_CORE_PORT_INDEX_OP)) 939 { 940 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", 941 p_buffer_supplier->nPortIndex); 942 943 retval = OMX_ErrorBadPortIndex; 944 } 945 946 break; 947 } 948 949 case OMX_IndexParamVideoPortFormat: 950 { 951 OMX_VIDEO_PARAM_PORTFORMATTYPE *p_port_format = 952 (OMX_VIDEO_PARAM_PORTFORMATTYPE *) p_param_data; 953 954 OMX_SWVDEC_LOG_API("OMX_IndexParamVideoPortFormat, port index %d", 955 p_port_format->nPortIndex); 956 957 if ((m_state != OMX_StateLoaded) && 958 (((p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_IP) && 959 (m_port_ip.enabled == OMX_TRUE) && 960 (m_port_ip.populated == OMX_TRUE)) || 961 ((p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_OP) && 962 (m_port_op.enabled == OMX_TRUE) && 963 (m_port_op.populated == OMX_TRUE)))) 964 { 965 OMX_SWVDEC_LOG_ERROR("OMX_IndexParamVideoPortFormat " 966 "disallowed in state %s " 967 "while port index %d is enabled & populated", 968 OMX_STATETYPE_STRING(m_state), 969 p_port_format->nPortIndex); 970 971 retval = OMX_ErrorIncorrectStateOperation; 972 } 973 else 974 { 975 retval = set_video_port_format(p_port_format); 976 } 977 978 break; 979 } 980 981 case OMX_IndexParamVideoMpeg2: 982 { 983 OMX_SWVDEC_LOG_ERROR("OMX_IndexParamVideoMpeg2 unsupported"); 984 985 retval = OMX_ErrorUnsupportedIndex; 986 break; 987 } 988 989 case OMX_IndexParamVideoMpeg4: 990 { 991 OMX_SWVDEC_LOG_API("OMX_IndexParamVideoMpeg4 unsupported"); 992 993 retval = OMX_ErrorUnsupportedIndex; 994 break; 995 } 996 997 case OMX_IndexParamVideoAvc: 998 { 999 OMX_SWVDEC_LOG_API("OMX_IndexParamVideoAvc unsupported"); 1000 1001 retval = OMX_ErrorUnsupportedIndex; 1002 break; 1003 } 1004 1005 case OMX_IndexParamVideoH263: 1006 { 1007 OMX_SWVDEC_LOG_API("OMX_IndexParamVideoH263 unsupported"); 1008 1009 retval = OMX_ErrorUnsupportedIndex; 1010 break; 1011 } 1012 1013 default: 1014 { 1015 /** 1016 * Vendor-specific extension indices checked here since they are not 1017 * part of the OMX_INDEXTYPE enumerated type. 1018 */ 1019 1020 switch ((OMX_QCOM_EXTN_INDEXTYPE) param_index) 1021 { 1022 1023 case OMX_QcomIndexPortDefn: 1024 { 1025 OMX_QCOM_PARAM_PORTDEFINITIONTYPE *p_port_def = 1026 (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) p_param_data; 1027 1028 OMX_SWVDEC_LOG_API("OMX_QcomIndexPortDefn, port index %d", 1029 p_port_def->nPortIndex); 1030 1031 if ((m_state != OMX_StateLoaded) && 1032 (((p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_IP) && 1033 (m_port_ip.enabled == OMX_TRUE) && 1034 (m_port_ip.populated == OMX_TRUE)) || 1035 ((p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_OP) && 1036 (m_port_op.enabled == OMX_TRUE) && 1037 (m_port_op.populated == OMX_TRUE)))) 1038 { 1039 OMX_SWVDEC_LOG_ERROR("OMX_QcomIndexPortDefn " 1040 "disallowed in state %s " 1041 "while port index %d " 1042 "is enabled & populated", 1043 OMX_STATETYPE_STRING(m_state), 1044 p_port_def->nPortIndex); 1045 1046 retval = OMX_ErrorIncorrectStateOperation; 1047 } 1048 else 1049 { 1050 retval = set_port_definition_qcom(p_port_def); 1051 } 1052 1053 break; 1054 } 1055 1056 case OMX_QcomIndexParamVideoDivx: 1057 { 1058 OMX_SWVDEC_LOG_API("OMX_QcomIndexParamVideoDivx"); 1059 1060 break; 1061 } 1062 1063 case OMX_QcomIndexParamVideoSyncFrameDecodingMode: 1064 { 1065 OMX_SWVDEC_LOG_API("OMX_QcomIndexParamVideoSyncFrameDecodingMode"); 1066 1067 m_sync_frame_decoding_mode = true; 1068 break; 1069 } 1070 1071 case OMX_QcomIndexParamVideoDecoderPictureOrder: 1072 { 1073 QOMX_VIDEO_DECODER_PICTURE_ORDER *p_picture_order = 1074 (QOMX_VIDEO_DECODER_PICTURE_ORDER *) p_param_data; 1075 1076 switch (p_picture_order->eOutputPictureOrder) 1077 { 1078 1079 case QOMX_VIDEO_DISPLAY_ORDER: 1080 { 1081 OMX_SWVDEC_LOG_API( 1082 "OMX_QcomIndexParamVideoDecoderPictureOrder, " 1083 "QOMX_VIDEO_DISPLAY_ORDER"); 1084 1085 break; 1086 } 1087 1088 case QOMX_VIDEO_DECODE_ORDER: 1089 { 1090 OMX_SWVDEC_LOG_API( 1091 "OMX_QcomIndexParamVideoDecoderPictureOrder, " 1092 "QOMX_VIDEO_DECODE_ORDER"); 1093 1094 OMX_SWVDEC_LOG_ERROR( 1095 "OMX_QcomIndexParamVideoDecoderPictureOrder, " 1096 "QOMX_VIDEO_DECODE_ORDER; unsupported"); 1097 1098 retval = OMX_ErrorUnsupportedSetting; 1099 break; 1100 } 1101 1102 default: 1103 { 1104 OMX_SWVDEC_LOG_ERROR( 1105 "OMX_QcomIndexParamVideoDecoderPictureOrder, %d; invalid", 1106 p_picture_order->eOutputPictureOrder); 1107 1108 retval = OMX_ErrorBadParameter; 1109 break; 1110 } 1111 1112 } 1113 1114 break; 1115 } 1116 1117 case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers: 1118 { 1119 OMX_SWVDEC_LOG_API( 1120 "OMX_GoogleAndroidIndexEnableAndroidNativeBuffers, %s", 1121 (((EnableAndroidNativeBuffersParams *) p_param_data)->enable ? 1122 "enable" : 1123 "disable")); 1124 1125 m_android_native_buffers = 1126 (bool) (((EnableAndroidNativeBuffersParams *) 1127 p_param_data)->enable); 1128 1129 break; 1130 } 1131 1132 case OMX_GoogleAndroidIndexUseAndroidNativeBuffer: 1133 { 1134 OMX_SWVDEC_LOG_ERROR("OMX_GoogleAndroidIndexUseAndroidNativeBuffer " 1135 "unsupported"); 1136 1137 retval = OMX_ErrorUnsupportedIndex; 1138 break; 1139 } 1140 1141 case OMX_QcomIndexParamEnableTimeStampReorder: 1142 { 1143 OMX_SWVDEC_LOG_API( 1144 "OMX_QcomIndexParamEnableTimeStampReorder, %s", 1145 (((QOMX_INDEXTIMESTAMPREORDER *) p_param_data)->bEnable ? 1146 "enable" : 1147 "disable")); 1148 1149 break; 1150 } 1151 1152 case OMX_QcomIndexParamVideoMetaBufferMode: 1153 { 1154 StoreMetaDataInBuffersParams *p_meta_data = 1155 (StoreMetaDataInBuffersParams *) p_param_data; 1156 1157 OMX_SWVDEC_LOG_API("OMX_QcomIndexParamVideoMetaBufferMode, " 1158 "port index %d, %s", 1159 p_meta_data->nPortIndex, 1160 (p_meta_data->bStoreMetaData ? 1161 "enable" : 1162 "disable")); 1163 1164 if (p_meta_data->nPortIndex == OMX_CORE_PORT_INDEX_OP) 1165 { 1166 if (p_meta_data->bStoreMetaData && m_meta_buffer_mode_disabled) 1167 { 1168 OMX_SWVDEC_LOG_ERROR("meta buffer mode disabled " 1169 "via ADB setprop: " 1170 "'omx_swvdec.meta_buffer.disable'"); 1171 1172 retval = OMX_ErrorBadParameter; 1173 } 1174 else 1175 { 1176 m_meta_buffer_mode = (bool) p_meta_data->bStoreMetaData; 1177 } 1178 } 1179 else 1180 { 1181 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", 1182 p_meta_data->nPortIndex); 1183 1184 retval = OMX_ErrorBadPortIndex; 1185 } 1186 1187 break; 1188 } 1189 1190 case OMX_QcomIndexParamVideoAdaptivePlaybackMode: 1191 { 1192 PrepareForAdaptivePlaybackParams *p_adaptive_playback_params = 1193 (PrepareForAdaptivePlaybackParams *) p_param_data; 1194 1195 OMX_SWVDEC_LOG_API("OMX_QcomIndexParamVideoAdaptivePlaybackMode, " 1196 "port index %d, %s, max dimensions: %d x %d", 1197 p_adaptive_playback_params->nPortIndex, 1198 (p_adaptive_playback_params->bEnable ? 1199 "enable" : 1200 "disable"), 1201 p_adaptive_playback_params->nMaxFrameWidth, 1202 p_adaptive_playback_params->nMaxFrameHeight); 1203 1204 if (p_adaptive_playback_params->nPortIndex == 1205 OMX_CORE_PORT_INDEX_OP) 1206 { 1207 if (p_adaptive_playback_params->bEnable) 1208 { 1209 m_adaptive_playback_mode = true; 1210 1211 retval = 1212 set_adaptive_playback( 1213 p_adaptive_playback_params->nMaxFrameWidth, 1214 p_adaptive_playback_params->nMaxFrameHeight); 1215 } 1216 } 1217 else 1218 { 1219 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", 1220 p_adaptive_playback_params->nPortIndex); 1221 1222 retval = OMX_ErrorBadPortIndex; 1223 } 1224 1225 break; 1226 } 1227 1228 default: 1229 { 1230 OMX_SWVDEC_LOG_ERROR("param index '0x%08x' invalid", 1231 (OMX_QCOM_EXTN_INDEXTYPE) param_index); 1232 1233 retval = OMX_ErrorBadParameter; 1234 break; 1235 } 1236 1237 } // switch ((OMX_QCOM_EXTN_INDEXTYPE) param_index) 1238 1239 break; 1240 } // default case 1241 1242 } // switch (param_index) 1243 1244 set_parameter_exit: 1245 return retval; 1246 } 1247 1248 /** 1249 * @brief Get a configuration from component. 1250 * 1251 * @param[in] cmp_handle: Component handle. 1252 * @param[in] config_index: Configuration index. 1253 * @param[in] p_config_data: Pointer to configuration data. 1254 * 1255 * @retval OMX_ERRORTYPE 1256 */ 1257 OMX_ERRORTYPE omx_swvdec::get_config(OMX_HANDLETYPE cmp_handle, 1258 OMX_INDEXTYPE config_index, 1259 OMX_PTR p_config_data) 1260 { 1261 OMX_ERRORTYPE retval = OMX_ErrorNone; 1262 1263 if (m_state == OMX_StateInvalid) 1264 { 1265 OMX_SWVDEC_LOG_ERROR("in invalid state"); 1266 1267 retval = OMX_ErrorInvalidState; 1268 } 1269 else if (cmp_handle == NULL) 1270 { 1271 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); 1272 1273 retval = OMX_ErrorInvalidComponent; 1274 } 1275 else if (p_config_data == NULL) 1276 { 1277 OMX_SWVDEC_LOG_ERROR("p_config_data = NULL"); 1278 1279 retval = OMX_ErrorBadParameter; 1280 } 1281 1282 if (retval != OMX_ErrorNone) 1283 { 1284 goto get_config_exit; 1285 } 1286 1287 switch (config_index) 1288 { 1289 1290 case OMX_IndexConfigCommonOutputCrop: 1291 { 1292 OMX_CONFIG_RECTTYPE *p_recttype = (OMX_CONFIG_RECTTYPE *) p_config_data; 1293 1294 OMX_SWVDEC_LOG_API("OMX_IndexConfigCommonOutputCrop, port index %d", 1295 p_recttype->nPortIndex); 1296 1297 if (p_recttype->nPortIndex == OMX_CORE_PORT_INDEX_OP) 1298 { 1299 if (m_dimensions_update_inprogress) 1300 { 1301 retval = get_frame_dimensions_swvdec(); 1302 1303 m_dimensions_update_inprogress = false; 1304 } 1305 1306 if (retval == OMX_ErrorNone) 1307 { 1308 p_recttype->nLeft = 0; 1309 p_recttype->nTop = 0; 1310 p_recttype->nWidth = m_frame_dimensions.width; 1311 p_recttype->nHeight = m_frame_dimensions.height; 1312 } 1313 } 1314 else 1315 { 1316 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", 1317 p_recttype->nPortIndex); 1318 1319 retval = OMX_ErrorBadPortIndex; 1320 } 1321 1322 break; 1323 } 1324 1325 default: 1326 { 1327 switch ((OMX_QCOM_EXTN_INDEXTYPE) config_index) 1328 { 1329 1330 case OMX_QcomIndexConfigInterlaced: 1331 { 1332 OMX_QCOM_CONFIG_INTERLACETYPE *p_config_interlacetype = 1333 (OMX_QCOM_CONFIG_INTERLACETYPE *) p_config_data; 1334 1335 OMX_SWVDEC_LOG_API("OMX_QcomIndexConfigInterlaced, " 1336 "port index %d, index %d", 1337 p_config_interlacetype->nPortIndex, 1338 p_config_interlacetype->nIndex); 1339 1340 if (p_config_interlacetype->nPortIndex == OMX_CORE_PORT_INDEX_OP) 1341 { 1342 if (p_config_interlacetype->nIndex == 0) 1343 { 1344 p_config_interlacetype->eInterlaceType = 1345 OMX_QCOM_InterlaceFrameProgressive; 1346 } 1347 else if (p_config_interlacetype->nIndex == 1) 1348 { 1349 p_config_interlacetype->eInterlaceType = 1350 OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst; 1351 } 1352 else if (p_config_interlacetype->nIndex == 2) 1353 { 1354 p_config_interlacetype->eInterlaceType = 1355 OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst; 1356 } 1357 else 1358 { 1359 OMX_SWVDEC_LOG_ERROR("index '%d' unsupported; " 1360 "no more interlaced types", 1361 p_config_interlacetype->nIndex); 1362 1363 retval = OMX_ErrorNoMore; 1364 } 1365 } 1366 else 1367 { 1368 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", 1369 p_config_interlacetype->nPortIndex); 1370 1371 retval = OMX_ErrorBadPortIndex; 1372 } 1373 1374 break; 1375 } 1376 1377 case OMX_QcomIndexQueryNumberOfVideoDecInstance: 1378 { 1379 QOMX_VIDEO_QUERY_DECODER_INSTANCES *p_decoder_instances = 1380 (QOMX_VIDEO_QUERY_DECODER_INSTANCES *) p_config_data; 1381 1382 OMX_SWVDEC_LOG_API("OMX_QcomIndexQueryNumberOfVideoDecInstance"); 1383 1384 p_decoder_instances->nNumOfInstances = OMX_SWVDEC_NUM_INSTANCES; 1385 break; 1386 } 1387 1388 case OMX_QcomIndexConfigVideoFramePackingArrangement: 1389 { 1390 OMX_SWVDEC_LOG_API( 1391 "OMX_QcomIndexConfigVideoFramePackingArrangement"); 1392 1393 OMX_SWVDEC_LOG_ERROR( 1394 "OMX_QcomIndexConfigVideoFramePackingArrangement unsupported"); 1395 1396 retval = OMX_ErrorUnsupportedIndex; 1397 break; 1398 } 1399 1400 default: 1401 { 1402 OMX_SWVDEC_LOG_ERROR("config index '0x%08x' invalid", config_index); 1403 1404 retval = OMX_ErrorBadParameter; 1405 break; 1406 } 1407 1408 } // switch ((OMX_QCOM_EXTN_INDEXTYPE) config_index) 1409 1410 break; 1411 } 1412 1413 } // switch (config_index) 1414 1415 get_config_exit: 1416 return retval; 1417 } 1418 1419 /** 1420 * @brief Set a configuration to component. 1421 * 1422 * @retval OMX_ERRORTYPE 1423 */ 1424 OMX_ERRORTYPE omx_swvdec::set_config(OMX_HANDLETYPE cmp_handle, 1425 OMX_INDEXTYPE config_index, 1426 OMX_PTR p_config_data) 1427 { 1428 (void) cmp_handle; 1429 (void) p_config_data; 1430 1431 OMX_SWVDEC_LOG_API("config index 0x%08x", config_index); 1432 1433 OMX_SWVDEC_LOG_ERROR("not implemented"); 1434 1435 return OMX_ErrorNotImplemented; 1436 } 1437 1438 /** 1439 * @brief Translate a vendor-specific extension string to a standard index type. 1440 * 1441 * @param[in] cmp_handle: Component handle. 1442 * @param[in] param_name: Parameter name (extension string). 1443 * @param[in,out] p_index_type: Pointer to extension string's index type. 1444 * 1445 * @retval OMX_ERRORTYPE 1446 */ 1447 OMX_ERRORTYPE omx_swvdec::get_extension_index(OMX_HANDLETYPE cmp_handle, 1448 OMX_STRING param_name, 1449 OMX_INDEXTYPE *p_index_type) 1450 { 1451 OMX_ERRORTYPE retval = OMX_ErrorNone; 1452 1453 if (m_state == OMX_StateInvalid) 1454 { 1455 OMX_SWVDEC_LOG_ERROR("in invalid state"); 1456 1457 retval = OMX_ErrorInvalidState; 1458 } 1459 else if (cmp_handle == NULL) 1460 { 1461 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); 1462 1463 retval = OMX_ErrorInvalidComponent; 1464 } 1465 else if (p_index_type == NULL) 1466 { 1467 OMX_SWVDEC_LOG_ERROR("p_index_type = NULL"); 1468 1469 retval = OMX_ErrorBadParameter; 1470 } 1471 1472 if (retval != OMX_ErrorNone) 1473 { 1474 goto get_extension_index_exit; 1475 } 1476 1477 OMX_SWVDEC_LOG_API("'%s'", param_name); 1478 1479 if (!strncmp(param_name, 1480 "OMX.QCOM.index.param.video.SyncFrameDecodingMode", 1481 OMX_MAX_STRINGNAME_SIZE)) 1482 { 1483 *p_index_type = 1484 (OMX_INDEXTYPE) OMX_QcomIndexParamVideoSyncFrameDecodingMode; 1485 } 1486 else if (!strncmp(param_name, 1487 "OMX.QCOM.index.param.IndexExtraData", 1488 OMX_MAX_STRINGNAME_SIZE)) 1489 { 1490 *p_index_type = (OMX_INDEXTYPE) OMX_QcomIndexParamIndexExtraDataType; 1491 } 1492 else if (!strncmp(param_name, 1493 "OMX.google.android.index.enableAndroidNativeBuffers", 1494 OMX_MAX_STRINGNAME_SIZE)) 1495 { 1496 *p_index_type = 1497 (OMX_INDEXTYPE) OMX_GoogleAndroidIndexEnableAndroidNativeBuffers; 1498 } 1499 else if (!strncmp(param_name, 1500 "OMX.google.android.index.useAndroidNativeBuffer2", 1501 OMX_MAX_STRINGNAME_SIZE)) 1502 { 1503 *p_index_type = 1504 (OMX_INDEXTYPE) OMX_GoogleAndroidIndexUseAndroidNativeBuffer2; 1505 } 1506 else if (!strncmp(param_name, 1507 "OMX.google.android.index.useAndroidNativeBuffer", 1508 OMX_MAX_STRINGNAME_SIZE)) 1509 { 1510 *p_index_type = 1511 (OMX_INDEXTYPE) OMX_GoogleAndroidIndexUseAndroidNativeBuffer; 1512 } 1513 else if (!strncmp(param_name, 1514 "OMX.google.android.index.getAndroidNativeBufferUsage", 1515 OMX_MAX_STRINGNAME_SIZE)) 1516 { 1517 *p_index_type = 1518 (OMX_INDEXTYPE) OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage; 1519 } 1520 else if (!strncmp(param_name, 1521 "OMX.google.android.index.storeMetaDataInBuffers", 1522 OMX_MAX_STRINGNAME_SIZE)) 1523 { 1524 *p_index_type = (OMX_INDEXTYPE) OMX_QcomIndexParamVideoMetaBufferMode; 1525 } 1526 else if (!strncmp(param_name, 1527 "OMX.google.android.index.describeColorFormat", 1528 OMX_MAX_STRINGNAME_SIZE)) 1529 { 1530 *p_index_type = (OMX_INDEXTYPE) OMX_QcomIndexFlexibleYUVDescription; 1531 } 1532 else if (!strncmp(param_name, 1533 "OMX.google.android.index.prepareForAdaptivePlayback", 1534 OMX_MAX_STRINGNAME_SIZE)) 1535 { 1536 *p_index_type = 1537 (OMX_INDEXTYPE) OMX_QcomIndexParamVideoAdaptivePlaybackMode; 1538 } 1539 else 1540 { 1541 OMX_SWVDEC_LOG_ERROR("'%s': not implemented", param_name); 1542 1543 retval = OMX_ErrorNotImplemented; 1544 } 1545 1546 get_extension_index_exit: 1547 return retval; 1548 } 1549 1550 /** 1551 * @brief Get component state. 1552 * 1553 * @param[in] cmp_handle: Component handle. 1554 * @param[in,out] p_state: Pointer to state variable. 1555 * 1556 * @retval OMX_ERRORTYPE 1557 */ 1558 OMX_ERRORTYPE omx_swvdec::get_state(OMX_HANDLETYPE cmp_handle, 1559 OMX_STATETYPE *p_state) 1560 { 1561 OMX_ERRORTYPE retval = OMX_ErrorNone; 1562 1563 if (cmp_handle == NULL) 1564 { 1565 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); 1566 1567 retval = OMX_ErrorInvalidComponent; 1568 } 1569 else 1570 { 1571 OMX_SWVDEC_LOG_API("%s", OMX_STATETYPE_STRING(m_state)); 1572 1573 *p_state = m_state; 1574 } 1575 1576 return retval; 1577 } 1578 1579 /** 1580 * @brief Component tunnel request. 1581 * 1582 * @retval OMX_ErrorNotImplemented 1583 */ 1584 OMX_ERRORTYPE omx_swvdec::component_tunnel_request( 1585 OMX_HANDLETYPE cmp_handle, 1586 OMX_U32 port, 1587 OMX_HANDLETYPE peer_component, 1588 OMX_U32 peer_port, 1589 OMX_TUNNELSETUPTYPE *p_tunnel_setup) 1590 { 1591 (void) cmp_handle; 1592 (void) port; 1593 (void) peer_component; 1594 (void) peer_port; 1595 (void) p_tunnel_setup; 1596 1597 OMX_SWVDEC_LOG_API(""); 1598 1599 OMX_SWVDEC_LOG_ERROR("not implemented"); 1600 1601 return OMX_ErrorNotImplemented; 1602 } 1603 1604 /** 1605 * @brief Use buffer. 1606 * 1607 * @param[in] cmp_handle: Component handle. 1608 * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type 1609 * structure. 1610 * @param[in] port: Port index. 1611 * @param[in] p_app_data: Pointer to IL client app data. 1612 * @param[in] bytes: Size of buffer to be allocated in bytes. 1613 * @param[in] p_buffer: Pointer to buffer to be used. 1614 * 1615 * @retval OMX_ERRORTYPE 1616 */ 1617 OMX_ERRORTYPE omx_swvdec::use_buffer(OMX_HANDLETYPE cmp_handle, 1618 OMX_BUFFERHEADERTYPE **pp_buffer_hdr, 1619 OMX_U32 port, 1620 OMX_PTR p_app_data, 1621 OMX_U32 bytes, 1622 OMX_U8 *p_buffer) 1623 { 1624 OMX_ERRORTYPE retval = OMX_ErrorNone; 1625 1626 if (m_state == OMX_StateInvalid) 1627 { 1628 OMX_SWVDEC_LOG_ERROR("in invalid state"); 1629 1630 retval = OMX_ErrorInvalidState; 1631 } 1632 else if (cmp_handle == NULL) 1633 { 1634 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); 1635 1636 retval = OMX_ErrorInvalidComponent; 1637 } 1638 else if (pp_buffer_hdr == NULL) 1639 { 1640 OMX_SWVDEC_LOG_ERROR("pp_buffer_hdr = NULL"); 1641 1642 retval = OMX_ErrorBadParameter; 1643 } 1644 else 1645 { 1646 OMX_SWVDEC_LOG_API("port index %d, %p", port, p_buffer); 1647 1648 if (port == OMX_CORE_PORT_INDEX_OP) 1649 { 1650 retval = buffer_use_op(pp_buffer_hdr, p_app_data, bytes, p_buffer); 1651 1652 if (retval == OMX_ErrorNone) 1653 { 1654 SWVDEC_STATUS retval_swvdec; 1655 1656 if ((m_status_flags & (1 << PENDING_STATE_LOADED_TO_IDLE)) && 1657 (m_port_ip.populated == OMX_TRUE) && 1658 (m_port_op.populated == OMX_TRUE)) 1659 { 1660 if ((retval_swvdec = swvdec_start(m_swvdec_handle)) != 1661 SWVDEC_STATUS_SUCCESS) 1662 { 1663 OMX_SWVDEC_LOG_ERROR("failed to start SwVdec"); 1664 1665 retval = retval_swvdec2omx(retval_swvdec); 1666 goto use_buffer_exit; 1667 } 1668 1669 m_status_flags &= ~(1 << PENDING_STATE_LOADED_TO_IDLE); 1670 1671 async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, 1672 OMX_CommandStateSet, 1673 OMX_StateIdle); 1674 } 1675 1676 if ((m_status_flags & (1 << PENDING_PORT_ENABLE_OP)) && 1677 (m_port_op.populated == OMX_TRUE)) 1678 { 1679 if (m_port_reconfig_inprogress) 1680 { 1681 if ((retval_swvdec = swvdec_start(m_swvdec_handle)) != 1682 SWVDEC_STATUS_SUCCESS) 1683 { 1684 OMX_SWVDEC_LOG_ERROR("failed to start SwVdec"); 1685 1686 retval = retval_swvdec2omx(retval_swvdec); 1687 } 1688 } 1689 1690 m_status_flags &= ~(1 << PENDING_PORT_ENABLE_OP); 1691 1692 async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, 1693 OMX_CommandPortEnable, 1694 OMX_CORE_PORT_INDEX_OP); 1695 } 1696 } 1697 } 1698 else 1699 { 1700 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", port); 1701 1702 retval = OMX_ErrorBadPortIndex; 1703 } 1704 } 1705 1706 use_buffer_exit: 1707 return retval; 1708 } 1709 1710 /** 1711 * @brief Allocate new buffer & associated header. 1712 * 1713 * @param[in] cmp_handle: Component handle. 1714 * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type 1715 * structure. 1716 * @param[in] port: Port index. 1717 * @param[in] p_app_data: Pointer to IL client app data. 1718 * @param[in] bytes: Size of buffer to be allocated in bytes. 1719 * 1720 * @retval OMX_ERRORTYPE 1721 */ 1722 OMX_ERRORTYPE omx_swvdec::allocate_buffer(OMX_HANDLETYPE cmp_handle, 1723 OMX_BUFFERHEADERTYPE **pp_buffer_hdr, 1724 OMX_U32 port, 1725 OMX_PTR p_app_data, 1726 OMX_U32 bytes) 1727 { 1728 OMX_ERRORTYPE retval = OMX_ErrorNone; 1729 1730 if (m_state == OMX_StateInvalid) 1731 { 1732 OMX_SWVDEC_LOG_ERROR("in invalid state"); 1733 1734 retval = OMX_ErrorInvalidState; 1735 } 1736 else if (cmp_handle == NULL) 1737 { 1738 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); 1739 1740 retval = OMX_ErrorInvalidComponent; 1741 } 1742 else if (pp_buffer_hdr == NULL) 1743 { 1744 OMX_SWVDEC_LOG_ERROR("pp_buffer_hdr = NULL"); 1745 1746 retval = OMX_ErrorBadParameter; 1747 } 1748 else 1749 { 1750 OMX_SWVDEC_LOG_API("port index %d, %d bytes", port, bytes); 1751 1752 if (port == OMX_CORE_PORT_INDEX_IP) 1753 { 1754 retval = buffer_allocate_ip(pp_buffer_hdr, 1755 p_app_data, 1756 bytes); 1757 } 1758 else if (port == OMX_CORE_PORT_INDEX_OP) 1759 { 1760 if (m_meta_buffer_mode == true) 1761 { 1762 OMX_SWVDEC_LOG_ERROR("'meta buffer mode' enabled"); 1763 1764 retval = OMX_ErrorBadParameter; 1765 } 1766 else if (m_android_native_buffers == true) 1767 { 1768 OMX_SWVDEC_LOG_ERROR("'android native buffers' enabled"); 1769 1770 retval = OMX_ErrorBadParameter; 1771 } 1772 else 1773 { 1774 retval = buffer_allocate_op(pp_buffer_hdr, 1775 p_app_data, 1776 bytes); 1777 } 1778 } 1779 else 1780 { 1781 OMX_SWVDEC_LOG_ERROR("port index %d invalid", port); 1782 1783 retval = OMX_ErrorBadPortIndex; 1784 } 1785 1786 if (retval == OMX_ErrorNone) 1787 { 1788 SWVDEC_STATUS retval_swvdec; 1789 1790 if ((m_status_flags & (1 << PENDING_STATE_LOADED_TO_IDLE)) && 1791 (m_port_ip.populated == OMX_TRUE) && 1792 (m_port_op.populated == OMX_TRUE)) 1793 { 1794 if ((retval_swvdec = swvdec_start(m_swvdec_handle)) != 1795 SWVDEC_STATUS_SUCCESS) 1796 { 1797 OMX_SWVDEC_LOG_ERROR("failed to start SwVdec"); 1798 1799 retval = retval_swvdec2omx(retval_swvdec); 1800 goto allocate_buffer_exit; 1801 } 1802 1803 m_status_flags &= ~(1 << PENDING_STATE_LOADED_TO_IDLE); 1804 1805 async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, 1806 OMX_CommandStateSet, 1807 OMX_StateIdle); 1808 } 1809 1810 if ((m_status_flags & (1 << PENDING_PORT_ENABLE_IP)) && 1811 (m_port_ip.populated == OMX_TRUE)) 1812 { 1813 m_status_flags &= ~(1 << PENDING_PORT_ENABLE_IP); 1814 1815 async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, 1816 OMX_CommandPortEnable, 1817 OMX_CORE_PORT_INDEX_IP); 1818 } 1819 1820 if ((m_status_flags & (1 << PENDING_PORT_ENABLE_OP)) && 1821 (m_port_op.populated == OMX_TRUE)) 1822 { 1823 if (m_port_reconfig_inprogress) 1824 { 1825 if ((retval_swvdec = swvdec_start(m_swvdec_handle)) != 1826 SWVDEC_STATUS_SUCCESS) 1827 { 1828 OMX_SWVDEC_LOG_ERROR("failed to start SwVdec"); 1829 1830 retval = retval_swvdec2omx(retval_swvdec); 1831 } 1832 } 1833 1834 m_status_flags &= ~(1 << PENDING_PORT_ENABLE_OP); 1835 1836 async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, 1837 OMX_CommandPortEnable, 1838 OMX_CORE_PORT_INDEX_OP); 1839 } 1840 } 1841 } 1842 1843 allocate_buffer_exit: 1844 return retval; 1845 } 1846 1847 /** 1848 * @brief Release buffer & associated header. 1849 * 1850 * @param[in] cmp_handle: Component handle. 1851 * @param[in] port: Port index. 1852 * @param[in] p_buffer_hdr: Pointer to buffer's buffer header. 1853 * 1854 * @retval OMX_ERRORTYPE 1855 */ 1856 OMX_ERRORTYPE omx_swvdec::free_buffer(OMX_HANDLETYPE cmp_handle, 1857 OMX_U32 port, 1858 OMX_BUFFERHEADERTYPE *p_buffer_hdr) 1859 { 1860 OMX_ERRORTYPE retval = OMX_ErrorNone; 1861 1862 if (cmp_handle == NULL) 1863 { 1864 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); 1865 1866 retval = OMX_ErrorInvalidComponent; 1867 } 1868 else if (p_buffer_hdr == NULL) 1869 { 1870 OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL"); 1871 1872 retval = OMX_ErrorBadParameter; 1873 } 1874 else if ((port != OMX_CORE_PORT_INDEX_IP) && 1875 (port != OMX_CORE_PORT_INDEX_OP)) 1876 { 1877 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", port); 1878 1879 retval = OMX_ErrorBadPortIndex; 1880 } 1881 else if (m_state != OMX_StateIdle) 1882 { 1883 if (m_state != OMX_StateExecuting) 1884 { 1885 OMX_SWVDEC_LOG_ERROR("disallowed in state %s", 1886 OMX_STATETYPE_STRING(m_state)); 1887 1888 retval = OMX_ErrorIncorrectStateOperation; 1889 } 1890 else 1891 { 1892 if (((port == OMX_CORE_PORT_INDEX_IP) && m_port_ip.enabled) || 1893 ((port == OMX_CORE_PORT_INDEX_OP) && m_port_op.enabled)) 1894 { 1895 OMX_SWVDEC_LOG_ERROR("port index %d not disabled", port); 1896 1897 retval = OMX_ErrorBadPortIndex; 1898 } 1899 } 1900 } 1901 1902 if (retval == OMX_ErrorNone) 1903 { 1904 OMX_SWVDEC_LOG_API("port index %d, %p", port, p_buffer_hdr); 1905 1906 if (port == OMX_CORE_PORT_INDEX_IP) 1907 { 1908 retval = buffer_deallocate_ip(p_buffer_hdr); 1909 } 1910 else 1911 { 1912 retval = buffer_deallocate_op(p_buffer_hdr); 1913 } 1914 } 1915 1916 if ((retval == OMX_ErrorNone) && 1917 (m_status_flags & (1 << PENDING_STATE_IDLE_TO_LOADED))) 1918 { 1919 if ((m_port_ip.unpopulated == OMX_TRUE) && 1920 (m_port_op.unpopulated == OMX_TRUE)) 1921 { 1922 SWVDEC_STATUS retval_swvdec; 1923 1924 if ((retval_swvdec = swvdec_stop(m_swvdec_handle)) == 1925 SWVDEC_STATUS_SUCCESS) 1926 { 1927 m_status_flags &= ~(1 << PENDING_STATE_IDLE_TO_LOADED); 1928 1929 async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, 1930 OMX_CommandStateSet, 1931 OMX_StateLoaded); 1932 } 1933 else 1934 { 1935 OMX_SWVDEC_LOG_ERROR("failed to stop SwVdec"); 1936 1937 retval = retval_swvdec2omx(retval_swvdec); 1938 } 1939 } 1940 } 1941 1942 if ((retval == OMX_ErrorNone) && 1943 (m_status_flags & (1 << PENDING_PORT_DISABLE_IP)) && 1944 m_port_ip.unpopulated) 1945 { 1946 m_status_flags &= ~(1 << PENDING_PORT_DISABLE_IP); 1947 1948 async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, 1949 OMX_CommandPortDisable, 1950 OMX_CORE_PORT_INDEX_IP); 1951 } 1952 1953 if ((retval == OMX_ErrorNone) && 1954 (m_status_flags & (1 << PENDING_PORT_DISABLE_OP)) && 1955 m_port_op.unpopulated) 1956 { 1957 if (m_port_reconfig_inprogress) 1958 { 1959 SWVDEC_STATUS retval_swvdec; 1960 1961 if ((retval_swvdec = swvdec_stop(m_swvdec_handle)) != 1962 SWVDEC_STATUS_SUCCESS) 1963 { 1964 OMX_SWVDEC_LOG_ERROR("failed to stop SwVdec"); 1965 1966 retval = retval_swvdec2omx(retval_swvdec); 1967 } 1968 } 1969 1970 m_status_flags &= ~(1 << PENDING_PORT_DISABLE_OP); 1971 1972 async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, 1973 OMX_CommandPortDisable, 1974 OMX_CORE_PORT_INDEX_OP); 1975 } 1976 1977 return retval; 1978 } 1979 1980 /** 1981 * @brief Send a buffer to component's input port to be emptied. 1982 * 1983 * @param[in] cmp_handle: Component handle. 1984 * @param[in] p_buffer_hdr: Pointer to buffer's buffer header. 1985 * 1986 * @retval OMX_ERRORTYPE 1987 */ 1988 OMX_ERRORTYPE omx_swvdec::empty_this_buffer(OMX_HANDLETYPE cmp_handle, 1989 OMX_BUFFERHEADERTYPE *p_buffer_hdr) 1990 { 1991 OMX_ERRORTYPE retval = OMX_ErrorNone; 1992 1993 unsigned int ii; 1994 1995 if (m_state == OMX_StateInvalid) 1996 { 1997 OMX_SWVDEC_LOG_ERROR("in invalid state"); 1998 1999 retval = OMX_ErrorInvalidState; 2000 } 2001 else if (cmp_handle == NULL) 2002 { 2003 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); 2004 2005 retval = OMX_ErrorInvalidComponent; 2006 } 2007 else if (p_buffer_hdr == NULL) 2008 { 2009 OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL"); 2010 2011 retval = OMX_ErrorBadParameter; 2012 } 2013 else if (p_buffer_hdr->pBuffer == NULL) 2014 { 2015 OMX_SWVDEC_LOG_ERROR("p_buffer_hdr->pBuffer = NULL"); 2016 2017 retval = OMX_ErrorBadParameter; 2018 } 2019 else if (p_buffer_hdr->pInputPortPrivate == NULL) 2020 { 2021 OMX_SWVDEC_LOG_ERROR("p_buffer_hdr->pInputPortPrivate = NULL"); 2022 2023 retval = OMX_ErrorBadParameter; 2024 } 2025 else if (m_port_ip.enabled == OMX_FALSE) 2026 { 2027 OMX_SWVDEC_LOG_ERROR("ip port disabled"); 2028 2029 retval = OMX_ErrorIncorrectStateOperation; 2030 } 2031 else if (p_buffer_hdr->nInputPortIndex != OMX_CORE_PORT_INDEX_IP) 2032 { 2033 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", 2034 p_buffer_hdr->nInputPortIndex); 2035 2036 retval = OMX_ErrorBadPortIndex; 2037 } 2038 2039 if (retval != OMX_ErrorNone) 2040 { 2041 goto empty_this_buffer_exit; 2042 } 2043 2044 for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++) 2045 { 2046 if (p_buffer_hdr == &(m_buffer_array_ip[ii].buffer_header)) 2047 { 2048 OMX_SWVDEC_LOG_LOW("ip buffer %p has index %d", 2049 p_buffer_hdr->pBuffer, 2050 ii); 2051 break; 2052 } 2053 } 2054 2055 if (ii == m_port_ip.def.nBufferCountActual) 2056 { 2057 OMX_SWVDEC_LOG_ERROR("ip buffer %p not found", 2058 p_buffer_hdr->pBuffer); 2059 2060 retval = OMX_ErrorBadParameter; 2061 goto empty_this_buffer_exit; 2062 } 2063 2064 OMX_SWVDEC_LOG_API("%p: buffer %p, flags 0x%08x, filled length %d, " 2065 "timestamp %lld", 2066 p_buffer_hdr, 2067 p_buffer_hdr->pBuffer, 2068 p_buffer_hdr->nFlags, 2069 p_buffer_hdr->nFilledLen, 2070 p_buffer_hdr->nTimeStamp); 2071 2072 async_post_event(OMX_SWVDEC_EVENT_ETB, 2073 (unsigned long) p_buffer_hdr, 2074 (unsigned long) ii); 2075 2076 empty_this_buffer_exit: 2077 return retval; 2078 } 2079 2080 /** 2081 * @brief Send a buffer to component's output port to be filled. 2082 * 2083 * @param[in] cmp_handle: Component handle. 2084 * @param[in] p_buffer_hdr: Pointer to buffer's buffer header. 2085 * 2086 * @retval OMX_ERRORTYPE 2087 */ 2088 OMX_ERRORTYPE omx_swvdec::fill_this_buffer(OMX_HANDLETYPE cmp_handle, 2089 OMX_BUFFERHEADERTYPE *p_buffer_hdr) 2090 { 2091 OMX_ERRORTYPE retval = OMX_ErrorNone; 2092 2093 unsigned int ii; 2094 2095 SWVDEC_BUFFER *p_buffer_swvdec; 2096 2097 if (m_state == OMX_StateInvalid) 2098 { 2099 OMX_SWVDEC_LOG_ERROR("in invalid state"); 2100 2101 retval = OMX_ErrorInvalidState; 2102 } 2103 else if (cmp_handle == NULL) 2104 { 2105 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); 2106 2107 retval = OMX_ErrorInvalidComponent; 2108 } 2109 else if (p_buffer_hdr == NULL) 2110 { 2111 OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL"); 2112 2113 retval = OMX_ErrorBadParameter; 2114 } 2115 else if (p_buffer_hdr->pBuffer == NULL) 2116 { 2117 OMX_SWVDEC_LOG_ERROR("p_buffer_hdr->pBuffer = NULL"); 2118 2119 retval = OMX_ErrorBadParameter; 2120 } 2121 else if (p_buffer_hdr->pOutputPortPrivate == NULL) 2122 { 2123 OMX_SWVDEC_LOG_ERROR("p_buffer_hdr->pOutputPortPrivate = NULL"); 2124 2125 retval = OMX_ErrorBadParameter; 2126 } 2127 else if (m_port_op.enabled == OMX_FALSE) 2128 { 2129 OMX_SWVDEC_LOG_ERROR("op port disabled"); 2130 2131 retval = OMX_ErrorIncorrectStateOperation; 2132 } 2133 else if (p_buffer_hdr->nOutputPortIndex != OMX_CORE_PORT_INDEX_OP) 2134 { 2135 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", 2136 p_buffer_hdr->nOutputPortIndex); 2137 2138 retval = OMX_ErrorBadPortIndex; 2139 } 2140 2141 if (retval != OMX_ErrorNone) 2142 { 2143 goto fill_this_buffer_exit; 2144 } 2145 2146 OMX_SWVDEC_LOG_API("%p", p_buffer_hdr); 2147 2148 for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++) 2149 { 2150 if (p_buffer_hdr == &(m_buffer_array_op[ii].buffer_header)) 2151 { 2152 OMX_SWVDEC_LOG_LOW("op buffer %p has index %d", 2153 p_buffer_hdr->pBuffer, 2154 ii); 2155 break; 2156 } 2157 } 2158 2159 if (ii == m_port_op.def.nBufferCountActual) 2160 { 2161 OMX_SWVDEC_LOG_ERROR("op buffer %p not found", 2162 p_buffer_hdr->pBuffer); 2163 2164 retval = OMX_ErrorBadParameter; 2165 goto fill_this_buffer_exit; 2166 } 2167 2168 p_buffer_swvdec = &m_buffer_array_op[ii].buffer_swvdec; 2169 2170 if (m_meta_buffer_mode) 2171 { 2172 struct VideoDecoderOutputMetaData *p_meta_data; 2173 2174 private_handle_t *p_private_handle; 2175 2176 struct vdec_bufferpayload *p_buffer_payload; 2177 2178 p_meta_data = 2179 (struct VideoDecoderOutputMetaData *) p_buffer_hdr->pBuffer; 2180 2181 p_private_handle = (private_handle_t *) (p_meta_data->pHandle); 2182 2183 p_buffer_payload = &m_buffer_array_op[ii].buffer_payload; 2184 2185 if (p_private_handle == NULL) 2186 { 2187 OMX_SWVDEC_LOG_ERROR( 2188 "p_buffer_hdr->pBuffer->pHandle = NULL"); 2189 2190 retval = OMX_ErrorBadParameter; 2191 goto fill_this_buffer_exit; 2192 } 2193 2194 pthread_mutex_lock(&m_meta_buffer_array_mutex); 2195 2196 if (m_meta_buffer_array[ii].ref_count == 0) 2197 { 2198 unsigned char *bufferaddr; 2199 2200 bufferaddr = (unsigned char *) mmap(NULL, 2201 m_port_op.def.nBufferSize, 2202 PROT_READ | PROT_WRITE, 2203 MAP_SHARED, 2204 p_private_handle->fd, 2205 0); 2206 2207 if (bufferaddr == MAP_FAILED) 2208 { 2209 OMX_SWVDEC_LOG_ERROR("mmap() failed for " 2210 "fd %d of size %d", 2211 p_private_handle->fd, 2212 m_port_op.def.nBufferSize); 2213 2214 pthread_mutex_unlock(&m_meta_buffer_array_mutex); 2215 2216 retval = OMX_ErrorInsufficientResources; 2217 goto fill_this_buffer_exit; 2218 } 2219 2220 p_buffer_payload->bufferaddr = bufferaddr; 2221 p_buffer_payload->pmem_fd = p_private_handle->fd; 2222 p_buffer_payload->buffer_len = m_port_op.def.nBufferSize; 2223 p_buffer_payload->mmaped_size = m_port_op.def.nBufferSize; 2224 2225 p_buffer_swvdec->p_buffer = bufferaddr; 2226 p_buffer_swvdec->size = m_port_op.def.nBufferSize; 2227 p_buffer_swvdec->p_client_data = (void *) ((unsigned long) ii); 2228 } 2229 2230 meta_buffer_ref_add(ii, p_buffer_payload->pmem_fd); 2231 2232 pthread_mutex_unlock(&m_meta_buffer_array_mutex); 2233 } 2234 2235 OMX_SWVDEC_LOG_LOW("%p: buffer %p", 2236 p_buffer_hdr, 2237 p_buffer_swvdec->p_buffer); 2238 2239 async_post_event(OMX_SWVDEC_EVENT_FTB, 2240 (unsigned long) p_buffer_hdr, 2241 (unsigned long) ii); 2242 2243 fill_this_buffer_exit: 2244 return retval; 2245 } 2246 2247 /** 2248 * @brief Set component's callback structure. 2249 * 2250 * @param[in] cmp_handle: Component handle. 2251 * @param[in] p_callbacks: Pointer to callback structure. 2252 * @param[in] p_app_data: Pointer to IL client app data. 2253 * 2254 * @retval OMX_ERRORTYPE 2255 */ 2256 OMX_ERRORTYPE omx_swvdec::set_callbacks(OMX_HANDLETYPE cmp_handle, 2257 OMX_CALLBACKTYPE *p_callbacks, 2258 OMX_PTR p_app_data) 2259 { 2260 OMX_ERRORTYPE retval = OMX_ErrorNone; 2261 2262 OMX_SWVDEC_LOG_API(""); 2263 2264 if (m_state == OMX_StateInvalid) 2265 { 2266 OMX_SWVDEC_LOG_ERROR("in invalid state"); 2267 2268 retval = OMX_ErrorInvalidState; 2269 } 2270 else if (cmp_handle == NULL) 2271 { 2272 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); 2273 2274 retval = OMX_ErrorInvalidComponent; 2275 } 2276 else if (p_callbacks->EventHandler == NULL) 2277 { 2278 OMX_SWVDEC_LOG_ERROR("p_callbacks->EventHandler = NULL"); 2279 2280 retval = OMX_ErrorBadParameter; 2281 } 2282 else if (p_callbacks->EmptyBufferDone == NULL) 2283 { 2284 OMX_SWVDEC_LOG_ERROR("p_callbacks->EmptyBufferDone = NULL"); 2285 2286 retval = OMX_ErrorBadParameter; 2287 } 2288 else if (p_callbacks->FillBufferDone == NULL) 2289 { 2290 OMX_SWVDEC_LOG_ERROR("p_callbacks->FillBufferDone = NULL"); 2291 2292 retval = OMX_ErrorBadParameter; 2293 } 2294 else 2295 { 2296 m_callback = *p_callbacks; 2297 m_app_data = p_app_data; 2298 } 2299 2300 return retval; 2301 } 2302 2303 /** 2304 * @brief Use EGL image. 2305 * 2306 * @retval OMX_ErrorNotImplemented 2307 */ 2308 OMX_ERRORTYPE omx_swvdec::use_EGL_image(OMX_HANDLETYPE cmp_handle, 2309 OMX_BUFFERHEADERTYPE **pp_buffer_hdr, 2310 OMX_U32 port, 2311 OMX_PTR p_app_data, 2312 void *egl_image) 2313 { 2314 (void) cmp_handle; 2315 (void) pp_buffer_hdr; 2316 (void) port; 2317 (void) p_app_data; 2318 (void) egl_image; 2319 2320 OMX_SWVDEC_LOG_API(""); 2321 2322 OMX_SWVDEC_LOG_ERROR("not implemented"); 2323 2324 return OMX_ErrorNotImplemented; 2325 } 2326 2327 /** 2328 * @brief Enumerate component role. 2329 * 2330 * @param[in] cmp_handle: Component handle. 2331 * @param[in,out] p_role: Pointer to component role string. 2332 * @param[in] index: Role index being queried. 2333 * 2334 * @retval OMX_ERRORTYPE 2335 */ 2336 OMX_ERRORTYPE omx_swvdec::component_role_enum(OMX_HANDLETYPE cmp_handle, 2337 OMX_U8 *p_role, 2338 OMX_U32 index) 2339 { 2340 OMX_ERRORTYPE retval = OMX_ErrorNone; 2341 2342 if (m_state == OMX_StateInvalid) 2343 { 2344 OMX_SWVDEC_LOG_ERROR("in invalid state"); 2345 2346 retval = OMX_ErrorInvalidState; 2347 } 2348 else if (cmp_handle == NULL) 2349 { 2350 OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); 2351 2352 retval = OMX_ErrorInvalidComponent; 2353 } 2354 else if (index > 0) 2355 { 2356 OMX_SWVDEC_LOG_HIGH("index '%d' unsupported; no more roles", index); 2357 2358 retval = OMX_ErrorNoMore; 2359 } 2360 else 2361 { 2362 memcpy(p_role, m_role_name, OMX_MAX_STRINGNAME_SIZE); 2363 2364 OMX_SWVDEC_LOG_API("index '%d': '%s'", index, p_role); 2365 } 2366 2367 return retval; 2368 } 2369 2370 /** 2371 * ------------------------- 2372 * SwVdec callback functions 2373 * ------------------------- 2374 */ 2375 2376 /** 2377 * @brief SwVdec empty buffer done callback. 2378 * 2379 * @param[in] swvdec_handle: SwVdec handle. 2380 * @param[in] p_buffer_ip: Pointer to input buffer structure. 2381 * @param[in] p_client_handle: Pointer to SwVdec's client handle. 2382 * 2383 * @retval SWVDEC_STATUS_SUCCESS 2384 * @retval SWVDEC_STATUS_NULL_POINTER 2385 * @retval SWVDEC_STATUS_INVALID_PARAMETERS 2386 */ 2387 SWVDEC_STATUS omx_swvdec::swvdec_empty_buffer_done_callback( 2388 SWVDEC_HANDLE swvdec_handle, 2389 SWVDEC_BUFFER *p_buffer_ip, 2390 void *p_client_handle) 2391 { 2392 SWVDEC_STATUS retval = SWVDEC_STATUS_SUCCESS; 2393 2394 if (p_buffer_ip == NULL) 2395 { 2396 OMX_SWVDEC_LOG_ERROR("p_buffer_ip = NULL"); 2397 2398 retval = SWVDEC_STATUS_NULL_POINTER; 2399 } 2400 else if (p_client_handle == NULL) 2401 { 2402 OMX_SWVDEC_LOG_ERROR("p_client_handle = NULL"); 2403 2404 retval = SWVDEC_STATUS_NULL_POINTER; 2405 } 2406 else 2407 { 2408 omx_swvdec *p_omx_swvdec = (omx_swvdec *) p_client_handle; 2409 2410 if (swvdec_handle != p_omx_swvdec->m_swvdec_handle) 2411 { 2412 OMX_SWVDEC_LOG_ERROR("invalid SwVdec handle"); 2413 2414 retval = SWVDEC_STATUS_INVALID_PARAMETERS; 2415 } 2416 else 2417 { 2418 p_omx_swvdec->swvdec_empty_buffer_done(p_buffer_ip); 2419 } 2420 } 2421 2422 return retval; 2423 } 2424 2425 /** 2426 * @brief SwVdec fill buffer done callback. 2427 * 2428 * @param[in] swvdec_handle: SwVdec handle. 2429 * @param[in] p_buffer_op: Pointer to output buffer structure. 2430 * @param[in] p_client_handle: Pointer to SwVdec's client handle. 2431 * 2432 * @retval SWVDEC_STATUS_SUCCESS 2433 * @retval SWVDEC_STATUS_NULL_POINTER 2434 * @retval SWVDEC_STATUS_INVALID_PARAMETERS 2435 */ 2436 SWVDEC_STATUS omx_swvdec::swvdec_fill_buffer_done_callback( 2437 SWVDEC_HANDLE swvdec_handle, 2438 SWVDEC_BUFFER *p_buffer_op, 2439 void *p_client_handle) 2440 { 2441 SWVDEC_STATUS retval = SWVDEC_STATUS_SUCCESS; 2442 2443 if (p_buffer_op == NULL) 2444 { 2445 OMX_SWVDEC_LOG_ERROR("p_buffer_op = NULL"); 2446 2447 retval = SWVDEC_STATUS_NULL_POINTER; 2448 } 2449 else if (p_client_handle == NULL) 2450 { 2451 OMX_SWVDEC_LOG_ERROR("p_client_handle = NULL"); 2452 2453 retval = SWVDEC_STATUS_NULL_POINTER; 2454 } 2455 else 2456 { 2457 omx_swvdec *p_omx_swvdec = (omx_swvdec *) p_client_handle; 2458 2459 if (swvdec_handle != p_omx_swvdec->m_swvdec_handle) 2460 { 2461 OMX_SWVDEC_LOG_ERROR("invalid SwVdec handle"); 2462 2463 retval = SWVDEC_STATUS_INVALID_PARAMETERS; 2464 } 2465 else 2466 { 2467 p_omx_swvdec->swvdec_fill_buffer_done(p_buffer_op); 2468 } 2469 } 2470 2471 return retval; 2472 } 2473 2474 /** 2475 * @brief SwVdec event handler callback. 2476 * 2477 * @param[in] swvdec_handle: SwVdec handle. 2478 * @param[in] event: Event. 2479 * @param[in] p_data: Pointer to event-specific data. 2480 * @param[in] p_client_handle: Pointer to SwVdec's client handle. 2481 * 2482 * @retval SWVDEC_STATUS_SUCCESS 2483 * @retval SWVDEC_STATUS_NULL_POINTER 2484 * @retval SWVDEC_STATUS_INVALID_PARAMETERS 2485 */ 2486 SWVDEC_STATUS omx_swvdec::swvdec_event_handler_callback( 2487 SWVDEC_HANDLE swvdec_handle, 2488 SWVDEC_EVENT event, 2489 void *p_data, 2490 void *p_client_handle) 2491 { 2492 SWVDEC_STATUS retval = SWVDEC_STATUS_SUCCESS; 2493 2494 if ((event == SWVDEC_EVENT_RELEASE_REFERENCE) && (p_data == NULL)) 2495 { 2496 OMX_SWVDEC_LOG_ERROR("p_data = NULL"); 2497 2498 retval = SWVDEC_STATUS_NULL_POINTER; 2499 } 2500 else if (p_client_handle == NULL) 2501 { 2502 OMX_SWVDEC_LOG_ERROR("p_client_handle = NULL"); 2503 2504 retval = SWVDEC_STATUS_NULL_POINTER; 2505 } 2506 else 2507 { 2508 omx_swvdec *p_omx_swvdec = (omx_swvdec *) p_client_handle; 2509 2510 if (swvdec_handle != p_omx_swvdec->m_swvdec_handle) 2511 { 2512 OMX_SWVDEC_LOG_ERROR("invalid SwVdec handle"); 2513 2514 retval = SWVDEC_STATUS_INVALID_PARAMETERS; 2515 } 2516 else 2517 { 2518 p_omx_swvdec->swvdec_event_handler(event, p_data); 2519 } 2520 } 2521 2522 return retval; 2523 } 2524 2525 /** 2526 * ----------------- 2527 * PRIVATE FUNCTIONS 2528 * ----------------- 2529 */ 2530 2531 /** 2532 * @brief Set frame dimensions for OMX component & SwVdec core. 2533 * 2534 * @param[in] width: Frame width. 2535 * @param[in] height: Frame height. 2536 * 2537 * @retval OMX_ERRORTYPE 2538 */ 2539 OMX_ERRORTYPE omx_swvdec::set_frame_dimensions(unsigned int width, 2540 unsigned int height) 2541 { 2542 OMX_ERRORTYPE retval; 2543 2544 m_frame_dimensions.width = width; 2545 m_frame_dimensions.height = height; 2546 2547 OMX_SWVDEC_LOG_HIGH("%d x %d", 2548 m_frame_dimensions.width, 2549 m_frame_dimensions.height); 2550 2551 retval = set_frame_dimensions_swvdec(); 2552 2553 return retval; 2554 } 2555 2556 /** 2557 * @brief Set frame attributes for OMX component & SwVdec core, based on 2558 * frame dimensions & color format. 2559 * 2560 * @param[in] color_format: Color format. 2561 * 2562 * @retval OMX_ERRORTYPE 2563 */ 2564 OMX_ERRORTYPE omx_swvdec::set_frame_attributes( 2565 OMX_COLOR_FORMATTYPE color_format) 2566 { 2567 OMX_ERRORTYPE retval = OMX_ErrorNone; 2568 2569 unsigned int width = m_frame_dimensions.width; 2570 unsigned int height = m_frame_dimensions.height; 2571 2572 unsigned int scanlines_uv; 2573 2574 unsigned int plane_size_y; 2575 unsigned int plane_size_uv; 2576 2577 switch (color_format) 2578 { 2579 2580 case OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m: 2581 { 2582 /** 2583 * alignment factors: 2584 * 2585 * - stride: 128 2586 * - scanlines_y: 32 2587 * - scanlines_uv: 16 2588 * - size: 4096 2589 */ 2590 2591 m_frame_attributes.stride = ALIGN(width, 128); 2592 m_frame_attributes.scanlines = ALIGN(height, 32); 2593 2594 scanlines_uv = ALIGN(height / 2, 16); 2595 2596 plane_size_y = (m_frame_attributes.stride * 2597 m_frame_attributes.scanlines); 2598 2599 plane_size_uv = m_frame_attributes.stride * scanlines_uv; 2600 2601 m_frame_attributes.size = ALIGN(plane_size_y + plane_size_uv, 4096); 2602 2603 OMX_SWVDEC_LOG_HIGH("'OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m': " 2604 "stride %d, scanlines %d, size %d", 2605 m_frame_attributes.stride, 2606 m_frame_attributes.scanlines, 2607 m_frame_attributes.size); 2608 2609 break; 2610 } 2611 2612 case OMX_COLOR_FormatYUV420SemiPlanar: 2613 { 2614 /** 2615 * alignment factors: 2616 * 2617 * - stride: 16 2618 * - scanlines_y: 16 2619 * - scanlines_uv: 16 2620 * - size: 4096 2621 */ 2622 2623 m_frame_attributes.stride = ALIGN(width, 16); 2624 m_frame_attributes.scanlines = ALIGN(height, 16); 2625 2626 scanlines_uv = ALIGN(height / 2, 16); 2627 2628 plane_size_y = (m_frame_attributes.stride * 2629 m_frame_attributes.scanlines); 2630 2631 plane_size_uv = m_frame_attributes.stride * scanlines_uv; 2632 2633 m_frame_attributes.size = ALIGN(plane_size_y + plane_size_uv, 4096); 2634 2635 OMX_SWVDEC_LOG_HIGH("'OMX_COLOR_FormatYUV420SemiPlanar': " 2636 "stride %d, scanlines %d, size %d", 2637 m_frame_attributes.stride, 2638 m_frame_attributes.scanlines, 2639 m_frame_attributes.size); 2640 2641 break; 2642 } 2643 2644 default: 2645 { 2646 OMX_SWVDEC_LOG_ERROR("'0x%08x' color format invalid or unsupported", 2647 color_format); 2648 2649 retval = OMX_ErrorBadParameter; 2650 break; 2651 } 2652 2653 } // switch (color_format) 2654 2655 if (retval == OMX_ErrorNone) 2656 { 2657 m_omx_color_formattype = color_format; 2658 2659 retval = set_frame_attributes_swvdec(); 2660 } 2661 2662 return retval; 2663 } 2664 2665 /** 2666 * @brief Set maximum adaptive playback frame dimensions for OMX component & 2667 * SwVdec core. 2668 * 2669 * @param[in] width: Max adaptive playback frame width. 2670 * @param[in] height: Max adaptive playback frame height. 2671 * 2672 * @retval OMX_ERRORTYPE 2673 */ 2674 OMX_ERRORTYPE omx_swvdec::set_adaptive_playback(unsigned int max_width, 2675 unsigned int max_height) 2676 { 2677 OMX_ERRORTYPE retval; 2678 2679 m_frame_dimensions_max.width = max_width; 2680 m_frame_dimensions_max.height = max_height; 2681 2682 OMX_SWVDEC_LOG_HIGH("%d x %d", 2683 m_frame_dimensions_max.width, 2684 m_frame_dimensions_max.height); 2685 2686 retval = set_adaptive_playback_swvdec(); 2687 2688 if (retval == OMX_ErrorNone) 2689 { 2690 retval = set_frame_dimensions(max_width, max_height); 2691 } 2692 2693 if (retval == OMX_ErrorNone) 2694 { 2695 retval = set_frame_attributes(m_omx_color_formattype); 2696 } 2697 2698 set_adaptive_playback_exit: 2699 return retval; 2700 } 2701 2702 /** 2703 * @brief Get video port format for input or output port. 2704 * 2705 * @param[in,out] p_port_format: Pointer to video port format type. 2706 * 2707 * @retval OMX_ERRORTYPE 2708 */ 2709 OMX_ERRORTYPE omx_swvdec::get_video_port_format( 2710 OMX_VIDEO_PARAM_PORTFORMATTYPE *p_port_format) 2711 { 2712 OMX_ERRORTYPE retval = OMX_ErrorNone; 2713 2714 if (p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_IP) 2715 { 2716 if (p_port_format->nIndex == 0) 2717 { 2718 p_port_format->eColorFormat = OMX_COLOR_FormatUnused; 2719 2720 p_port_format->eCompressionFormat = m_omx_video_codingtype; 2721 2722 OMX_SWVDEC_LOG_HIGH("color format 0x%08x, " 2723 "compression format 0x%08x", 2724 p_port_format->eColorFormat, 2725 p_port_format->eCompressionFormat); 2726 } 2727 else 2728 { 2729 OMX_SWVDEC_LOG_HIGH("index '%d' unsupported; " 2730 "no more compression formats", 2731 p_port_format->nIndex); 2732 2733 retval = OMX_ErrorNoMore; 2734 } 2735 } 2736 else if (p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_OP) 2737 { 2738 if (p_port_format->nIndex == 0) 2739 { 2740 p_port_format->eColorFormat = 2741 OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m; 2742 2743 p_port_format->eCompressionFormat = OMX_VIDEO_CodingUnused; 2744 2745 OMX_SWVDEC_LOG_HIGH("color format 0x%08x, " 2746 "compression format 0x%08x", 2747 p_port_format->eColorFormat, 2748 p_port_format->eCompressionFormat); 2749 } 2750 else if (p_port_format->nIndex == 1) 2751 { 2752 p_port_format->eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; 2753 2754 p_port_format->eCompressionFormat = OMX_VIDEO_CodingUnused; 2755 2756 OMX_SWVDEC_LOG_HIGH("color format 0x%08x, " 2757 "compression format 0x%08x", 2758 p_port_format->eColorFormat, 2759 p_port_format->eCompressionFormat); 2760 } 2761 else 2762 { 2763 OMX_SWVDEC_LOG_HIGH("index '%d' unsupported; no more color formats", 2764 p_port_format->nIndex); 2765 2766 retval = OMX_ErrorNoMore; 2767 } 2768 } 2769 else 2770 { 2771 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", 2772 p_port_format->nPortIndex); 2773 2774 retval = OMX_ErrorBadPortIndex; 2775 } 2776 2777 return retval; 2778 } 2779 2780 /** 2781 * @brief Set video port format for input or output port. 2782 * 2783 * @param[in] p_port_format: Pointer to video port format type. 2784 * 2785 * @retval OMX_ERRORTYPE 2786 */ 2787 OMX_ERRORTYPE omx_swvdec::set_video_port_format( 2788 OMX_VIDEO_PARAM_PORTFORMATTYPE *p_port_format) 2789 { 2790 OMX_ERRORTYPE retval = OMX_ErrorNone; 2791 2792 if (p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_IP) 2793 { 2794 OMX_SWVDEC_LOG_HIGH("OMX_IndexParamVideoPortFormat, port index 0; " 2795 "doing nothing"); 2796 } 2797 else if (p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_OP) 2798 { 2799 retval = set_frame_attributes(p_port_format->eColorFormat); 2800 } 2801 else 2802 { 2803 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", 2804 p_port_format->nPortIndex); 2805 2806 retval = OMX_ErrorBadPortIndex; 2807 } 2808 2809 set_video_port_format_exit: 2810 return retval; 2811 } 2812 2813 /** 2814 * @brief Get port definition for input or output port. 2815 * 2816 * @param[in,out] p_port_def: Pointer to port definition type. 2817 * 2818 * @retval OMX_ERRORTYPE 2819 */ 2820 OMX_ERRORTYPE omx_swvdec::get_port_definition( 2821 OMX_PARAM_PORTDEFINITIONTYPE *p_port_def) 2822 { 2823 OMX_ERRORTYPE retval = OMX_ErrorNone; 2824 2825 p_port_def->eDomain = OMX_PortDomainVideo; 2826 2827 if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_IP) 2828 { 2829 if ((retval = get_buffer_requirements_swvdec(OMX_CORE_PORT_INDEX_IP)) != 2830 OMX_ErrorNone) 2831 { 2832 goto get_port_definition_exit; 2833 } 2834 2835 p_port_def->eDir = OMX_DirInput; 2836 p_port_def->nBufferCountActual = m_port_ip.def.nBufferCountActual; 2837 p_port_def->nBufferCountMin = m_port_ip.def.nBufferCountMin; 2838 p_port_def->nBufferSize = m_port_ip.def.nBufferSize; 2839 p_port_def->bEnabled = m_port_ip.enabled; 2840 p_port_def->bPopulated = m_port_ip.populated; 2841 2842 OMX_SWVDEC_LOG_HIGH("port index %d: " 2843 "count actual %d, count min %d, size %d", 2844 p_port_def->nPortIndex, 2845 p_port_def->nBufferCountActual, 2846 p_port_def->nBufferCountMin, 2847 p_port_def->nBufferSize); 2848 2849 // frame dimensions & attributes don't apply to input port 2850 2851 p_port_def->format.video.eColorFormat = OMX_COLOR_FormatUnused; 2852 p_port_def->format.video.eCompressionFormat = m_omx_video_codingtype; 2853 } 2854 else if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_OP) 2855 { 2856 if ((retval = get_frame_dimensions_swvdec()) != OMX_ErrorNone) 2857 { 2858 goto get_port_definition_exit; 2859 } 2860 2861 p_port_def->format.video.nFrameWidth = m_frame_dimensions.width; 2862 p_port_def->format.video.nFrameHeight = m_frame_dimensions.height; 2863 2864 if (m_port_reconfig_inprogress) 2865 { 2866 if ((retval = set_frame_attributes(m_omx_color_formattype)) != 2867 OMX_ErrorNone) 2868 { 2869 goto get_port_definition_exit; 2870 } 2871 } 2872 2873 if ((retval = get_frame_attributes_swvdec()) != OMX_ErrorNone) 2874 { 2875 goto get_port_definition_exit; 2876 } 2877 2878 p_port_def->format.video.nStride = m_frame_attributes.stride; 2879 p_port_def->format.video.nSliceHeight = m_frame_attributes.scanlines; 2880 2881 OMX_SWVDEC_LOG_HIGH("port index %d: " 2882 "%d x %d, stride %d, sliceheight %d", 2883 p_port_def->nPortIndex, 2884 p_port_def->format.video.nFrameWidth, 2885 p_port_def->format.video.nFrameHeight, 2886 p_port_def->format.video.nStride, 2887 p_port_def->format.video.nSliceHeight); 2888 2889 /** 2890 * Query to SwVdec core for buffer requirements is not allowed in 2891 * executing state since it will overwrite the component's buffer 2892 * requirements updated via the most recent set_parameter(). 2893 * 2894 * Buffer requirements communicated to component via set_parameter() are 2895 * not propagated to SwVdec core. 2896 * 2897 * The only execption is if port reconfiguration is in progress, in 2898 * which case the query to SwVdec core is required since buffer 2899 * requirements can change based on new dimensions. 2900 */ 2901 if ((m_state != OMX_StateExecuting) || m_port_reconfig_inprogress) 2902 { 2903 if ((retval = 2904 get_buffer_requirements_swvdec(OMX_CORE_PORT_INDEX_OP)) != 2905 OMX_ErrorNone) 2906 { 2907 goto get_port_definition_exit; 2908 } 2909 } 2910 2911 p_port_def->eDir = OMX_DirOutput; 2912 p_port_def->nBufferCountActual = m_port_op.def.nBufferCountActual; 2913 p_port_def->nBufferCountMin = m_port_op.def.nBufferCountMin; 2914 p_port_def->nBufferSize = m_port_op.def.nBufferSize; 2915 p_port_def->bEnabled = m_port_op.enabled; 2916 p_port_def->bPopulated = m_port_op.populated; 2917 2918 OMX_SWVDEC_LOG_HIGH("port index %d: " 2919 "count actual %d, count min %d, size %d", 2920 p_port_def->nPortIndex, 2921 p_port_def->nBufferCountActual, 2922 p_port_def->nBufferCountMin, 2923 p_port_def->nBufferSize); 2924 2925 p_port_def->format.video.eColorFormat = m_omx_color_formattype; 2926 p_port_def->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; 2927 2928 if (m_omx_color_formattype == 2929 OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m) 2930 { 2931 OMX_SWVDEC_LOG_HIGH( 2932 "port index %d: color format '0x%08x': " 2933 "OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m", 2934 p_port_def->nPortIndex, 2935 p_port_def->format.video.eColorFormat); 2936 } 2937 else if (m_omx_color_formattype == OMX_COLOR_FormatYUV420SemiPlanar) 2938 { 2939 OMX_SWVDEC_LOG_HIGH("port index %d: color format '0x%08x': " 2940 "OMX_COLOR_FormatYUV420SemiPlanar", 2941 p_port_def->nPortIndex, 2942 p_port_def->format.video.eColorFormat); 2943 } 2944 else 2945 { 2946 assert(0); 2947 retval = OMX_ErrorUndefined; 2948 } 2949 } 2950 else 2951 { 2952 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", p_port_def->nPortIndex); 2953 2954 retval = OMX_ErrorBadPortIndex; 2955 } 2956 2957 get_port_definition_exit: 2958 return retval; 2959 } 2960 2961 /** 2962 * @brief Set port definition for input or output port. 2963 * 2964 * @param[in] p_port_def: Pointer to port definition type. 2965 * 2966 * @retval OMX_ERRORTYPE 2967 */ 2968 OMX_ERRORTYPE omx_swvdec::set_port_definition( 2969 OMX_PARAM_PORTDEFINITIONTYPE *p_port_def) 2970 { 2971 OMX_ERRORTYPE retval = OMX_ErrorNone; 2972 2973 OMX_SWVDEC_LOG_HIGH("port index %d: " 2974 "count actual %d, count min %d, size %d", 2975 p_port_def->nPortIndex, 2976 p_port_def->nBufferCountActual, 2977 p_port_def->nBufferCountMin, 2978 p_port_def->nBufferSize); 2979 2980 if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_IP) 2981 { 2982 m_port_ip.def.nBufferCountActual = p_port_def->nBufferCountActual; 2983 m_port_ip.def.nBufferCountMin = p_port_def->nBufferCountMin; 2984 m_port_ip.def.nBufferSize = p_port_def->nBufferSize; 2985 } 2986 else if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_OP) 2987 { 2988 /** 2989 * OMX component's output port nBufferSize is not updated based on what 2990 * IL client sends; instead it is updated based on the possibly updated 2991 * frame attributes. 2992 * 2993 * This is because set_parameter() for output port definition only has 2994 * updates to buffer counts or frame dimensions. 2995 */ 2996 2997 m_port_op.def.nBufferCountActual = p_port_def->nBufferCountActual; 2998 m_port_op.def.nBufferCountMin = p_port_def->nBufferCountMin; 2999 3000 OMX_SWVDEC_LOG_HIGH("port index %d: %d x %d", 3001 p_port_def->nPortIndex, 3002 p_port_def->format.video.nFrameWidth, 3003 p_port_def->format.video.nFrameHeight); 3004 3005 /** 3006 * Update frame dimensions & attributes if: 3007 * 3008 * 1. not in adaptive playback mode 3009 * OR 3010 * 2. new frame dimensions greater than adaptive playback mode's 3011 * max frame dimensions 3012 */ 3013 3014 if ((m_adaptive_playback_mode == false) || 3015 (p_port_def->format.video.nFrameWidth > 3016 m_frame_dimensions_max.width) || 3017 (p_port_def->format.video.nFrameHeight > 3018 m_frame_dimensions_max.height)) 3019 { 3020 OMX_SWVDEC_LOG_HIGH("updating frame dimensions & attributes"); 3021 3022 if ((retval = 3023 set_frame_dimensions(p_port_def->format.video.nFrameWidth, 3024 p_port_def->format.video.nFrameHeight)) != 3025 OMX_ErrorNone) 3026 { 3027 goto set_port_definition_exit; 3028 } 3029 3030 if ((retval = set_frame_attributes(m_omx_color_formattype)) != 3031 OMX_ErrorNone) 3032 { 3033 goto set_port_definition_exit; 3034 } 3035 3036 // nBufferSize updated based on (possibly new) frame attributes 3037 3038 m_port_op.def.nBufferSize = m_frame_attributes.size; 3039 } 3040 else 3041 { 3042 OMX_SWVDEC_LOG_HIGH("not updating frame dimensions & attributes"); 3043 } 3044 } 3045 else 3046 { 3047 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", p_port_def->nPortIndex); 3048 3049 retval = OMX_ErrorBadPortIndex; 3050 } 3051 3052 set_port_definition_exit: 3053 return retval; 3054 } 3055 3056 /** 3057 * @brief Get supported profile & level. 3058 * 3059 * The supported profiles & levels are not queried from SwVdec core, but 3060 * hard-coded. This should ideally be replaced with a query to SwVdec core. 3061 * 3062 * @param[in,out] p_profilelevel: Pointer to video profile & level type. 3063 * 3064 * @retval OMX_ERRORTYPE 3065 */ 3066 OMX_ERRORTYPE omx_swvdec::get_supported_profilelevel( 3067 OMX_VIDEO_PARAM_PROFILELEVELTYPE *p_profilelevel) 3068 { 3069 OMX_ERRORTYPE retval = OMX_ErrorNone; 3070 3071 if (p_profilelevel == NULL) 3072 { 3073 OMX_SWVDEC_LOG_ERROR("p_profilelevel = NULL"); 3074 3075 retval = OMX_ErrorBadParameter; 3076 goto get_supported_profilelevel_exit; 3077 } 3078 3079 if (p_profilelevel->nPortIndex != OMX_CORE_PORT_INDEX_IP) 3080 { 3081 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", 3082 p_profilelevel->nPortIndex); 3083 3084 retval = OMX_ErrorBadPortIndex; 3085 goto get_supported_profilelevel_exit; 3086 } 3087 3088 if (m_omx_video_codingtype == OMX_VIDEO_CodingH263) 3089 { 3090 if (p_profilelevel->nProfileIndex == 0) 3091 { 3092 p_profilelevel->eProfile = OMX_VIDEO_H263ProfileBaseline; 3093 p_profilelevel->eLevel = OMX_VIDEO_H263Level70; 3094 3095 OMX_SWVDEC_LOG_HIGH("H.263 baseline profile, level 70"); 3096 } 3097 else 3098 { 3099 OMX_SWVDEC_LOG_HIGH("profile index '%d' unsupported; " 3100 "no more profiles", 3101 p_profilelevel->nProfileIndex); 3102 3103 retval = OMX_ErrorNoMore; 3104 } 3105 } 3106 else if ((m_omx_video_codingtype == OMX_VIDEO_CodingMPEG4) || 3107 (m_omx_video_codingtype == 3108 ((OMX_VIDEO_CODINGTYPE) QOMX_VIDEO_CodingDivx))) 3109 { 3110 if (p_profilelevel->nProfileIndex == 0) 3111 { 3112 p_profilelevel->eProfile = OMX_VIDEO_MPEG4ProfileSimple; 3113 p_profilelevel->eLevel = OMX_VIDEO_MPEG4Level5; 3114 3115 OMX_SWVDEC_LOG_HIGH("MPEG-4 simple profile, level 5"); 3116 } 3117 else if (p_profilelevel->nProfileIndex == 1) 3118 { 3119 p_profilelevel->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple; 3120 p_profilelevel->eLevel = OMX_VIDEO_MPEG4Level5; 3121 3122 OMX_SWVDEC_LOG_HIGH("MPEG-4 advanced simple profile, level 5"); 3123 } 3124 else 3125 { 3126 OMX_SWVDEC_LOG_HIGH("profile index '%d' unsupported; " 3127 "no more profiles", 3128 p_profilelevel->nProfileIndex); 3129 3130 retval = OMX_ErrorNoMore; 3131 } 3132 } 3133 else 3134 { 3135 assert(0); 3136 retval = OMX_ErrorUndefined; 3137 } 3138 3139 get_supported_profilelevel_exit: 3140 return retval; 3141 } 3142 3143 /** 3144 * @brief Describe color format. 3145 * 3146 * @param[in,out] p_params: Pointer to 'DescribeColorFormatParams' structure. 3147 * 3148 * @retval OMX_ERRORTYPE 3149 */ 3150 OMX_ERRORTYPE omx_swvdec::describe_color_format( 3151 DescribeColorFormatParams *p_params) 3152 { 3153 OMX_ERRORTYPE retval = OMX_ErrorNone; 3154 3155 if (p_params == NULL) 3156 { 3157 OMX_SWVDEC_LOG_ERROR("p_params = NULL"); 3158 3159 retval = OMX_ErrorBadParameter; 3160 } 3161 else 3162 { 3163 MediaImage *p_img = &p_params->sMediaImage; 3164 3165 switch (p_params->eColorFormat) 3166 { 3167 3168 case OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m: 3169 { 3170 size_t stride, scanlines; 3171 3172 p_img->mType = MediaImage::MEDIA_IMAGE_TYPE_YUV; 3173 p_img->mNumPlanes = 3; 3174 3175 p_img->mWidth = p_params->nFrameWidth; 3176 p_img->mHeight = p_params->nFrameHeight; 3177 3178 /** 3179 * alignment factors: 3180 * 3181 * - stride: 128 3182 * - scanlines: 32 3183 */ 3184 stride = ALIGN(p_img->mWidth, 128); 3185 scanlines = ALIGN(p_img->mHeight, 32); 3186 3187 p_img->mBitDepth = 8; 3188 3189 // plane 0 (Y) 3190 p_img->mPlane[MediaImage::Y].mOffset = 0; 3191 p_img->mPlane[MediaImage::Y].mColInc = 1; 3192 p_img->mPlane[MediaImage::Y].mRowInc = stride; 3193 p_img->mPlane[MediaImage::Y].mHorizSubsampling = 1; 3194 p_img->mPlane[MediaImage::Y].mVertSubsampling = 1; 3195 3196 // plane 1 (U) 3197 p_img->mPlane[MediaImage::U].mOffset = stride * scanlines; 3198 p_img->mPlane[MediaImage::U].mColInc = 2; 3199 p_img->mPlane[MediaImage::U].mRowInc = stride; 3200 p_img->mPlane[MediaImage::U].mHorizSubsampling = 2; 3201 p_img->mPlane[MediaImage::U].mVertSubsampling = 2; 3202 3203 // plane 2 (V) 3204 p_img->mPlane[MediaImage::V].mOffset = stride * scanlines + 1; 3205 p_img->mPlane[MediaImage::V].mColInc = 2; 3206 p_img->mPlane[MediaImage::V].mRowInc = stride; 3207 p_img->mPlane[MediaImage::V].mHorizSubsampling = 2; 3208 p_img->mPlane[MediaImage::V].mVertSubsampling = 2; 3209 3210 break; 3211 } 3212 3213 case OMX_COLOR_FormatYUV420SemiPlanar: 3214 { 3215 // do nothing; standard OMX color formats should not be described 3216 retval = OMX_ErrorUnsupportedSetting; 3217 break; 3218 } 3219 3220 default: 3221 { 3222 OMX_SWVDEC_LOG_ERROR("color format '0x%08x' invalid/unsupported", 3223 p_params->eColorFormat); 3224 3225 p_img->mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN; 3226 3227 retval = OMX_ErrorBadParameter; 3228 break; 3229 } 3230 3231 } // switch (p_params->eColorFormat) 3232 } 3233 3234 return retval; 3235 } 3236 3237 /** 3238 * @brief Set QTI vendor-specific port definition for input or output port. 3239 * 3240 * @param[in] p_port_def: Pointer to QTI vendor-specific port definition type. 3241 * 3242 * @retval OMX_ERRORTYPE 3243 */ 3244 OMX_ERRORTYPE omx_swvdec::set_port_definition_qcom( 3245 OMX_QCOM_PARAM_PORTDEFINITIONTYPE *p_port_def) 3246 { 3247 OMX_ERRORTYPE retval = OMX_ErrorNone; 3248 3249 if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_IP) 3250 { 3251 switch (p_port_def->nFramePackingFormat) 3252 { 3253 3254 case OMX_QCOM_FramePacking_Arbitrary: 3255 { 3256 OMX_SWVDEC_LOG_HIGH("OMX_QCOM_FramePacking_Arbitrary"); 3257 3258 m_arbitrary_bytes_mode = true; 3259 3260 break; 3261 } 3262 3263 case OMX_QCOM_FramePacking_OnlyOneCompleteFrame: 3264 { 3265 OMX_SWVDEC_LOG_HIGH( 3266 "OMX_QCOM_FramePacking_OnlyOneCompleteFrame"); 3267 3268 break; 3269 } 3270 3271 default: 3272 { 3273 OMX_SWVDEC_LOG_ERROR( 3274 "frame packing format '%d' unsupported", 3275 p_port_def->nFramePackingFormat); 3276 3277 retval = OMX_ErrorUnsupportedSetting; 3278 break; 3279 } 3280 3281 } 3282 } 3283 else if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_OP) 3284 { 3285 OMX_SWVDEC_LOG_HIGH("nMemRegion %d, nCacheAttr %d", 3286 p_port_def->nMemRegion, 3287 p_port_def->nCacheAttr); 3288 } 3289 else 3290 { 3291 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", 3292 p_port_def->nPortIndex); 3293 3294 retval = OMX_ErrorBadPortIndex; 3295 } 3296 3297 return retval; 3298 } 3299 3300 /** 3301 * @brief Set SwVdec frame dimensions based on OMX component frame dimensions. 3302 * 3303 * @retval OMX_ERRORTYPE 3304 */ 3305 OMX_ERRORTYPE omx_swvdec::set_frame_dimensions_swvdec() 3306 { 3307 OMX_ERRORTYPE retval = OMX_ErrorNone; 3308 3309 SWVDEC_PROPERTY property; 3310 3311 SWVDEC_STATUS retval_swvdec; 3312 3313 property.id = SWVDEC_PROPERTY_ID_FRAME_DIMENSIONS; 3314 3315 property.info.frame_dimensions.width = m_frame_dimensions.width; 3316 property.info.frame_dimensions.height = m_frame_dimensions.height; 3317 3318 if ((retval_swvdec = swvdec_setproperty(m_swvdec_handle, &property)) != 3319 SWVDEC_STATUS_SUCCESS) 3320 { 3321 retval = retval_swvdec2omx(retval_swvdec); 3322 } 3323 3324 return retval; 3325 } 3326 3327 /** 3328 * @brief Set SwVdec frame attributes based on OMX component frame attributes. 3329 * 3330 * @retval OMX_ERRORTYPE 3331 */ 3332 OMX_ERRORTYPE omx_swvdec::set_frame_attributes_swvdec() 3333 { 3334 OMX_ERRORTYPE retval = OMX_ErrorNone; 3335 3336 SWVDEC_FRAME_ATTRIBUTES *p_frame_attributes; 3337 3338 SWVDEC_PROPERTY property; 3339 3340 SWVDEC_STATUS retval_swvdec; 3341 3342 p_frame_attributes = &property.info.frame_attributes; 3343 3344 property.id = SWVDEC_PROPERTY_ID_FRAME_ATTRIBUTES; 3345 3346 p_frame_attributes->color_format = SWVDEC_COLOR_FORMAT_SEMIPLANAR_NV12; 3347 3348 p_frame_attributes->stride = m_frame_attributes.stride; 3349 p_frame_attributes->scanlines = m_frame_attributes.scanlines; 3350 p_frame_attributes->size = m_frame_attributes.size; 3351 3352 if ((retval_swvdec = swvdec_setproperty(m_swvdec_handle, &property)) != 3353 SWVDEC_STATUS_SUCCESS) 3354 { 3355 retval = retval_swvdec2omx(retval_swvdec); 3356 } 3357 3358 return retval; 3359 } 3360 3361 /** 3362 * @brief Set maximum adaptive playback frame dimensions for SwVdec core. 3363 */ 3364 OMX_ERRORTYPE omx_swvdec::set_adaptive_playback_swvdec() 3365 { 3366 OMX_ERRORTYPE retval = OMX_ErrorNone; 3367 3368 SWVDEC_PROPERTY property; 3369 3370 SWVDEC_STATUS retval_swvdec; 3371 3372 property.id = SWVDEC_PROPERTY_ID_ADAPTIVE_PLAYBACK; 3373 3374 property.info.frame_dimensions.width = m_frame_dimensions_max.width; 3375 property.info.frame_dimensions.height = m_frame_dimensions_max.height; 3376 3377 if ((retval_swvdec = swvdec_setproperty(m_swvdec_handle, &property)) != 3378 SWVDEC_STATUS_SUCCESS) 3379 { 3380 retval = retval_swvdec2omx(retval_swvdec); 3381 } 3382 3383 return retval; 3384 } 3385 3386 /** 3387 * @brief Get SwVdec frame dimensions and set OMX component frame dimensions. 3388 * 3389 * @retval OMX_ERRORTYPE 3390 */ 3391 OMX_ERRORTYPE omx_swvdec::get_frame_dimensions_swvdec() 3392 { 3393 OMX_ERRORTYPE retval = OMX_ErrorNone; 3394 3395 SWVDEC_PROPERTY property; 3396 3397 SWVDEC_STATUS retval_swvdec; 3398 3399 property.id = SWVDEC_PROPERTY_ID_FRAME_DIMENSIONS; 3400 3401 if ((retval_swvdec = swvdec_getproperty(m_swvdec_handle, &property)) != 3402 SWVDEC_STATUS_SUCCESS) 3403 { 3404 retval = retval_swvdec2omx(retval_swvdec); 3405 } 3406 else 3407 { 3408 m_frame_dimensions.width = property.info.frame_dimensions.width; 3409 m_frame_dimensions.height = property.info.frame_dimensions.height; 3410 } 3411 3412 return retval; 3413 } 3414 3415 /** 3416 * @brief Get SwVdec frame attributes and set OMX component frame attributes. 3417 * 3418 * @retval OMX_ERRORTYPE 3419 */ 3420 OMX_ERRORTYPE omx_swvdec::get_frame_attributes_swvdec() 3421 { 3422 OMX_ERRORTYPE retval = OMX_ErrorNone; 3423 3424 SWVDEC_PROPERTY property; 3425 3426 SWVDEC_STATUS retval_swvdec; 3427 3428 property.id = SWVDEC_PROPERTY_ID_FRAME_ATTRIBUTES; 3429 3430 if ((retval_swvdec = swvdec_getproperty(m_swvdec_handle, &property)) != 3431 SWVDEC_STATUS_SUCCESS) 3432 { 3433 retval = retval_swvdec2omx(retval_swvdec); 3434 } 3435 else 3436 { 3437 m_frame_attributes.stride = property.info.frame_attributes.stride; 3438 m_frame_attributes.scanlines = property.info.frame_attributes.scanlines; 3439 m_frame_attributes.size = property.info.frame_attributes.size; 3440 } 3441 3442 return retval; 3443 } 3444 3445 /** 3446 * @brief Get SwVdec buffer requirements; set input or output port definitions. 3447 * 3448 * @param[in] port_index: Port index. 3449 * 3450 * @retval OMX_ERRORTYPE 3451 */ 3452 OMX_ERRORTYPE omx_swvdec::get_buffer_requirements_swvdec( 3453 unsigned int port_index) 3454 { 3455 OMX_ERRORTYPE retval = OMX_ErrorNone; 3456 3457 SWVDEC_PROPERTY property; 3458 3459 SWVDEC_STATUS retval_swvdec; 3460 3461 SWVDEC_BUFFER_REQ *p_buffer_req; 3462 3463 if (port_index == OMX_CORE_PORT_INDEX_IP) 3464 { 3465 property.id = SWVDEC_PROPERTY_ID_BUFFER_REQ_IP; 3466 3467 p_buffer_req = &property.info.buffer_req_ip; 3468 3469 if ((retval_swvdec = swvdec_getproperty(m_swvdec_handle, &property)) != 3470 SWVDEC_STATUS_SUCCESS) 3471 { 3472 retval = retval_swvdec2omx(retval_swvdec); 3473 goto get_buffer_requirements_swvdec_exit; 3474 } 3475 3476 m_port_ip.def.nBufferSize = p_buffer_req->size; 3477 m_port_ip.def.nBufferCountMin = p_buffer_req->mincount; 3478 m_port_ip.def.nBufferCountActual = MAX(p_buffer_req->mincount, 3479 OMX_SWVDEC_IP_BUFFER_COUNT_MIN); 3480 m_port_ip.def.nBufferAlignment = p_buffer_req->alignment; 3481 3482 OMX_SWVDEC_LOG_HIGH("ip port: %d bytes x %d, %d-byte aligned", 3483 m_port_ip.def.nBufferSize, 3484 m_port_ip.def.nBufferCountActual, 3485 m_port_ip.def.nBufferAlignment); 3486 } 3487 else if (port_index == OMX_CORE_PORT_INDEX_OP) 3488 { 3489 property.id = SWVDEC_PROPERTY_ID_BUFFER_REQ_OP; 3490 3491 p_buffer_req = &property.info.buffer_req_op; 3492 3493 if ((retval_swvdec = swvdec_getproperty(m_swvdec_handle, &property)) != 3494 SWVDEC_STATUS_SUCCESS) 3495 { 3496 retval = retval_swvdec2omx(retval_swvdec); 3497 goto get_buffer_requirements_swvdec_exit; 3498 } 3499 3500 if (m_sync_frame_decoding_mode) 3501 { 3502 p_buffer_req->mincount = 1; 3503 } 3504 3505 m_port_op.def.nBufferSize = p_buffer_req->size; 3506 m_port_op.def.nBufferCountMin = p_buffer_req->mincount; 3507 m_port_op.def.nBufferCountActual = MAX(p_buffer_req->mincount, 3508 m_port_op.def.nBufferCountActual); 3509 m_port_op.def.nBufferAlignment = p_buffer_req->alignment; 3510 3511 OMX_SWVDEC_LOG_HIGH("op port: %d bytes x %d, %d-byte aligned", 3512 m_port_op.def.nBufferSize, 3513 m_port_op.def.nBufferCountActual, 3514 m_port_op.def.nBufferAlignment); 3515 } 3516 else 3517 { 3518 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", port_index); 3519 3520 retval = OMX_ErrorBadPortIndex; 3521 } 3522 3523 get_buffer_requirements_swvdec_exit: 3524 return retval; 3525 } 3526 3527 /** 3528 * @brief Allocate input buffer, and input buffer info array if ncessary. 3529 * 3530 * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type 3531 * structure. 3532 * @param[in] p_app_data: Pointer to IL client app data. 3533 * @param[in] size: Size of buffer to be allocated in bytes. 3534 * 3535 * @retval OMX_ERRORTYPE 3536 */ 3537 OMX_ERRORTYPE omx_swvdec::buffer_allocate_ip( 3538 OMX_BUFFERHEADERTYPE **pp_buffer_hdr, 3539 OMX_PTR p_app_data, 3540 OMX_U32 size) 3541 { 3542 OMX_ERRORTYPE retval = OMX_ErrorNone; 3543 3544 unsigned int ii; 3545 3546 if (size != m_port_ip.def.nBufferSize) 3547 { 3548 OMX_SWVDEC_LOG_ERROR("requested size (%d bytes) not equal to " 3549 "configured size (%d bytes)", 3550 size, 3551 m_port_ip.def.nBufferSize); 3552 3553 retval = OMX_ErrorBadParameter; 3554 goto buffer_allocate_ip_exit; 3555 } 3556 3557 if (m_buffer_array_ip == NULL) 3558 { 3559 OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s", 3560 m_port_ip.def.nBufferCountActual, 3561 (m_port_ip.def.nBufferCountActual > 1) ? "s" : ""); 3562 3563 if ((retval = buffer_allocate_ip_info_array()) != OMX_ErrorNone) 3564 { 3565 goto buffer_allocate_ip_exit; 3566 } 3567 } 3568 3569 for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++) 3570 { 3571 if (m_buffer_array_ip[ii].buffer_populated == false) 3572 { 3573 OMX_SWVDEC_LOG_LOW("buffer %d not populated", ii); 3574 break; 3575 } 3576 } 3577 3578 if (ii < m_port_ip.def.nBufferCountActual) 3579 { 3580 int pmem_fd = -1; 3581 3582 unsigned char *bufferaddr; 3583 3584 OMX_SWVDEC_LOG_HIGH("ip buffer %d: %d bytes being allocated", 3585 ii, 3586 size); 3587 3588 m_buffer_array_ip[ii].ion_info.ion_fd_device = 3589 ion_memory_alloc_map(&m_buffer_array_ip[ii].ion_info.ion_alloc_data, 3590 &m_buffer_array_ip[ii].ion_info.ion_fd_data, 3591 size, 3592 m_port_ip.def.nBufferAlignment); 3593 3594 if (m_buffer_array_ip[ii].ion_info.ion_fd_device < 0) 3595 { 3596 retval = OMX_ErrorInsufficientResources; 3597 goto buffer_allocate_ip_exit; 3598 } 3599 3600 pmem_fd = m_buffer_array_ip[ii].ion_info.ion_fd_data.fd; 3601 3602 bufferaddr = (unsigned char *) mmap(NULL, 3603 size, 3604 PROT_READ | PROT_WRITE, 3605 MAP_SHARED, 3606 pmem_fd, 3607 0); 3608 3609 if (bufferaddr == MAP_FAILED) 3610 { 3611 OMX_SWVDEC_LOG_ERROR("mmap() failed for fd %d of size %d", 3612 pmem_fd, 3613 size); 3614 3615 close(pmem_fd); 3616 ion_memory_free(&m_buffer_array_ip[ii].ion_info); 3617 3618 retval = OMX_ErrorInsufficientResources; 3619 goto buffer_allocate_ip_exit; 3620 } 3621 3622 *pp_buffer_hdr = &m_buffer_array_ip[ii].buffer_header; 3623 3624 m_buffer_array_ip[ii].buffer_payload.bufferaddr = bufferaddr; 3625 m_buffer_array_ip[ii].buffer_payload.pmem_fd = pmem_fd; 3626 m_buffer_array_ip[ii].buffer_payload.buffer_len = size; 3627 m_buffer_array_ip[ii].buffer_payload.mmaped_size = size; 3628 m_buffer_array_ip[ii].buffer_payload.offset = 0; 3629 3630 m_buffer_array_ip[ii].buffer_swvdec.p_buffer = bufferaddr; 3631 m_buffer_array_ip[ii].buffer_swvdec.size = size; 3632 m_buffer_array_ip[ii].buffer_swvdec.p_client_data = 3633 (void *) ((unsigned long) ii); 3634 3635 m_buffer_array_ip[ii].buffer_populated = true; 3636 3637 OMX_SWVDEC_LOG_HIGH("ip buffer %d: %p, %d bytes", 3638 ii, 3639 bufferaddr, 3640 size); 3641 3642 (*pp_buffer_hdr)->pBuffer = (OMX_U8 *) bufferaddr; 3643 (*pp_buffer_hdr)->nSize = sizeof(OMX_BUFFERHEADERTYPE); 3644 (*pp_buffer_hdr)->nVersion.nVersion = OMX_SPEC_VERSION; 3645 (*pp_buffer_hdr)->nAllocLen = size; 3646 (*pp_buffer_hdr)->pAppPrivate = p_app_data; 3647 (*pp_buffer_hdr)->nInputPortIndex = OMX_CORE_PORT_INDEX_IP; 3648 (*pp_buffer_hdr)->pInputPortPrivate = 3649 (void *) &(m_buffer_array_ip[ii].buffer_payload); 3650 3651 m_port_ip.populated = port_ip_populated(); 3652 m_port_ip.unpopulated = OMX_FALSE; 3653 } 3654 else 3655 { 3656 OMX_SWVDEC_LOG_ERROR("all %d ip buffers allocated", 3657 m_port_ip.def.nBufferCountActual); 3658 3659 retval = OMX_ErrorInsufficientResources; 3660 } 3661 3662 buffer_allocate_ip_exit: 3663 return retval; 3664 } 3665 3666 /** 3667 * @brief Allocate output buffer, and output buffer info array if necessary. 3668 * 3669 * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type 3670 * structure. 3671 * @param[in] p_app_data: Pointer to IL client app data. 3672 * @param[in] size: Size of buffer to be allocated in bytes. 3673 * 3674 * @retval OMX_ERRORTYPE 3675 */ 3676 OMX_ERRORTYPE omx_swvdec::buffer_allocate_op( 3677 OMX_BUFFERHEADERTYPE **pp_buffer_hdr, 3678 OMX_PTR p_app_data, 3679 OMX_U32 size) 3680 { 3681 OMX_ERRORTYPE retval = OMX_ErrorNone; 3682 3683 unsigned int ii; 3684 3685 if (size != m_port_op.def.nBufferSize) 3686 { 3687 OMX_SWVDEC_LOG_ERROR("requested size (%d bytes) not equal to " 3688 "configured size (%d bytes)", 3689 size, 3690 m_port_op.def.nBufferSize); 3691 3692 retval = OMX_ErrorBadParameter; 3693 goto buffer_allocate_op_exit; 3694 } 3695 3696 if (m_buffer_array_op == NULL) 3697 { 3698 OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s", 3699 m_port_op.def.nBufferCountActual, 3700 (m_port_op.def.nBufferCountActual > 1) ? "s" : ""); 3701 3702 if ((retval = buffer_allocate_op_info_array()) != OMX_ErrorNone) 3703 { 3704 goto buffer_allocate_op_exit; 3705 } 3706 } 3707 3708 for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++) 3709 { 3710 if (m_buffer_array_op[ii].buffer_populated == false) 3711 { 3712 OMX_SWVDEC_LOG_LOW("buffer %d not populated", ii); 3713 break; 3714 } 3715 } 3716 3717 if (ii < m_port_op.def.nBufferCountActual) 3718 { 3719 int pmem_fd = -1; 3720 3721 unsigned char *bufferaddr; 3722 3723 OMX_SWVDEC_LOG_HIGH("op buffer %d: %d bytes being allocated", 3724 ii, 3725 size); 3726 3727 m_buffer_array_op[ii].ion_info.ion_fd_device = 3728 ion_memory_alloc_map(&m_buffer_array_op[ii].ion_info.ion_alloc_data, 3729 &m_buffer_array_op[ii].ion_info.ion_fd_data, 3730 size, 3731 m_port_op.def.nBufferAlignment); 3732 3733 if (m_buffer_array_op[ii].ion_info.ion_fd_device < 0) 3734 { 3735 retval = OMX_ErrorInsufficientResources; 3736 goto buffer_allocate_op_exit; 3737 } 3738 3739 pmem_fd = m_buffer_array_op[ii].ion_info.ion_fd_data.fd; 3740 3741 bufferaddr = (unsigned char *) mmap(NULL, 3742 size, 3743 PROT_READ | PROT_WRITE, 3744 MAP_SHARED, 3745 pmem_fd, 3746 0); 3747 3748 if (bufferaddr == MAP_FAILED) 3749 { 3750 OMX_SWVDEC_LOG_ERROR("mmap() failed for fd %d of size %d", 3751 pmem_fd, 3752 size); 3753 3754 close(pmem_fd); 3755 ion_memory_free(&m_buffer_array_op[ii].ion_info); 3756 3757 retval = OMX_ErrorInsufficientResources; 3758 goto buffer_allocate_op_exit; 3759 } 3760 3761 *pp_buffer_hdr = &m_buffer_array_op[ii].buffer_header; 3762 3763 m_buffer_array_op[ii].buffer_payload.bufferaddr = bufferaddr; 3764 m_buffer_array_op[ii].buffer_payload.pmem_fd = pmem_fd; 3765 m_buffer_array_op[ii].buffer_payload.buffer_len = size; 3766 m_buffer_array_op[ii].buffer_payload.mmaped_size = size; 3767 m_buffer_array_op[ii].buffer_payload.offset = 0; 3768 3769 m_buffer_array_op[ii].buffer_swvdec.p_buffer = bufferaddr; 3770 m_buffer_array_op[ii].buffer_swvdec.size = size; 3771 m_buffer_array_op[ii].buffer_swvdec.p_client_data = 3772 (void *) ((unsigned long) ii); 3773 3774 m_buffer_array_op[ii].buffer_populated = true; 3775 3776 OMX_SWVDEC_LOG_HIGH("op buffer %d: %p, %d bytes", 3777 ii, 3778 bufferaddr, 3779 size); 3780 3781 (*pp_buffer_hdr)->pBuffer = (OMX_U8 *) bufferaddr; 3782 (*pp_buffer_hdr)->nSize = sizeof(OMX_BUFFERHEADERTYPE); 3783 (*pp_buffer_hdr)->nVersion.nVersion = OMX_SPEC_VERSION; 3784 (*pp_buffer_hdr)->nAllocLen = size; 3785 (*pp_buffer_hdr)->pAppPrivate = p_app_data; 3786 (*pp_buffer_hdr)->nOutputPortIndex = OMX_CORE_PORT_INDEX_OP; 3787 (*pp_buffer_hdr)->pOutputPortPrivate = 3788 (void *) &(m_buffer_array_op[ii].buffer_payload); 3789 3790 m_port_op.populated = port_op_populated(); 3791 m_port_op.unpopulated = OMX_FALSE; 3792 } 3793 else 3794 { 3795 OMX_SWVDEC_LOG_ERROR("all %d op buffers allocated", 3796 m_port_op.def.nBufferCountActual); 3797 3798 retval = OMX_ErrorInsufficientResources; 3799 } 3800 3801 buffer_allocate_op_exit: 3802 return retval; 3803 } 3804 3805 /** 3806 * @brief Allocate input buffer info array. 3807 */ 3808 OMX_ERRORTYPE omx_swvdec::buffer_allocate_ip_info_array() 3809 { 3810 OMX_ERRORTYPE retval = OMX_ErrorNone; 3811 3812 unsigned int ii; 3813 3814 OMX_BUFFERHEADERTYPE *p_buffer_hdr; 3815 3816 if (m_buffer_array_ip != NULL) 3817 { 3818 OMX_SWVDEC_LOG_ERROR("buffer info array already allocated"); 3819 3820 retval = OMX_ErrorInsufficientResources; 3821 goto buffer_allocate_ip_info_array_exit; 3822 } 3823 3824 OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s", 3825 m_port_ip.def.nBufferCountActual, 3826 (m_port_ip.def.nBufferCountActual > 1) ? "s" : ""); 3827 3828 m_buffer_array_ip = 3829 (OMX_SWVDEC_BUFFER_INFO *) calloc(sizeof(OMX_SWVDEC_BUFFER_INFO), 3830 m_port_ip.def.nBufferCountActual); 3831 3832 if (m_buffer_array_ip == NULL) 3833 { 3834 OMX_SWVDEC_LOG_ERROR("failed to allocate buffer info array; " 3835 "%d element%s, %zu bytes requested", 3836 m_port_ip.def.nBufferCountActual, 3837 (m_port_ip.def.nBufferCountActual > 1) ? "s" : "", 3838 sizeof(OMX_SWVDEC_BUFFER_INFO) * 3839 m_port_ip.def.nBufferCountActual); 3840 3841 retval = OMX_ErrorInsufficientResources; 3842 goto buffer_allocate_ip_info_array_exit; 3843 } 3844 3845 for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++) 3846 { 3847 p_buffer_hdr = &m_buffer_array_ip[ii].buffer_header; 3848 3849 // reset file descriptors 3850 3851 m_buffer_array_ip[ii].buffer_payload.pmem_fd = -1; 3852 m_buffer_array_ip[ii].ion_info.ion_fd_device = -1; 3853 3854 m_buffer_array_ip[ii].buffer_swvdec.p_client_data = 3855 (void *) ((unsigned long) ii); 3856 3857 p_buffer_hdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); 3858 p_buffer_hdr->nVersion.nVersion = OMX_SPEC_VERSION; 3859 p_buffer_hdr->nInputPortIndex = OMX_CORE_PORT_INDEX_IP; 3860 p_buffer_hdr->pInputPortPrivate = 3861 (void *) &(m_buffer_array_ip[ii].buffer_payload); 3862 } 3863 3864 buffer_allocate_ip_info_array_exit: 3865 return retval; 3866 } 3867 3868 /** 3869 * @brief Allocate output buffer info array. 3870 */ 3871 OMX_ERRORTYPE omx_swvdec::buffer_allocate_op_info_array() 3872 { 3873 OMX_ERRORTYPE retval = OMX_ErrorNone; 3874 3875 unsigned int ii; 3876 3877 OMX_BUFFERHEADERTYPE *p_buffer_hdr; 3878 3879 if (m_buffer_array_op != NULL) 3880 { 3881 OMX_SWVDEC_LOG_ERROR("buffer info array already allocated"); 3882 3883 retval = OMX_ErrorInsufficientResources; 3884 goto buffer_allocate_op_info_array_exit; 3885 } 3886 3887 OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s", 3888 m_port_op.def.nBufferCountActual, 3889 (m_port_op.def.nBufferCountActual > 1) ? "s" : ""); 3890 3891 m_buffer_array_op = 3892 (OMX_SWVDEC_BUFFER_INFO *) calloc(sizeof(OMX_SWVDEC_BUFFER_INFO), 3893 m_port_op.def.nBufferCountActual); 3894 3895 if (m_buffer_array_op == NULL) 3896 { 3897 OMX_SWVDEC_LOG_ERROR("failed to allocate buffer info array; " 3898 "%d element%s, %zu bytes requested", 3899 m_port_op.def.nBufferCountActual, 3900 (m_port_op.def.nBufferCountActual > 1) ? "s" : "", 3901 sizeof(OMX_SWVDEC_BUFFER_INFO) * 3902 m_port_op.def.nBufferCountActual); 3903 3904 retval = OMX_ErrorInsufficientResources; 3905 goto buffer_allocate_op_info_array_exit; 3906 } 3907 3908 for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++) 3909 { 3910 p_buffer_hdr = &m_buffer_array_op[ii].buffer_header; 3911 3912 // reset file descriptors 3913 3914 m_buffer_array_op[ii].buffer_payload.pmem_fd = -1; 3915 m_buffer_array_op[ii].ion_info.ion_fd_device = -1; 3916 3917 m_buffer_array_op[ii].buffer_swvdec.p_client_data = 3918 (void *) ((unsigned long) ii); 3919 3920 p_buffer_hdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); 3921 p_buffer_hdr->nVersion.nVersion = OMX_SPEC_VERSION; 3922 p_buffer_hdr->nOutputPortIndex = OMX_CORE_PORT_INDEX_OP; 3923 p_buffer_hdr->pOutputPortPrivate = 3924 (void *) &(m_buffer_array_op[ii].buffer_payload); 3925 } 3926 3927 buffer_allocate_op_info_array_exit: 3928 return retval; 3929 } 3930 3931 /** 3932 * @brief Use buffer allocated by IL client; allocate output buffer info array 3933 * if necessary. 3934 * 3935 * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type 3936 * structure. 3937 * @param[in] p_app_data: Pointer to IL client app data. 3938 * @param[in] size: Size of buffer to be allocated in bytes. 3939 * @param[in] p_buffer: Pointer to buffer to be used. 3940 * 3941 * @retval OMX_ERRORTYPE 3942 */ 3943 OMX_ERRORTYPE omx_swvdec::buffer_use_op( 3944 OMX_BUFFERHEADERTYPE **pp_buffer_hdr, 3945 OMX_PTR p_app_data, 3946 OMX_U32 size, 3947 OMX_U8 *p_buffer) 3948 { 3949 OMX_ERRORTYPE retval = OMX_ErrorNone; 3950 3951 unsigned int ii; 3952 3953 (void) size; 3954 3955 if (m_buffer_array_op == NULL) 3956 { 3957 OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s", 3958 m_port_op.def.nBufferCountActual, 3959 (m_port_op.def.nBufferCountActual > 1) ? "s" : ""); 3960 3961 if ((retval = buffer_allocate_op_info_array()) != OMX_ErrorNone) 3962 { 3963 goto buffer_use_op_exit; 3964 } 3965 } 3966 3967 if (m_meta_buffer_mode && (m_meta_buffer_array == NULL)) 3968 { 3969 OMX_SWVDEC_LOG_HIGH("allocating meta buffer info array, %d element%s", 3970 m_port_op.def.nBufferCountActual, 3971 (m_port_op.def.nBufferCountActual > 1) ? "s" : ""); 3972 3973 if ((retval = meta_buffer_array_allocate()) != OMX_ErrorNone) 3974 { 3975 goto buffer_use_op_exit; 3976 } 3977 } 3978 3979 for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++) 3980 { 3981 if (m_buffer_array_op[ii].buffer_populated == false) 3982 { 3983 OMX_SWVDEC_LOG_LOW("buffer %d not populated", ii); 3984 break; 3985 } 3986 } 3987 3988 if (ii < m_port_op.def.nBufferCountActual) 3989 { 3990 struct vdec_bufferpayload *p_buffer_payload; 3991 3992 SWVDEC_BUFFER *p_buffer_swvdec; 3993 3994 *pp_buffer_hdr = &m_buffer_array_op[ii].buffer_header; 3995 p_buffer_payload = &m_buffer_array_op[ii].buffer_payload; 3996 p_buffer_swvdec = &m_buffer_array_op[ii].buffer_swvdec; 3997 3998 if (m_meta_buffer_mode) 3999 { 4000 p_buffer_swvdec->size = m_port_op.def.nBufferSize; 4001 p_buffer_swvdec->p_client_data = (void *) ((unsigned long) ii); 4002 4003 m_buffer_array_op[ii].buffer_populated = true; 4004 4005 (*pp_buffer_hdr)->pBuffer = p_buffer; 4006 (*pp_buffer_hdr)->pAppPrivate = p_app_data; 4007 (*pp_buffer_hdr)->nAllocLen = 4008 sizeof(struct VideoDecoderOutputMetaData); 4009 4010 OMX_SWVDEC_LOG_HIGH("op buffer %d: %p (meta buffer)", 4011 ii, 4012 *pp_buffer_hdr); 4013 4014 m_port_op.populated = port_op_populated(); 4015 m_port_op.unpopulated = OMX_FALSE; 4016 } 4017 else if (m_android_native_buffers) 4018 { 4019 private_handle_t *p_handle; 4020 4021 OMX_U8 *p_buffer_mapped; 4022 4023 p_handle = (private_handle_t *) p_buffer; 4024 4025 if (((OMX_U32) p_handle->size) < m_port_op.def.nBufferSize) 4026 { 4027 OMX_SWVDEC_LOG_ERROR("requested size (%d bytes) not equal to " 4028 "configured size (%d bytes)", 4029 p_handle->size, 4030 m_port_op.def.nBufferSize); 4031 4032 retval = OMX_ErrorBadParameter; 4033 goto buffer_use_op_exit; 4034 } 4035 4036 m_port_op.def.nBufferSize = p_handle->size; 4037 4038 p_buffer_mapped = (OMX_U8 *) mmap(NULL, 4039 p_handle->size, 4040 PROT_READ | PROT_WRITE, 4041 MAP_SHARED, 4042 p_handle->fd, 4043 0); 4044 4045 if (p_buffer_mapped == MAP_FAILED) 4046 { 4047 OMX_SWVDEC_LOG_ERROR("mmap() failed for fd %d of size %d", 4048 p_handle->fd, 4049 p_handle->size); 4050 4051 retval = OMX_ErrorInsufficientResources; 4052 goto buffer_use_op_exit; 4053 } 4054 4055 p_buffer_payload->bufferaddr = p_buffer_mapped; 4056 p_buffer_payload->pmem_fd = p_handle->fd; 4057 p_buffer_payload->buffer_len = p_handle->size; 4058 p_buffer_payload->mmaped_size = p_handle->size; 4059 p_buffer_payload->offset = 0; 4060 4061 p_buffer_swvdec->p_buffer = p_buffer_mapped; 4062 p_buffer_swvdec->size = m_port_op.def.nBufferSize; 4063 p_buffer_swvdec->p_client_data = (void *) ((unsigned long) ii); 4064 4065 m_buffer_array_op[ii].buffer_populated = true; 4066 4067 (*pp_buffer_hdr)->pBuffer = (m_android_native_buffers ? 4068 ((OMX_U8 *) p_handle) : 4069 p_buffer_mapped); 4070 (*pp_buffer_hdr)->pAppPrivate = p_app_data; 4071 (*pp_buffer_hdr)->nAllocLen = m_port_op.def.nBufferSize; 4072 4073 m_buffer_array_op[ii].ion_info.ion_fd_data.fd = p_handle->fd; 4074 4075 OMX_SWVDEC_LOG_HIGH("op buffer %d: %p", 4076 ii, 4077 *pp_buffer_hdr); 4078 4079 m_port_op.populated = port_op_populated(); 4080 m_port_op.unpopulated = OMX_FALSE; 4081 } 4082 else 4083 { 4084 OMX_SWVDEC_LOG_ERROR("neither 'meta buffer mode' nor " 4085 "'android native buffers' enabled"); 4086 4087 retval = OMX_ErrorBadParameter; 4088 } 4089 } 4090 else 4091 { 4092 OMX_SWVDEC_LOG_ERROR("all %d op buffers populated", 4093 m_port_op.def.nBufferCountActual); 4094 4095 retval = OMX_ErrorInsufficientResources; 4096 } 4097 4098 buffer_use_op_exit: 4099 return retval; 4100 } 4101 4102 /** 4103 * @brief De-allocate input buffer. 4104 * 4105 * @param[in] p_buffer_hdr: Pointer to buffer header structure. 4106 * 4107 * @retval OMX_ERRORTYPE 4108 */ 4109 OMX_ERRORTYPE omx_swvdec::buffer_deallocate_ip( 4110 OMX_BUFFERHEADERTYPE *p_buffer_hdr) 4111 { 4112 OMX_ERRORTYPE retval = OMX_ErrorNone; 4113 4114 unsigned int ii; 4115 4116 if (p_buffer_hdr == NULL) 4117 { 4118 OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL"); 4119 4120 retval = OMX_ErrorBadParameter; 4121 goto buffer_deallocate_ip_exit; 4122 } 4123 else if (m_buffer_array_ip == NULL) 4124 { 4125 OMX_SWVDEC_LOG_ERROR("ip buffer array not allocated"); 4126 4127 retval = OMX_ErrorBadParameter; 4128 goto buffer_deallocate_ip_exit; 4129 } 4130 4131 for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++) 4132 { 4133 if (p_buffer_hdr == &(m_buffer_array_ip[ii].buffer_header)) 4134 { 4135 OMX_SWVDEC_LOG_LOW("%p has index %d", 4136 p_buffer_hdr->pBuffer, 4137 ii); 4138 break; 4139 } 4140 } 4141 4142 if (ii < m_port_ip.def.nBufferCountActual) 4143 { 4144 if (m_buffer_array_ip[ii].buffer_payload.pmem_fd > 0) 4145 { 4146 m_buffer_array_ip[ii].buffer_populated = false; 4147 4148 m_port_ip.populated = OMX_FALSE; 4149 4150 munmap(m_buffer_array_ip[ii].buffer_payload.bufferaddr, 4151 m_buffer_array_ip[ii].buffer_payload.mmaped_size); 4152 4153 close(m_buffer_array_ip[ii].buffer_payload.pmem_fd); 4154 m_buffer_array_ip[ii].buffer_payload.pmem_fd = -1; 4155 4156 ion_memory_free(&m_buffer_array_ip[ii].ion_info); 4157 4158 for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++) 4159 { 4160 if (m_buffer_array_ip[ii].buffer_populated) 4161 { 4162 break; 4163 } 4164 } 4165 4166 if (ii == m_port_ip.def.nBufferCountActual) 4167 { 4168 buffer_deallocate_ip_info_array(); 4169 4170 m_port_ip.unpopulated = OMX_TRUE; 4171 } 4172 } 4173 else 4174 { 4175 OMX_SWVDEC_LOG_ERROR("%p: pmem_fd %d", 4176 p_buffer_hdr->pBuffer, 4177 m_buffer_array_ip[ii].buffer_payload.pmem_fd); 4178 } 4179 } 4180 else 4181 { 4182 OMX_SWVDEC_LOG_ERROR("%p not found", p_buffer_hdr->pBuffer); 4183 4184 retval = OMX_ErrorBadParameter; 4185 } 4186 4187 buffer_deallocate_ip_exit: 4188 return retval; 4189 } 4190 4191 /** 4192 * @brief De-allocate output buffer. 4193 * 4194 * @param[in] p_buffer_hdr: Pointer to buffer header structure. 4195 * 4196 * @retval OMX_ERRORTYPE 4197 */ 4198 OMX_ERRORTYPE omx_swvdec::buffer_deallocate_op( 4199 OMX_BUFFERHEADERTYPE *p_buffer_hdr) 4200 { 4201 OMX_ERRORTYPE retval = OMX_ErrorNone; 4202 4203 unsigned int ii; 4204 4205 if (p_buffer_hdr == NULL) 4206 { 4207 OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL"); 4208 4209 retval = OMX_ErrorBadParameter; 4210 goto buffer_deallocate_op_exit; 4211 } 4212 else if (m_buffer_array_op == NULL) 4213 { 4214 OMX_SWVDEC_LOG_ERROR("op buffer array not allocated"); 4215 4216 retval = OMX_ErrorBadParameter; 4217 goto buffer_deallocate_op_exit; 4218 } 4219 4220 for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++) 4221 { 4222 if (p_buffer_hdr == &(m_buffer_array_op[ii].buffer_header)) 4223 { 4224 OMX_SWVDEC_LOG_LOW("%p has index %d", 4225 p_buffer_hdr->pBuffer, 4226 ii); 4227 break; 4228 } 4229 } 4230 4231 if (ii < m_port_op.def.nBufferCountActual) 4232 { 4233 if (m_meta_buffer_mode) 4234 { 4235 // do nothing; munmap() & FD reset done in FBD or RR 4236 } 4237 else if (m_android_native_buffers) 4238 { 4239 munmap(m_buffer_array_op[ii].buffer_payload.bufferaddr, 4240 m_buffer_array_op[ii].buffer_payload.mmaped_size); 4241 4242 m_buffer_array_op[ii].buffer_payload.pmem_fd = -1; 4243 } 4244 else 4245 { 4246 munmap(m_buffer_array_op[ii].buffer_payload.bufferaddr, 4247 m_buffer_array_op[ii].buffer_payload.mmaped_size); 4248 4249 close(m_buffer_array_op[ii].buffer_payload.pmem_fd); 4250 4251 m_buffer_array_op[ii].buffer_payload.pmem_fd = -1; 4252 4253 ion_memory_free(&m_buffer_array_op[ii].ion_info); 4254 } 4255 4256 m_buffer_array_op[ii].buffer_populated = false; 4257 4258 m_port_op.populated = OMX_FALSE; 4259 4260 for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++) 4261 { 4262 if (m_buffer_array_op[ii].buffer_populated) 4263 { 4264 break; 4265 } 4266 } 4267 4268 if (ii == m_port_op.def.nBufferCountActual) 4269 { 4270 buffer_deallocate_op_info_array(); 4271 4272 m_port_op.unpopulated = OMX_TRUE; 4273 4274 if (m_meta_buffer_mode) 4275 { 4276 meta_buffer_array_deallocate(); 4277 } 4278 } 4279 } 4280 else 4281 { 4282 OMX_SWVDEC_LOG_ERROR("%p not found", p_buffer_hdr->pBuffer); 4283 4284 retval = OMX_ErrorBadParameter; 4285 } 4286 4287 buffer_deallocate_op_exit: 4288 return retval; 4289 } 4290 4291 /** 4292 * @brief De-allocate input buffer info array. 4293 */ 4294 void omx_swvdec::buffer_deallocate_ip_info_array() 4295 { 4296 assert(m_buffer_array_ip != NULL); 4297 4298 free(m_buffer_array_ip); 4299 4300 m_buffer_array_ip = NULL; 4301 } 4302 4303 /** 4304 * @brief De-allocate output buffer info array. 4305 */ 4306 void omx_swvdec::buffer_deallocate_op_info_array() 4307 { 4308 assert(m_buffer_array_op != NULL); 4309 4310 free(m_buffer_array_op); 4311 4312 m_buffer_array_op = NULL; 4313 } 4314 4315 /** 4316 * @brief Allocate meta buffer info array. 4317 * 4318 * @retval OMX_ERRORTYPE 4319 */ 4320 OMX_ERRORTYPE omx_swvdec::meta_buffer_array_allocate() 4321 { 4322 OMX_ERRORTYPE retval = OMX_ErrorNone; 4323 4324 m_meta_buffer_array = ((OMX_SWVDEC_META_BUFFER_INFO *) 4325 calloc(sizeof(OMX_SWVDEC_META_BUFFER_INFO), 4326 m_port_op.def.nBufferCountActual)); 4327 4328 if (m_meta_buffer_array == NULL) 4329 { 4330 OMX_SWVDEC_LOG_ERROR("failed to allocate meta_buffer info array; " 4331 "%d element%s, %zu bytes requested", 4332 m_port_op.def.nBufferCountActual, 4333 (m_port_op.def.nBufferCountActual > 1) ? "s" : "", 4334 sizeof(OMX_SWVDEC_META_BUFFER_INFO) * 4335 m_port_op.def.nBufferCountActual); 4336 4337 retval = OMX_ErrorInsufficientResources; 4338 } 4339 else 4340 { 4341 unsigned int ii; 4342 4343 for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++) 4344 { 4345 m_meta_buffer_array[ii].fd = -1; 4346 } 4347 } 4348 4349 return retval; 4350 } 4351 4352 /** 4353 * @brief De-allocate meta buffer info array. 4354 */ 4355 void omx_swvdec::meta_buffer_array_deallocate() 4356 { 4357 assert(m_meta_buffer_array != NULL); 4358 4359 free(m_meta_buffer_array); 4360 4361 m_meta_buffer_array = NULL; 4362 } 4363 4364 /** 4365 * @brief Add meta buffer reference. 4366 * 4367 * @param[in] index: Buffer index. 4368 * @param[in] fd: File descriptor. 4369 */ 4370 void omx_swvdec::meta_buffer_ref_add(unsigned int index, int fd) 4371 { 4372 if (m_meta_buffer_array[index].ref_count == 0) 4373 { 4374 m_meta_buffer_array[index].fd = fd; 4375 } 4376 4377 m_meta_buffer_array[index].ref_count++; 4378 } 4379 4380 /** 4381 * @brief Remove meta buffer reference. 4382 * 4383 * @param[in] index: Buffer index. 4384 */ 4385 void omx_swvdec::meta_buffer_ref_remove(unsigned int index) 4386 { 4387 pthread_mutex_lock(&m_meta_buffer_array_mutex); 4388 4389 m_meta_buffer_array[index].ref_count--; 4390 4391 if (m_meta_buffer_array[index].ref_count == 0) 4392 { 4393 m_meta_buffer_array[index].fd = -1; 4394 4395 munmap(m_buffer_array_op[index].buffer_payload.bufferaddr, 4396 m_buffer_array_op[index].buffer_payload.mmaped_size); 4397 4398 m_buffer_array_op[index].buffer_payload.bufferaddr = NULL; 4399 m_buffer_array_op[index].buffer_payload.offset = 0; 4400 m_buffer_array_op[index].buffer_payload.mmaped_size = 0; 4401 4402 m_buffer_array_op[index].buffer_swvdec.p_buffer = NULL; 4403 m_buffer_array_op[index].buffer_swvdec.size = 0; 4404 } 4405 4406 pthread_mutex_unlock(&m_meta_buffer_array_mutex); 4407 } 4408 4409 /** 4410 * @brief Split MPEG-4 bitstream buffer into multiple frames (if they exist). 4411 * 4412 * @param[in,out] offset_array: Array of offsets to frame headers. 4413 * @param[in] p_buffer_hdr: Pointer to buffer header. 4414 * 4415 * @retval Number of frames in buffer. 4416 */ 4417 unsigned int split_buffer_mpeg4(unsigned int *offset_array, 4418 OMX_BUFFERHEADERTYPE *p_buffer_hdr) 4419 { 4420 unsigned char *p_buffer = p_buffer_hdr->pBuffer; 4421 4422 unsigned int byte_count = 0; 4423 4424 unsigned int num_frame_headers = 0; 4425 4426 unsigned int next_4bytes; 4427 4428 while ((byte_count < p_buffer_hdr->nFilledLen) && 4429 (num_frame_headers < OMX_SWVDEC_MAX_FRAMES_PER_ETB)) 4430 { 4431 next_4bytes = *((unsigned int *) p_buffer); 4432 4433 next_4bytes = __builtin_bswap32(next_4bytes); 4434 4435 if (next_4bytes == 0x000001B6) 4436 { 4437 OMX_SWVDEC_LOG_HIGH("%p, buffer %p: " 4438 "frame header at %d bytes offset", 4439 p_buffer_hdr, 4440 p_buffer_hdr->pBuffer, 4441 byte_count); 4442 4443 offset_array[num_frame_headers] = byte_count; 4444 4445 num_frame_headers++; 4446 4447 p_buffer += 4; 4448 byte_count += 4; 4449 } 4450 else 4451 { 4452 p_buffer++; 4453 byte_count++; 4454 } 4455 } 4456 4457 return num_frame_headers; 4458 } 4459 4460 /** 4461 * @brief Check if ip port is populated, i.e., if all ip buffers are populated. 4462 * 4463 * @retval true 4464 * @retval false 4465 */ 4466 OMX_BOOL omx_swvdec::port_ip_populated() 4467 { 4468 OMX_BOOL retval = OMX_FALSE; 4469 4470 if (m_buffer_array_ip != NULL) 4471 { 4472 unsigned int ii; 4473 4474 for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++) 4475 { 4476 if (m_buffer_array_ip[ii].buffer_populated == false) 4477 { 4478 break; 4479 } 4480 } 4481 4482 if (ii == m_port_ip.def.nBufferCountActual) 4483 { 4484 retval = OMX_TRUE; 4485 } 4486 } 4487 4488 return retval; 4489 } 4490 4491 /** 4492 * @brief Check if op port is populated, i.e., if all op buffers are populated. 4493 * 4494 * @retval true 4495 * @retval false 4496 */ 4497 OMX_BOOL omx_swvdec::port_op_populated() 4498 { 4499 OMX_BOOL retval = OMX_FALSE; 4500 4501 if (m_buffer_array_op != NULL) 4502 { 4503 unsigned int ii; 4504 4505 for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++) 4506 { 4507 if (m_buffer_array_op[ii].buffer_populated == false) 4508 { 4509 break; 4510 } 4511 } 4512 4513 if (ii == m_port_op.def.nBufferCountActual) 4514 { 4515 retval = OMX_TRUE; 4516 } 4517 } 4518 4519 return retval; 4520 } 4521 4522 /** 4523 * @brief Flush input, output, or both input & output ports. 4524 * 4525 * @param[in] port_index: Index of port to flush. 4526 * 4527 * @retval OMX_ERRORTYPE 4528 */ 4529 OMX_ERRORTYPE omx_swvdec::flush(unsigned int port_index) 4530 { 4531 OMX_ERRORTYPE retval = OMX_ErrorNone; 4532 4533 if (((port_index == OMX_CORE_PORT_INDEX_IP) && 4534 m_port_ip.flush_inprogress) || 4535 ((port_index == OMX_CORE_PORT_INDEX_OP) && 4536 m_port_op.flush_inprogress) || 4537 ((port_index == OMX_ALL) && 4538 m_port_ip.flush_inprogress && 4539 m_port_op.flush_inprogress)) 4540 { 4541 OMX_SWVDEC_LOG_HIGH("flush port index %d already in progress", 4542 port_index); 4543 } 4544 else 4545 { 4546 SWVDEC_FLUSH_TYPE swvdec_flush_type; 4547 4548 SWVDEC_STATUS retval_swvdec; 4549 4550 if (port_index == OMX_CORE_PORT_INDEX_IP) 4551 { 4552 m_port_ip.flush_inprogress = OMX_TRUE; 4553 4554 // no separate SwVdec flush type for input 4555 } 4556 else if (port_index == OMX_CORE_PORT_INDEX_OP) 4557 { 4558 m_port_op.flush_inprogress = OMX_TRUE; 4559 4560 swvdec_flush_type = (m_port_ip.flush_inprogress ? 4561 SWVDEC_FLUSH_TYPE_ALL : 4562 SWVDEC_FLUSH_TYPE_OP); 4563 4564 if ((retval_swvdec = swvdec_flush(m_swvdec_handle, 4565 swvdec_flush_type)) != 4566 SWVDEC_STATUS_SUCCESS) 4567 { 4568 retval = retval_swvdec2omx(retval_swvdec); 4569 } 4570 } 4571 else if (port_index == OMX_ALL) 4572 { 4573 m_port_ip.flush_inprogress = OMX_TRUE; 4574 m_port_op.flush_inprogress = OMX_TRUE; 4575 4576 swvdec_flush_type = SWVDEC_FLUSH_TYPE_ALL; 4577 4578 if ((retval_swvdec = swvdec_flush(m_swvdec_handle, 4579 swvdec_flush_type)) != 4580 SWVDEC_STATUS_SUCCESS) 4581 { 4582 retval = retval_swvdec2omx(retval_swvdec); 4583 } 4584 } 4585 else 4586 { 4587 assert(0); 4588 } 4589 } 4590 4591 return retval; 4592 } 4593 4594 /** 4595 * @brief Allocate & map ION memory. 4596 */ 4597 int omx_swvdec::ion_memory_alloc_map(struct ion_allocation_data *p_alloc_data, 4598 struct ion_fd_data *p_fd_data, 4599 OMX_U32 size, 4600 OMX_U32 alignment) 4601 { 4602 int fd = -EINVAL; 4603 int rc = -EINVAL; 4604 4605 if ((p_alloc_data == NULL) || (p_fd_data == NULL) || (size == 0)) 4606 { 4607 OMX_SWVDEC_LOG_ERROR("invalid arguments"); 4608 goto ion_memory_alloc_map_exit; 4609 } 4610 4611 if ((fd = open("/dev/ion", O_RDONLY)) < 0) 4612 { 4613 OMX_SWVDEC_LOG_ERROR("failed to open ion device; fd = %d", fd); 4614 goto ion_memory_alloc_map_exit; 4615 } 4616 4617 p_alloc_data->len = size; 4618 p_alloc_data->align = (alignment < 4096) ? 4096 : alignment; 4619 p_alloc_data->heap_id_mask = ION_HEAP(ION_IOMMU_HEAP_ID); 4620 p_alloc_data->flags = 0; 4621 4622 OMX_SWVDEC_LOG_LOW("heap_id_mask 0x%08x, len %zu, align %zu", 4623 p_alloc_data->heap_id_mask, 4624 p_alloc_data->len, 4625 p_alloc_data->align); 4626 4627 rc = ioctl(fd, ION_IOC_ALLOC, p_alloc_data); 4628 4629 if (rc || (p_alloc_data->handle == 0)) 4630 { 4631 OMX_SWVDEC_LOG_ERROR("ioctl() for allocation failed"); 4632 4633 close(fd); 4634 fd = -ENOMEM; 4635 4636 goto ion_memory_alloc_map_exit; 4637 } 4638 4639 p_fd_data->handle = p_alloc_data->handle; 4640 4641 if (ioctl(fd, ION_IOC_MAP, p_fd_data)) 4642 { 4643 struct vdec_ion ion_buf_info; 4644 4645 OMX_SWVDEC_LOG_ERROR("ioctl() for mapping failed"); 4646 4647 ion_buf_info.ion_alloc_data = *p_alloc_data; 4648 ion_buf_info.ion_fd_device = fd; 4649 ion_buf_info.ion_fd_data = *p_fd_data; 4650 4651 ion_memory_free(&ion_buf_info); 4652 4653 p_fd_data->fd = -1; 4654 4655 close(fd); 4656 fd = -ENOMEM; 4657 4658 goto ion_memory_alloc_map_exit; 4659 } 4660 4661 ion_memory_alloc_map_exit: 4662 return fd; 4663 } 4664 4665 /** 4666 * @brief Free ION memory. 4667 */ 4668 void omx_swvdec::ion_memory_free(struct vdec_ion *p_ion_buf_info) 4669 { 4670 if (p_ion_buf_info == NULL) 4671 { 4672 OMX_SWVDEC_LOG_ERROR("p_ion_buf_info = NULL"); 4673 goto ion_memory_free_exit; 4674 } 4675 4676 if (ioctl(p_ion_buf_info->ion_fd_device, 4677 ION_IOC_FREE, 4678 &p_ion_buf_info->ion_alloc_data.handle)) 4679 { 4680 OMX_SWVDEC_LOG_ERROR("ioctl() for freeing failed"); 4681 } 4682 4683 close(p_ion_buf_info->ion_fd_device); 4684 4685 p_ion_buf_info->ion_fd_device = -1; 4686 p_ion_buf_info->ion_alloc_data.handle = 0; 4687 p_ion_buf_info->ion_fd_data.fd = -1; 4688 4689 ion_memory_free_exit: 4690 return; 4691 } 4692 4693 /** 4694 * @brief Flush cached ION output buffer. 4695 * 4696 * @param[in] index: Index of buffer in output buffer info array. 4697 */ 4698 void omx_swvdec::ion_flush_op(unsigned int index) 4699 { 4700 if (index < m_port_op.def.nBufferCountActual) 4701 { 4702 struct vdec_bufferpayload *p_buffer_payload = 4703 &m_buffer_array_op[index].buffer_payload; 4704 4705 if(p_buffer_payload) 4706 { 4707 if(p_buffer_payload->bufferaddr != NULL) 4708 { 4709 __builtin___clear_cache(reinterpret_cast<char*>((size_t*)p_buffer_payload->bufferaddr), 4710 reinterpret_cast<char*>((size_t*)p_buffer_payload->bufferaddr +p_buffer_payload->buffer_len)); 4711 } 4712 } 4713 } 4714 else 4715 { 4716 OMX_SWVDEC_LOG_ERROR("buffer index '%d' invalid", index); 4717 } 4718 4719 return; 4720 } 4721 4722 /** 4723 * ---------------------------- 4724 * component callback functions 4725 * ---------------------------- 4726 */ 4727 4728 /** 4729 * @brief Empty buffer done callback. 4730 * 4731 * @param[in] p_buffer_ip: Pointer to input buffer structure. 4732 */ 4733 void omx_swvdec::swvdec_empty_buffer_done(SWVDEC_BUFFER *p_buffer_ip) 4734 { 4735 unsigned long index = (unsigned long) p_buffer_ip->p_client_data; 4736 4737 m_buffer_array_ip[index].buffer_header.nFilledLen = 4738 p_buffer_ip->filled_length; 4739 4740 async_post_event(OMX_SWVDEC_EVENT_EBD, 4741 (unsigned long) &m_buffer_array_ip[index].buffer_header, 4742 index); 4743 } 4744 4745 /** 4746 * @brief Fill buffer done callback. 4747 * 4748 * @param[in] p_buffer_op: Pointer to output buffer structure. 4749 */ 4750 void omx_swvdec::swvdec_fill_buffer_done(SWVDEC_BUFFER *p_buffer_op) 4751 { 4752 unsigned long index = (unsigned long) p_buffer_op->p_client_data; 4753 4754 OMX_BUFFERHEADERTYPE *p_buffer_hdr; 4755 4756 if (index < ((unsigned long) m_port_op.def.nBufferCountActual)) 4757 { 4758 p_buffer_hdr = &m_buffer_array_op[index].buffer_header; 4759 4760 p_buffer_hdr->nFlags = p_buffer_op->flags; 4761 p_buffer_hdr->nTimeStamp = p_buffer_op->timestamp; 4762 p_buffer_hdr->nFilledLen = ((m_meta_buffer_mode && 4763 p_buffer_op->filled_length) ? 4764 p_buffer_hdr->nAllocLen : 4765 p_buffer_op->filled_length); 4766 } 4767 4768 async_post_event(OMX_SWVDEC_EVENT_FBD, 4769 (unsigned long) &m_buffer_array_op[index].buffer_header, 4770 index); 4771 } 4772 4773 /** 4774 * @brief Event handler callback. 4775 * 4776 * @param[in] event: Event. 4777 * @param[in] p_data: Pointer to event-specific data. 4778 */ 4779 void omx_swvdec::swvdec_event_handler(SWVDEC_EVENT event, void *p_data) 4780 { 4781 switch (event) 4782 { 4783 4784 case SWVDEC_EVENT_FLUSH_ALL_DONE: 4785 { 4786 async_post_event(OMX_SWVDEC_EVENT_FLUSH_PORT_IP, 0, 0); 4787 async_post_event(OMX_SWVDEC_EVENT_FLUSH_PORT_OP, 0, 0); 4788 4789 break; 4790 } 4791 4792 case SWVDEC_EVENT_FLUSH_OP_DONE: 4793 { 4794 async_post_event(OMX_SWVDEC_EVENT_FLUSH_PORT_OP, 0, 0); 4795 4796 break; 4797 } 4798 4799 case SWVDEC_EVENT_RELEASE_REFERENCE: 4800 { 4801 SWVDEC_BUFFER *p_buffer_op = (SWVDEC_BUFFER *) p_data; 4802 4803 unsigned long index = (unsigned long) p_buffer_op->p_client_data; 4804 4805 OMX_SWVDEC_LOG_LOW("release reference: %p", p_buffer_op->p_buffer); 4806 4807 assert(index < ((unsigned long) m_port_op.def.nBufferCountActual)); 4808 4809 if (m_meta_buffer_mode) 4810 { 4811 meta_buffer_ref_remove(index); 4812 } 4813 4814 break; 4815 } 4816 4817 case SWVDEC_EVENT_RECONFIG_REQUIRED: 4818 { 4819 async_post_event(OMX_SWVDEC_EVENT_PORT_RECONFIG, 0, 0); 4820 4821 break; 4822 } 4823 4824 case SWVDEC_EVENT_DIMENSIONS_UPDATED: 4825 { 4826 async_post_event(OMX_SWVDEC_EVENT_DIMENSIONS_UPDATED, 0, 0); 4827 4828 break; 4829 } 4830 4831 case SWVDEC_EVENT_FATAL_ERROR: 4832 default: 4833 { 4834 async_post_event(OMX_SWVDEC_EVENT_ERROR, OMX_ErrorHardware, 0); 4835 4836 break; 4837 } 4838 4839 } 4840 } 4841 4842 /** 4843 * @brief Translate SwVdec status return value to OMX error type return value. 4844 * 4845 * @param[in] retval_swvdec: SwVdec status return value. 4846 * 4847 * @retval OMX_ERRORTYPE 4848 */ 4849 OMX_ERRORTYPE omx_swvdec::retval_swvdec2omx(SWVDEC_STATUS retval_swvdec) 4850 { 4851 OMX_ERRORTYPE retval_omx; 4852 4853 switch (retval_swvdec) 4854 { 4855 4856 SWVDEC_STATUS_SUCCESS: 4857 retval_omx = OMX_ErrorNone; 4858 break; 4859 4860 SWVDEC_STATUS_FAILURE: 4861 retval_omx = OMX_ErrorUndefined; 4862 break; 4863 4864 SWVDEC_STATUS_NULL_POINTER: 4865 SWVDEC_STATUS_INVALID_PARAMETERS: 4866 retval_omx = OMX_ErrorBadParameter; 4867 break; 4868 4869 SWVDEC_STATUS_INVALID_STATE: 4870 retval_omx = OMX_ErrorInvalidState; 4871 break; 4872 4873 SWVDEC_STATUS_INSUFFICIENT_RESOURCES: 4874 retval_omx = OMX_ErrorInsufficientResources; 4875 break; 4876 4877 SWVDEC_STATUS_UNSUPPORTED: 4878 retval_omx = OMX_ErrorUnsupportedSetting; 4879 break; 4880 4881 SWVDEC_STATUS_NOT_IMPLEMENTED: 4882 retval_omx = OMX_ErrorNotImplemented; 4883 break; 4884 4885 default: 4886 retval_omx = OMX_ErrorUndefined; 4887 break; 4888 4889 } 4890 4891 return retval_omx; 4892 } 4893 4894 /** 4895 * @brief Create asynchronous thread. 4896 * 4897 * @retval OMX_ERRORTYPE 4898 */ 4899 OMX_ERRORTYPE omx_swvdec::async_thread_create() 4900 { 4901 OMX_ERRORTYPE retval = OMX_ErrorNone; 4902 4903 pthread_attr_t thread_attributes; 4904 4905 if (sem_init(&m_async_thread.sem_thread_created, 0, 0)) 4906 { 4907 OMX_SWVDEC_LOG_ERROR("failed to create async thread created semaphore"); 4908 4909 retval = OMX_ErrorInsufficientResources; 4910 } 4911 else if (sem_init(&m_async_thread.sem_event, 0, 0)) 4912 { 4913 OMX_SWVDEC_LOG_ERROR("failed to create async thread event semaphore"); 4914 4915 retval = OMX_ErrorInsufficientResources; 4916 } 4917 else if (pthread_attr_init(&thread_attributes)) 4918 { 4919 OMX_SWVDEC_LOG_ERROR("failed to create thread attributes object"); 4920 4921 retval = OMX_ErrorInsufficientResources; 4922 } 4923 else if (pthread_attr_setdetachstate(&thread_attributes, 4924 PTHREAD_CREATE_JOINABLE)) 4925 { 4926 OMX_SWVDEC_LOG_ERROR("failed to set detach state attribute"); 4927 4928 retval = OMX_ErrorInsufficientResources; 4929 4930 pthread_attr_destroy(&thread_attributes); 4931 } 4932 else 4933 { 4934 m_async_thread.created = false; 4935 m_async_thread.exit = false; 4936 4937 if (pthread_create(&m_async_thread.handle, 4938 &thread_attributes, 4939 (void *(*)(void *)) async_thread, 4940 this)) 4941 { 4942 OMX_SWVDEC_LOG_ERROR("failed to create async thread"); 4943 4944 retval = OMX_ErrorInsufficientResources; 4945 4946 pthread_attr_destroy(&thread_attributes); 4947 } 4948 else 4949 { 4950 if (pthread_setname_np(m_async_thread.handle, "swvdec_async")) 4951 { 4952 // don't return error 4953 OMX_SWVDEC_LOG_ERROR("failed to set async thread name"); 4954 } 4955 4956 sem_wait(&m_async_thread.sem_thread_created); 4957 4958 m_async_thread.created = true; 4959 } 4960 } 4961 4962 return retval; 4963 } 4964 4965 /** 4966 * @brief Destroy asynchronous thread. 4967 */ 4968 void omx_swvdec::async_thread_destroy() 4969 { 4970 if (m_async_thread.created) 4971 { 4972 m_async_thread.exit = true; 4973 4974 sem_post(&m_async_thread.sem_event); 4975 4976 pthread_join(m_async_thread.handle, NULL); 4977 4978 m_async_thread.created = false; 4979 } 4980 4981 m_async_thread.exit = false; 4982 4983 sem_destroy(&m_async_thread.sem_event); 4984 sem_destroy(&m_async_thread.sem_thread_created); 4985 } 4986 4987 /** 4988 * @brief Post event to appropriate queue. 4989 * 4990 * @param[in] event_id: Event ID. 4991 * @param[in] event_param1: Event parameter 1. 4992 * @param[in] event_param2: Event parameter 2. 4993 */ 4994 void omx_swvdec::async_post_event(unsigned long event_id, 4995 unsigned long event_param1, 4996 unsigned long event_param2) 4997 { 4998 OMX_SWVDEC_EVENT_INFO event_info; 4999 5000 event_info.event_id = event_id; 5001 event_info.event_param1 = event_param1; 5002 event_info.event_param2 = event_param2; 5003 5004 switch (event_id) 5005 { 5006 5007 case OMX_SWVDEC_EVENT_ETB: 5008 case OMX_SWVDEC_EVENT_EBD: 5009 { 5010 m_queue_port_ip.push(&event_info); 5011 break; 5012 } 5013 5014 case OMX_SWVDEC_EVENT_FTB: 5015 case OMX_SWVDEC_EVENT_FBD: 5016 { 5017 m_queue_port_op.push(&event_info); 5018 break; 5019 } 5020 5021 default: 5022 { 5023 m_queue_command.push(&event_info); 5024 break; 5025 } 5026 5027 } 5028 5029 sem_post(&m_async_thread.sem_event); 5030 } 5031 5032 /** 5033 * @brief Asynchronous thread. 5034 * 5035 * @param[in] p_cmp: Pointer to OMX SwVdec component class. 5036 */ 5037 void omx_swvdec::async_thread(void *p_cmp) 5038 { 5039 if (p_cmp == NULL) 5040 { 5041 OMX_SWVDEC_LOG_ERROR("p_cmp = NULL"); 5042 } 5043 else 5044 { 5045 omx_swvdec *p_omx_swvdec = (omx_swvdec *) p_cmp; 5046 5047 ASYNC_THREAD *p_async_thread = &p_omx_swvdec->m_async_thread; 5048 5049 OMX_SWVDEC_LOG_HIGH("created"); 5050 5051 sem_post(&p_async_thread->sem_thread_created); 5052 5053 while (p_async_thread->exit == false) 5054 { 5055 sem_wait(&p_async_thread->sem_event); 5056 5057 if (p_async_thread->exit == true) 5058 { 5059 break; 5060 } 5061 5062 p_omx_swvdec->async_process_event(p_cmp); 5063 } 5064 } 5065 5066 OMX_SWVDEC_LOG_HIGH("exiting"); 5067 } 5068 5069 /** 5070 * @brief Process event. 5071 * 5072 * @param[in] p_cmp: Pointer to OMX SwVdec component class. 5073 */ 5074 void omx_swvdec::async_process_event(void *p_cmp) 5075 { 5076 omx_swvdec *p_omx_swvdec; 5077 5078 OMX_SWVDEC_EVENT_INFO event_info; 5079 5080 OMX_ERRORTYPE retval = OMX_ErrorNone; 5081 5082 if (p_cmp == NULL) 5083 { 5084 OMX_SWVDEC_LOG_ERROR("p_cmp = NULL"); 5085 5086 goto async_process_event_exit; 5087 } 5088 5089 p_omx_swvdec = (omx_swvdec *) p_cmp; 5090 5091 // NOTE: queues popped in order of priority; do not change! 5092 5093 if ((p_omx_swvdec->m_queue_command.pop(&event_info) == false) && 5094 (p_omx_swvdec->m_queue_port_op.pop(&event_info) == false) && 5095 (p_omx_swvdec->m_queue_port_ip.pop(&event_info) == false)) 5096 { 5097 OMX_SWVDEC_LOG_LOW("no event popped"); 5098 5099 goto async_process_event_exit; 5100 } 5101 5102 switch (event_info.event_id) 5103 { 5104 5105 case OMX_SWVDEC_EVENT_CMD: 5106 { 5107 OMX_COMMANDTYPE cmd = (OMX_COMMANDTYPE) event_info.event_param1; 5108 OMX_U32 param = (OMX_U32) event_info.event_param2; 5109 5110 retval = p_omx_swvdec->async_process_event_cmd(cmd, param); 5111 break; 5112 } 5113 5114 case OMX_SWVDEC_EVENT_CMD_ACK: 5115 { 5116 OMX_COMMANDTYPE cmd = (OMX_COMMANDTYPE) event_info.event_param1; 5117 OMX_U32 param = (OMX_U32) event_info.event_param2; 5118 5119 retval = p_omx_swvdec->async_process_event_cmd_ack(cmd, param); 5120 break; 5121 } 5122 5123 case OMX_SWVDEC_EVENT_ERROR: 5124 { 5125 OMX_ERRORTYPE error_code = (OMX_ERRORTYPE) event_info.event_param1; 5126 5127 retval = p_omx_swvdec->async_process_event_error(error_code); 5128 break; 5129 } 5130 5131 case OMX_SWVDEC_EVENT_ETB: 5132 { 5133 OMX_BUFFERHEADERTYPE *p_buffer_hdr = 5134 (OMX_BUFFERHEADERTYPE *) event_info.event_param1; 5135 5136 unsigned int index = event_info.event_param2; 5137 5138 retval = p_omx_swvdec->async_process_event_etb(p_buffer_hdr, index); 5139 break; 5140 } 5141 5142 case OMX_SWVDEC_EVENT_FTB: 5143 { 5144 OMX_BUFFERHEADERTYPE *p_buffer_hdr = 5145 (OMX_BUFFERHEADERTYPE *) event_info.event_param1; 5146 5147 unsigned int index = event_info.event_param2; 5148 5149 retval = p_omx_swvdec->async_process_event_ftb(p_buffer_hdr, index); 5150 break; 5151 } 5152 5153 case OMX_SWVDEC_EVENT_EBD: 5154 { 5155 OMX_BUFFERHEADERTYPE *p_buffer_hdr = 5156 (OMX_BUFFERHEADERTYPE *) event_info.event_param1; 5157 5158 unsigned int index = event_info.event_param2; 5159 5160 retval = p_omx_swvdec->async_process_event_ebd(p_buffer_hdr, index); 5161 break; 5162 } 5163 5164 case OMX_SWVDEC_EVENT_FBD: 5165 { 5166 OMX_BUFFERHEADERTYPE *p_buffer_hdr = 5167 (OMX_BUFFERHEADERTYPE *) event_info.event_param1; 5168 5169 unsigned int index = event_info.event_param2; 5170 5171 retval = p_omx_swvdec->async_process_event_fbd(p_buffer_hdr, index); 5172 break; 5173 } 5174 5175 case OMX_SWVDEC_EVENT_EOS: 5176 { 5177 retval = p_omx_swvdec->async_process_event_eos(); 5178 break; 5179 } 5180 5181 case OMX_SWVDEC_EVENT_FLUSH_PORT_IP: 5182 { 5183 retval = p_omx_swvdec->async_process_event_flush_port_ip(); 5184 break; 5185 } 5186 5187 case OMX_SWVDEC_EVENT_FLUSH_PORT_OP: 5188 { 5189 retval = p_omx_swvdec->async_process_event_flush_port_op(); 5190 break; 5191 } 5192 5193 case OMX_SWVDEC_EVENT_PORT_RECONFIG: 5194 { 5195 retval = p_omx_swvdec->async_process_event_port_reconfig(); 5196 break; 5197 } 5198 5199 case OMX_SWVDEC_EVENT_DIMENSIONS_UPDATED: 5200 { 5201 retval = p_omx_swvdec->async_process_event_dimensions_updated(); 5202 break; 5203 } 5204 5205 default: 5206 { 5207 assert(0); 5208 5209 retval = OMX_ErrorUndefined; 5210 break; 5211 } 5212 5213 } 5214 5215 if (retval != OMX_ErrorNone) 5216 { 5217 p_omx_swvdec->async_post_event(OMX_SWVDEC_EVENT_ERROR, retval, 0); 5218 } 5219 5220 async_process_event_exit: 5221 return; 5222 } 5223 5224 /** 5225 * @brief Process command event. 5226 * 5227 * @param[in] cmd: Command. 5228 * @param[in] param: Command parameter. 5229 * 5230 * @retval OMX_ERRORTYPE 5231 */ 5232 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd(OMX_COMMANDTYPE cmd, 5233 OMX_U32 param) 5234 { 5235 OMX_ERRORTYPE retval = OMX_ErrorNone; 5236 5237 bool cmd_ack = false; 5238 5239 SWVDEC_STATUS retval_swvdec; 5240 5241 switch (cmd) 5242 { 5243 5244 case OMX_CommandStateSet: 5245 { 5246 retval = async_process_event_cmd_state_set(&cmd_ack, 5247 (OMX_STATETYPE) param); 5248 break; 5249 } 5250 5251 case OMX_CommandFlush: 5252 { 5253 retval = async_process_event_cmd_flush((unsigned int) param); 5254 break; 5255 } 5256 5257 case OMX_CommandPortDisable: 5258 { 5259 retval = async_process_event_cmd_port_disable(&cmd_ack, 5260 (unsigned int) param); 5261 break; 5262 } 5263 5264 case OMX_CommandPortEnable: 5265 { 5266 retval = async_process_event_cmd_port_enable(&cmd_ack, 5267 (unsigned int) param); 5268 break; 5269 } 5270 5271 default: 5272 { 5273 OMX_SWVDEC_LOG_ERROR("cmd '%d' invalid", (int) cmd); 5274 5275 retval = OMX_ErrorBadParameter; 5276 break; 5277 } 5278 5279 } // switch (cmd) 5280 5281 if (retval != OMX_ErrorNone) 5282 { 5283 async_post_event(OMX_SWVDEC_EVENT_ERROR, retval, 0); 5284 } 5285 else if (cmd_ack) 5286 { 5287 async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, cmd, param); 5288 } 5289 5290 sem_post(&m_sem_cmd); 5291 5292 return retval; 5293 } 5294 5295 /** 5296 * @brief Process command acknowledgement event. 5297 * 5298 * @param[in] cmd: Command. 5299 * @param[in] param: Command parameter. 5300 * 5301 * @retval OMX_ERRORTYPE 5302 */ 5303 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_ack(OMX_COMMANDTYPE cmd, 5304 OMX_U32 param) 5305 { 5306 OMX_ERRORTYPE retval = OMX_ErrorNone; 5307 5308 switch (cmd) 5309 { 5310 5311 case OMX_CommandStateSet: 5312 { 5313 OMX_SWVDEC_LOG_HIGH("%s -> %s", 5314 OMX_STATETYPE_STRING(m_state), 5315 OMX_STATETYPE_STRING((OMX_STATETYPE) param)); 5316 5317 m_state = (OMX_STATETYPE) param; 5318 5319 OMX_SWVDEC_LOG_CALLBACK("EventHandler(): OMX_EventCmdComplete, " 5320 "OMX_CommandStateSet, %s", 5321 OMX_STATETYPE_STRING(m_state)); 5322 5323 m_callback.EventHandler(&m_cmp, 5324 m_app_data, 5325 OMX_EventCmdComplete, 5326 OMX_CommandStateSet, 5327 (OMX_U32) m_state, 5328 NULL); 5329 break; 5330 } 5331 5332 case OMX_CommandFlush: 5333 case OMX_CommandPortEnable: 5334 case OMX_CommandPortDisable: 5335 { 5336 if ((cmd == OMX_CommandPortEnable) && m_port_reconfig_inprogress) 5337 { 5338 m_port_reconfig_inprogress = false; 5339 } 5340 5341 OMX_SWVDEC_LOG_CALLBACK("EventHandler(): OMX_EventCmdComplete, " 5342 "%s, port index %d", 5343 OMX_COMMANDTYPE_STRING(cmd), 5344 param); 5345 5346 m_callback.EventHandler(&m_cmp, 5347 m_app_data, 5348 OMX_EventCmdComplete, 5349 cmd, 5350 param, 5351 NULL); 5352 break; 5353 } 5354 5355 default: 5356 { 5357 OMX_SWVDEC_LOG_ERROR("cmd '%d' invalid", (int) cmd); 5358 5359 retval = OMX_ErrorBadParameter; 5360 break; 5361 } 5362 5363 } // switch (cmd) 5364 5365 return retval; 5366 } 5367 5368 /** 5369 * @brief Process error event. 5370 * 5371 * @param[in] error_code: Error code. 5372 * 5373 * @retval OMX_ErrorNone 5374 */ 5375 OMX_ERRORTYPE omx_swvdec::async_process_event_error(OMX_ERRORTYPE error_code) 5376 { 5377 if (error_code == OMX_ErrorInvalidState) 5378 { 5379 OMX_SWVDEC_LOG_HIGH("%s -> OMX_StateInvalid", 5380 OMX_STATETYPE_STRING(m_state)); 5381 5382 m_state = OMX_StateInvalid; 5383 } 5384 5385 OMX_SWVDEC_LOG_CALLBACK("EventHandler(): OMX_EventError, 0x%08x", 5386 error_code); 5387 5388 m_callback.EventHandler(&m_cmp, 5389 m_app_data, 5390 OMX_EventError, 5391 (OMX_U32) error_code, 5392 0, 5393 NULL); 5394 5395 return OMX_ErrorNone; 5396 } 5397 5398 /** 5399 * @brief Process OMX_CommandStateSet. 5400 * 5401 * @param[in,out] p_cmd_ack: Pointer to 'command acknowledge' boolean variable. 5402 * @param[in] state_new: New state to which transition is requested. 5403 * 5404 * @retval OMX_ERRORTYPE 5405 */ 5406 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_state_set( 5407 bool *p_cmd_ack, 5408 OMX_STATETYPE state_new) 5409 { 5410 OMX_ERRORTYPE retval = OMX_ErrorNone; 5411 5412 SWVDEC_STATUS retval_swvdec; 5413 5414 OMX_SWVDEC_LOG_HIGH("'%s-to-%s' requested", 5415 OMX_STATETYPE_STRING(m_state), 5416 OMX_STATETYPE_STRING(state_new)); 5417 5418 /** 5419 * Only the following state transitions are allowed via CommandStateSet: 5420 * 5421 * LOADED -> IDLE -> EXECUTING 5422 * LOADED <- IDLE <- EXECUTING 5423 */ 5424 5425 if (m_state == OMX_StateInvalid) 5426 { 5427 OMX_SWVDEC_LOG_ERROR("in state %s", OMX_STATETYPE_STRING(m_state)); 5428 5429 retval = OMX_ErrorInvalidState; 5430 } 5431 else if (state_new == OMX_StateInvalid) 5432 { 5433 OMX_SWVDEC_LOG_ERROR("requested transition to state %s", 5434 OMX_STATETYPE_STRING(state_new)); 5435 5436 retval = OMX_ErrorInvalidState; 5437 } 5438 else if ((m_state == OMX_StateLoaded) && 5439 (state_new == OMX_StateIdle)) 5440 { 5441 if ((m_port_ip.populated == OMX_TRUE) && 5442 (m_port_op.populated == OMX_TRUE)) 5443 { 5444 if ((retval_swvdec = swvdec_start(m_swvdec_handle)) == 5445 SWVDEC_STATUS_SUCCESS) 5446 { 5447 *p_cmd_ack = true; 5448 } 5449 else 5450 { 5451 OMX_SWVDEC_LOG_ERROR("failed to start SwVdec"); 5452 5453 retval = retval_swvdec2omx(retval_swvdec); 5454 } 5455 } 5456 else 5457 { 5458 m_status_flags |= (1 << PENDING_STATE_LOADED_TO_IDLE); 5459 5460 OMX_SWVDEC_LOG_LOW("'loaded-to-idle' pending"); 5461 } 5462 } 5463 else if ((m_state == OMX_StateIdle) && 5464 (state_new == OMX_StateExecuting)) 5465 { 5466 *p_cmd_ack = true; 5467 } 5468 else if ((m_state == OMX_StateExecuting) && 5469 (state_new == OMX_StateIdle)) 5470 { 5471 m_status_flags |= (1 << PENDING_STATE_EXECUTING_TO_IDLE); 5472 5473 OMX_SWVDEC_LOG_LOW("'executing-to-idle' pending"); 5474 5475 retval = flush(OMX_ALL); 5476 } 5477 else if ((m_state == OMX_StateIdle) && 5478 (state_new == OMX_StateLoaded)) 5479 { 5480 if ((m_port_ip.unpopulated == OMX_TRUE) && 5481 (m_port_op.unpopulated == OMX_TRUE)) 5482 { 5483 if ((retval_swvdec = swvdec_stop(m_swvdec_handle)) == 5484 SWVDEC_STATUS_SUCCESS) 5485 { 5486 *p_cmd_ack = true; 5487 } 5488 else 5489 { 5490 OMX_SWVDEC_LOG_ERROR("failed to stop SwVdec"); 5491 5492 retval = retval_swvdec2omx(retval_swvdec); 5493 } 5494 } 5495 else 5496 { 5497 m_status_flags |= (1 << PENDING_STATE_IDLE_TO_LOADED); 5498 5499 OMX_SWVDEC_LOG_LOW("'idle-to-loaded' pending"); 5500 } 5501 } 5502 else 5503 { 5504 OMX_SWVDEC_LOG_ERROR("state transition '%s -> %s' illegal", 5505 OMX_STATETYPE_STRING(m_state), 5506 OMX_STATETYPE_STRING(state_new)); 5507 5508 retval = ((state_new == m_state) ? 5509 OMX_ErrorSameState : 5510 OMX_ErrorIncorrectStateTransition); 5511 } 5512 5513 return retval; 5514 } 5515 5516 /** 5517 * @brief Process OMX_CommandFlush. 5518 * 5519 * @param[in] port_index: Index of port to flush. 5520 * 5521 * @retval OMX_ERRORTYPE 5522 */ 5523 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_flush(unsigned int port_index) 5524 { 5525 OMX_ERRORTYPE retval = OMX_ErrorNone; 5526 5527 OMX_SWVDEC_LOG_HIGH("flush port index %d requested", port_index); 5528 5529 if (port_index == OMX_CORE_PORT_INDEX_IP) 5530 { 5531 m_status_flags |= (1 << PENDING_PORT_FLUSH_IP); 5532 5533 OMX_SWVDEC_LOG_LOW("ip port flush pending"); 5534 } 5535 else if (port_index == OMX_CORE_PORT_INDEX_OP) 5536 { 5537 m_status_flags |= (1 << PENDING_PORT_FLUSH_OP); 5538 5539 OMX_SWVDEC_LOG_LOW("op port flush pending"); 5540 } 5541 else if (port_index == OMX_ALL) 5542 { 5543 m_status_flags |= (1 << PENDING_PORT_FLUSH_IP); 5544 m_status_flags |= (1 << PENDING_PORT_FLUSH_OP); 5545 5546 OMX_SWVDEC_LOG_LOW("ip & op ports flush pending"); 5547 } 5548 5549 retval = flush(port_index); 5550 5551 return retval; 5552 } 5553 5554 /** 5555 * @brief Process OMX_CommandPortDisable. 5556 * 5557 * @param[in,out] p_cmd_ack: Pointer to 'command acknowledge' boolean variable. 5558 * @param[in] port_index: Index of port to disable. 5559 * 5560 * @retval OMX_ERRORTYPE 5561 */ 5562 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_port_disable( 5563 bool *p_cmd_ack, 5564 unsigned int port_index) 5565 { 5566 OMX_ERRORTYPE retval = OMX_ErrorNone; 5567 5568 OMX_SWVDEC_LOG_HIGH("disable port index %d requested", port_index); 5569 5570 if (port_index == OMX_CORE_PORT_INDEX_IP) 5571 { 5572 if (m_port_ip.enabled == OMX_FALSE) 5573 { 5574 OMX_SWVDEC_LOG_ERROR("ip port already disabled"); 5575 5576 retval = OMX_ErrorBadPortIndex; 5577 } 5578 else 5579 { 5580 m_port_ip.enabled = OMX_FALSE; 5581 5582 if (m_port_ip.unpopulated) 5583 { 5584 *p_cmd_ack = true; 5585 } 5586 else 5587 { 5588 m_status_flags |= (1 << PENDING_PORT_DISABLE_IP); 5589 5590 OMX_SWVDEC_LOG_LOW("ip port disable pending"); 5591 5592 if (m_port_ip.num_pending_buffers) 5593 { 5594 retval = flush(port_index); 5595 } 5596 } 5597 } 5598 } 5599 else if (port_index == OMX_CORE_PORT_INDEX_OP) 5600 { 5601 if (m_port_op.enabled == OMX_FALSE) 5602 { 5603 OMX_SWVDEC_LOG_ERROR("op port already disabled"); 5604 5605 retval = OMX_ErrorBadPortIndex; 5606 } 5607 else 5608 { 5609 m_port_op.enabled = OMX_FALSE; 5610 5611 if (m_port_op.unpopulated) 5612 { 5613 *p_cmd_ack = true; 5614 } 5615 else 5616 { 5617 m_status_flags |= (1 << PENDING_PORT_DISABLE_OP); 5618 5619 OMX_SWVDEC_LOG_LOW("op port disable pending"); 5620 5621 if (m_port_op.num_pending_buffers) 5622 { 5623 retval = flush(port_index); 5624 } 5625 } 5626 } 5627 } 5628 else if (port_index == OMX_ALL) 5629 { 5630 if (m_port_ip.enabled == OMX_FALSE) 5631 { 5632 OMX_SWVDEC_LOG_ERROR("ip port already disabled"); 5633 5634 retval = OMX_ErrorBadPortIndex; 5635 } 5636 else if (m_port_op.enabled == OMX_FALSE) 5637 { 5638 OMX_SWVDEC_LOG_ERROR("op port already disabled"); 5639 5640 retval = OMX_ErrorBadPortIndex; 5641 } 5642 else 5643 { 5644 if (m_port_ip.unpopulated && m_port_op.unpopulated) 5645 { 5646 *p_cmd_ack = true; 5647 } 5648 else 5649 { 5650 m_port_ip.enabled = OMX_FALSE; 5651 m_port_op.enabled = OMX_FALSE; 5652 5653 if (m_port_ip.unpopulated == OMX_FALSE) 5654 { 5655 m_status_flags |= (1 << PENDING_PORT_DISABLE_IP); 5656 5657 OMX_SWVDEC_LOG_LOW("ip port disable pending"); 5658 5659 if (m_port_ip.num_pending_buffers) 5660 { 5661 retval = flush(port_index); 5662 } 5663 } 5664 5665 if ((retval == OMX_ErrorNone) && 5666 (m_port_op.unpopulated == OMX_FALSE)) 5667 { 5668 m_status_flags |= (1 << PENDING_PORT_DISABLE_OP); 5669 5670 OMX_SWVDEC_LOG_LOW("op port disable pending"); 5671 5672 if (m_port_op.num_pending_buffers) 5673 { 5674 retval = flush(port_index); 5675 } 5676 } 5677 } 5678 } 5679 } 5680 else 5681 { 5682 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", 5683 port_index); 5684 5685 retval = OMX_ErrorBadPortIndex; 5686 } 5687 5688 return retval; 5689 } 5690 5691 /** 5692 * @brief Process OMX_CommandPortEnable. 5693 * 5694 * @param[in,out] p_cmd_ack: Pointer to 'command acknowledge' boolean variable. 5695 * @param[in] port_index: Index of port to enable. 5696 * 5697 * @retval OMX_ERRORTYPE 5698 */ 5699 OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_port_enable( 5700 bool *p_cmd_ack, 5701 unsigned int port_index) 5702 { 5703 OMX_ERRORTYPE retval = OMX_ErrorNone; 5704 5705 OMX_SWVDEC_LOG_HIGH("enable port index %d requested", port_index); 5706 5707 if (port_index == OMX_CORE_PORT_INDEX_IP) 5708 { 5709 if (m_port_ip.enabled) 5710 { 5711 OMX_SWVDEC_LOG_ERROR("ip port already enabled"); 5712 5713 retval = OMX_ErrorBadPortIndex; 5714 } 5715 else 5716 { 5717 m_port_ip.enabled = OMX_TRUE; 5718 5719 if (m_port_ip.populated) 5720 { 5721 *p_cmd_ack = true; 5722 } 5723 else 5724 { 5725 m_status_flags |= (1 << PENDING_PORT_ENABLE_IP); 5726 5727 OMX_SWVDEC_LOG_LOW("ip port enable pending"); 5728 } 5729 } 5730 } 5731 else if (port_index == OMX_CORE_PORT_INDEX_OP) 5732 { 5733 if (m_port_op.enabled) 5734 { 5735 OMX_SWVDEC_LOG_ERROR("op port already enabled"); 5736 5737 retval = OMX_ErrorBadPortIndex; 5738 } 5739 else 5740 { 5741 m_port_op.enabled = OMX_TRUE; 5742 5743 if (m_port_op.populated) 5744 { 5745 *p_cmd_ack = true; 5746 } 5747 else 5748 { 5749 m_status_flags |= (1 << PENDING_PORT_ENABLE_OP); 5750 5751 OMX_SWVDEC_LOG_LOW("op port enable pending"); 5752 } 5753 } 5754 } 5755 else if (port_index == OMX_ALL) 5756 { 5757 if (m_port_ip.enabled) 5758 { 5759 OMX_SWVDEC_LOG_ERROR("ip port already enabled"); 5760 5761 retval = OMX_ErrorBadPortIndex; 5762 } 5763 else if (m_port_op.enabled) 5764 { 5765 OMX_SWVDEC_LOG_ERROR("op port already enabled"); 5766 5767 retval = OMX_ErrorBadPortIndex; 5768 } 5769 else 5770 { 5771 m_port_ip.enabled = OMX_TRUE; 5772 m_port_op.enabled = OMX_TRUE; 5773 5774 if (m_port_ip.populated && m_port_op.populated) 5775 { 5776 *p_cmd_ack = true; 5777 } 5778 else if (m_port_ip.populated == false) 5779 { 5780 m_status_flags |= (1 << PENDING_PORT_ENABLE_IP); 5781 5782 OMX_SWVDEC_LOG_LOW("ip port enable pending"); 5783 } 5784 else if (m_port_op.populated == false) 5785 { 5786 m_status_flags |= (1 << PENDING_PORT_ENABLE_OP); 5787 5788 OMX_SWVDEC_LOG_LOW("op port enable pending"); 5789 } 5790 } 5791 } 5792 else 5793 { 5794 OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", 5795 port_index); 5796 5797 retval = OMX_ErrorBadPortIndex; 5798 } 5799 5800 return retval; 5801 } 5802 5803 /** 5804 * @brief Process ETB event. 5805 * 5806 * @param[in] p_buffer_hdr: Pointer to buffer header. 5807 * @param[in] index: Index of buffer in input buffer info array. 5808 * 5809 * @retval OMX_ERRORTYPE 5810 */ 5811 OMX_ERRORTYPE omx_swvdec::async_process_event_etb( 5812 OMX_BUFFERHEADERTYPE *p_buffer_hdr, 5813 unsigned int index) 5814 { 5815 OMX_ERRORTYPE retval = OMX_ErrorNone; 5816 5817 m_port_ip.num_pending_buffers++; 5818 5819 if ((p_buffer_hdr->nFilledLen == 0) && 5820 ((p_buffer_hdr->nFlags & OMX_BUFFERFLAG_EOS) == 0)) 5821 { 5822 OMX_SWVDEC_LOG_HIGH("returning %p, buffer %p; " 5823 "zero length & no EOS flag", 5824 p_buffer_hdr, 5825 p_buffer_hdr->pBuffer); 5826 5827 async_post_event(OMX_SWVDEC_EVENT_EBD, 5828 (unsigned long) p_buffer_hdr, 5829 (unsigned long) index); 5830 } 5831 else if (m_port_ip.flush_inprogress) 5832 { 5833 OMX_SWVDEC_LOG_HIGH("returning %p, buffer %p; " 5834 "ip port flush in progress", 5835 p_buffer_hdr, 5836 p_buffer_hdr->pBuffer); 5837 5838 async_post_event(OMX_SWVDEC_EVENT_EBD, 5839 (unsigned long) p_buffer_hdr, 5840 (unsigned long) index); 5841 } 5842 else 5843 { 5844 SWVDEC_STATUS retval_swvdec; 5845 5846 SWVDEC_BUFFER *p_buffer_swvdec = 5847 &(m_buffer_array_ip[index].buffer_swvdec); 5848 5849 if (p_buffer_hdr->nFilledLen && 5850 ((p_buffer_hdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) == 0)) 5851 { 5852 m_queue_timestamp.push(p_buffer_hdr->nTimeStamp); 5853 } 5854 5855 assert(p_buffer_swvdec->p_buffer == p_buffer_hdr->pBuffer); 5856 5857 if (m_arbitrary_bytes_mode && 5858 p_buffer_hdr->nFilledLen && 5859 ((p_buffer_hdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) == 0)) 5860 { 5861 unsigned int offset_array[OMX_SWVDEC_MAX_FRAMES_PER_ETB] = {0}; 5862 5863 unsigned int num_frame_headers = 1; 5864 5865 if ((m_omx_video_codingtype == 5866 ((OMX_VIDEO_CODINGTYPE) QOMX_VIDEO_CodingDivx)) || 5867 (m_omx_video_codingtype == OMX_VIDEO_CodingMPEG4)) 5868 { 5869 num_frame_headers = split_buffer_mpeg4(offset_array, 5870 p_buffer_hdr); 5871 } 5872 else 5873 { 5874 assert(0); 5875 } 5876 5877 if(num_frame_headers > 1) 5878 { 5879 m_buffer_array_ip[index].split_count = num_frame_headers - 1; 5880 5881 for (unsigned int ii = 0; ii < num_frame_headers; ii++) 5882 { 5883 p_buffer_swvdec->flags = p_buffer_hdr->nFlags; 5884 p_buffer_swvdec->timestamp = p_buffer_hdr->nTimeStamp; 5885 5886 if (ii == 0) 5887 { 5888 p_buffer_swvdec->offset = 0; 5889 p_buffer_swvdec->filled_length = (offset_array[ii + 1] ? 5890 offset_array[ii + 1] : 5891 p_buffer_hdr->nFilledLen); 5892 } 5893 else 5894 { 5895 p_buffer_swvdec->offset = offset_array[ii]; 5896 p_buffer_swvdec->filled_length = 5897 p_buffer_hdr->nFilledLen - offset_array[ii]; 5898 } 5899 5900 m_diag.dump_ip(p_buffer_swvdec->p_buffer + 5901 p_buffer_swvdec->offset, 5902 p_buffer_swvdec->filled_length); 5903 5904 retval_swvdec = swvdec_emptythisbuffer(m_swvdec_handle, 5905 p_buffer_swvdec); 5906 5907 if (retval_swvdec != SWVDEC_STATUS_SUCCESS) 5908 { 5909 retval = retval_swvdec2omx(retval_swvdec); 5910 break; 5911 } 5912 } 5913 } 5914 else 5915 { 5916 OMX_SWVDEC_LOG_HIGH("No frame detected for Buffer %p, with TS %lld", 5917 p_buffer_hdr->pBuffer, p_buffer_hdr->nTimeStamp ); 5918 5919 p_buffer_swvdec->flags = p_buffer_hdr->nFlags; 5920 p_buffer_swvdec->offset = 0; 5921 p_buffer_swvdec->timestamp = p_buffer_hdr->nTimeStamp; 5922 p_buffer_swvdec->filled_length = p_buffer_hdr->nFilledLen; 5923 5924 m_diag.dump_ip(p_buffer_swvdec->p_buffer + p_buffer_swvdec->offset, 5925 p_buffer_swvdec->filled_length); 5926 5927 retval_swvdec = swvdec_emptythisbuffer(m_swvdec_handle, 5928 p_buffer_swvdec); 5929 5930 if (retval_swvdec != SWVDEC_STATUS_SUCCESS) 5931 { 5932 retval = retval_swvdec2omx(retval_swvdec); 5933 } 5934 } 5935 } 5936 else 5937 { 5938 p_buffer_swvdec->flags = p_buffer_hdr->nFlags; 5939 p_buffer_swvdec->offset = 0; 5940 p_buffer_swvdec->timestamp = p_buffer_hdr->nTimeStamp; 5941 p_buffer_swvdec->filled_length = p_buffer_hdr->nFilledLen; 5942 5943 m_diag.dump_ip(p_buffer_swvdec->p_buffer + p_buffer_swvdec->offset, 5944 p_buffer_swvdec->filled_length); 5945 5946 retval_swvdec = swvdec_emptythisbuffer(m_swvdec_handle, 5947 p_buffer_swvdec); 5948 5949 if (retval_swvdec != SWVDEC_STATUS_SUCCESS) 5950 { 5951 retval = retval_swvdec2omx(retval_swvdec); 5952 } 5953 } 5954 } 5955 return retval; 5956 } 5957 5958 /** 5959 * @brief Process FTB event. 5960 * 5961 * @param[in] p_buffer_hdr: Pointer to buffer header. 5962 * @param[in] index: Index of buffer in output buffer info array. 5963 * 5964 * @retval OMX_ERRORTYPE 5965 */ 5966 OMX_ERRORTYPE omx_swvdec::async_process_event_ftb( 5967 OMX_BUFFERHEADERTYPE *p_buffer_hdr, 5968 unsigned int index) 5969 { 5970 OMX_ERRORTYPE retval = OMX_ErrorNone; 5971 5972 m_port_op.num_pending_buffers++; 5973 5974 if (m_port_op.flush_inprogress) 5975 { 5976 OMX_SWVDEC_LOG_HIGH("returning %p, buffer %p; " 5977 "op port flush in progress", 5978 p_buffer_hdr, 5979 m_buffer_array_op[index].buffer_swvdec.p_buffer); 5980 5981 async_post_event(OMX_SWVDEC_EVENT_FBD, 5982 (unsigned long) p_buffer_hdr, 5983 (unsigned long) index); 5984 } 5985 else 5986 { 5987 SWVDEC_STATUS retval_swvdec; 5988 5989 SWVDEC_BUFFER *p_buffer_swvdec = 5990 &(m_buffer_array_op[index].buffer_swvdec); 5991 5992 retval_swvdec = swvdec_fillthisbuffer(m_swvdec_handle, p_buffer_swvdec); 5993 5994 if (retval_swvdec != SWVDEC_STATUS_SUCCESS) 5995 { 5996 retval = retval_swvdec2omx(retval_swvdec); 5997 } 5998 } 5999 6000 return retval; 6001 } 6002 6003 /** 6004 * @brief Process EBD event. 6005 * 6006 * @param[in] p_buffer_hdr: Pointer to buffer header. 6007 * @param[in] index: Index of buffer in output buffer info array. 6008 * 6009 * @retval OMX_ERRORTYPE 6010 */ 6011 OMX_ERRORTYPE omx_swvdec::async_process_event_ebd( 6012 OMX_BUFFERHEADERTYPE *p_buffer_hdr, 6013 unsigned int index) 6014 { 6015 OMX_ERRORTYPE retval = OMX_ErrorNone; 6016 6017 if (index < m_port_ip.def.nBufferCountActual) 6018 { 6019 if (m_arbitrary_bytes_mode && m_buffer_array_ip[index].split_count) 6020 { 6021 m_buffer_array_ip[index].split_count--; 6022 } 6023 else 6024 { 6025 m_port_ip.num_pending_buffers--; 6026 6027 OMX_SWVDEC_LOG_CALLBACK( 6028 "EmptyBufferDone(): %p, buffer %p", 6029 p_buffer_hdr, 6030 m_buffer_array_ip[index].buffer_swvdec.p_buffer); 6031 6032 m_callback.EmptyBufferDone(&m_cmp, m_app_data, p_buffer_hdr); 6033 } 6034 } 6035 else 6036 { 6037 OMX_SWVDEC_LOG_ERROR("buffer index '%d' invalid", index); 6038 6039 retval = OMX_ErrorBadParameter; 6040 } 6041 6042 return retval; 6043 } 6044 6045 /** 6046 * @brief Process FBD event. 6047 * 6048 * @param[in] p_buffer_hdr: Pointer to buffer header. 6049 * @param[in] index: Index of buffer in output buffer info array. 6050 * 6051 * @retval OMX_ERRORTYPE 6052 */ 6053 OMX_ERRORTYPE omx_swvdec::async_process_event_fbd( 6054 OMX_BUFFERHEADERTYPE *p_buffer_hdr, 6055 unsigned int index) 6056 { 6057 OMX_ERRORTYPE retval = OMX_ErrorNone; 6058 6059 static long long timestamp_prev = 0; 6060 6061 if (index < m_port_op.def.nBufferCountActual) 6062 { 6063 OMX_U8 *p_buffer; 6064 6065 p_buffer = m_buffer_array_op[index].buffer_swvdec.p_buffer; 6066 6067 m_port_op.num_pending_buffers--; 6068 6069 if (m_port_op.flush_inprogress) 6070 { 6071 p_buffer_hdr->nFilledLen = 0; 6072 p_buffer_hdr->nTimeStamp = 0; 6073 p_buffer_hdr->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT; 6074 } 6075 6076 if (p_buffer_hdr->nFilledLen) 6077 { 6078 if (m_sync_frame_decoding_mode) 6079 { 6080 OMX_SWVDEC_LOG_LOW("sync frame decoding mode; " 6081 "setting timestamp to zero"); 6082 6083 p_buffer_hdr->nTimeStamp = 0; 6084 } 6085 else 6086 { 6087 if (m_queue_timestamp.empty()) 6088 { 6089 OMX_SWVDEC_LOG_ERROR("timestamp queue empty; " 6090 "re-using previous timestamp %lld", 6091 timestamp_prev); 6092 6093 p_buffer_hdr->nTimeStamp = timestamp_prev; 6094 } 6095 else 6096 { 6097 p_buffer_hdr->nTimeStamp = m_queue_timestamp.top(); 6098 6099 m_queue_timestamp.pop(); 6100 6101 timestamp_prev = p_buffer_hdr->nTimeStamp; 6102 } 6103 } 6104 6105 ion_flush_op(index); 6106 6107 if (m_meta_buffer_mode) 6108 { 6109 pthread_mutex_lock(&m_meta_buffer_array_mutex); 6110 } 6111 6112 m_diag.dump_op(p_buffer, 6113 m_frame_dimensions.width, 6114 m_frame_dimensions.height, 6115 m_frame_attributes.stride, 6116 m_frame_attributes.scanlines); 6117 6118 if (m_meta_buffer_mode) 6119 { 6120 pthread_mutex_unlock(&m_meta_buffer_array_mutex); 6121 } 6122 } 6123 else 6124 { 6125 OMX_SWVDEC_LOG_LOW("filled length zero; " 6126 "setting timestamp to zero"); 6127 6128 p_buffer_hdr->nTimeStamp = 0; 6129 } 6130 6131 if (p_buffer_hdr->nFlags & OMX_BUFFERFLAG_EOS) 6132 { 6133 async_post_event(OMX_SWVDEC_EVENT_EOS, 0, 0); 6134 6135 OMX_SWVDEC_LOG_LOW("flushing %zu elements in timestamp queue", 6136 m_queue_timestamp.size()); 6137 6138 while (m_queue_timestamp.empty() == false) 6139 { 6140 m_queue_timestamp.pop(); 6141 } 6142 } 6143 6144 if (m_meta_buffer_mode && 6145 ((p_buffer_hdr->nFlags & OMX_BUFFERFLAG_READONLY)) == 0) 6146 { 6147 meta_buffer_ref_remove(index); 6148 } 6149 6150 OMX_SWVDEC_LOG_CALLBACK( 6151 "FillBufferDone(): %p, buffer %p, " 6152 "flags 0x%08x, filled length %d, timestamp %lld", 6153 p_buffer_hdr, 6154 p_buffer, 6155 p_buffer_hdr->nFlags, 6156 p_buffer_hdr->nFilledLen, 6157 p_buffer_hdr->nTimeStamp); 6158 6159 m_callback.FillBufferDone(&m_cmp, m_app_data, p_buffer_hdr); 6160 } 6161 else 6162 { 6163 OMX_SWVDEC_LOG_ERROR("buffer index '%d' invalid", index); 6164 6165 retval = OMX_ErrorBadParameter; 6166 } 6167 6168 async_process_event_fbd_exit: 6169 return retval; 6170 } 6171 6172 /** 6173 * @brief Process EOS event. 6174 * 6175 * @retval OMX_ErrorNone 6176 */ 6177 OMX_ERRORTYPE omx_swvdec::async_process_event_eos() 6178 { 6179 OMX_SWVDEC_LOG_CALLBACK("EventHandler(): " 6180 "OMX_EventBufferFlag, port index %d, EOS", 6181 OMX_CORE_PORT_INDEX_OP); 6182 6183 m_callback.EventHandler(&m_cmp, 6184 m_app_data, 6185 OMX_EventBufferFlag, 6186 OMX_CORE_PORT_INDEX_OP, 6187 OMX_BUFFERFLAG_EOS, 6188 NULL); 6189 6190 return OMX_ErrorNone; 6191 } 6192 6193 /** 6194 * @brief Process input port flush event. 6195 * 6196 * @retval OMX_ERRORTYPE 6197 */ 6198 OMX_ERRORTYPE omx_swvdec::async_process_event_flush_port_ip() 6199 { 6200 OMX_ERRORTYPE retval = OMX_ErrorNone; 6201 6202 OMX_SWVDEC_EVENT_INFO event_info; 6203 6204 OMX_BUFFERHEADERTYPE *p_buffer_hdr; 6205 6206 unsigned int index; 6207 6208 while (m_queue_port_ip.pop(&event_info)) 6209 { 6210 switch (event_info.event_id) 6211 { 6212 6213 case OMX_SWVDEC_EVENT_ETB: 6214 { 6215 p_buffer_hdr = (OMX_BUFFERHEADERTYPE *) event_info.event_param1; 6216 6217 index = event_info.event_param2; 6218 6219 // compensate decrement in async_process_event_ebd() 6220 m_port_ip.num_pending_buffers++; 6221 6222 retval = async_process_event_ebd(p_buffer_hdr, index); 6223 break; 6224 } 6225 6226 case OMX_SWVDEC_EVENT_EBD: 6227 { 6228 p_buffer_hdr = (OMX_BUFFERHEADERTYPE *) event_info.event_param1; 6229 6230 index = event_info.event_param2; 6231 6232 retval = async_process_event_ebd(p_buffer_hdr, index); 6233 break; 6234 } 6235 6236 default: 6237 { 6238 assert(0); 6239 break; 6240 } 6241 6242 } 6243 } 6244 6245 assert(m_port_ip.num_pending_buffers == 0); 6246 6247 if ((retval == OMX_ErrorNone) && 6248 (m_status_flags & (1 << PENDING_PORT_FLUSH_IP))) 6249 { 6250 m_status_flags &= ~(1 << PENDING_PORT_FLUSH_IP); 6251 6252 async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, 6253 OMX_CommandFlush, 6254 OMX_CORE_PORT_INDEX_IP); 6255 } 6256 6257 m_port_ip.flush_inprogress = OMX_FALSE; 6258 6259 return retval; 6260 } 6261 6262 /** 6263 * @brief Process output port flush event. 6264 * 6265 * @retval OMX_ERRORTYPE 6266 */ 6267 OMX_ERRORTYPE omx_swvdec::async_process_event_flush_port_op() 6268 { 6269 OMX_ERRORTYPE retval = OMX_ErrorNone; 6270 6271 OMX_SWVDEC_EVENT_INFO event_info; 6272 6273 OMX_BUFFERHEADERTYPE *p_buffer_hdr; 6274 6275 unsigned int index; 6276 6277 while (m_queue_port_op.pop(&event_info)) 6278 { 6279 switch (event_info.event_id) 6280 { 6281 6282 case OMX_SWVDEC_EVENT_FTB: 6283 { 6284 p_buffer_hdr = (OMX_BUFFERHEADERTYPE *) event_info.event_param1; 6285 6286 index = event_info.event_param2; 6287 6288 // compensate decrement in async_process_event_fbd() 6289 m_port_op.num_pending_buffers++; 6290 6291 retval = async_process_event_fbd(p_buffer_hdr, index); 6292 break; 6293 } 6294 6295 case OMX_SWVDEC_EVENT_FBD: 6296 { 6297 p_buffer_hdr = (OMX_BUFFERHEADERTYPE *) event_info.event_param1; 6298 6299 index = event_info.event_param2; 6300 6301 retval = async_process_event_fbd(p_buffer_hdr, index); 6302 break; 6303 } 6304 6305 default: 6306 { 6307 assert(0); 6308 break; 6309 } 6310 6311 } 6312 } 6313 6314 assert(m_port_op.num_pending_buffers == 0); 6315 6316 if ((retval == OMX_ErrorNone) && 6317 (m_status_flags & (1 << PENDING_PORT_FLUSH_OP))) 6318 { 6319 m_status_flags &= ~(1 << PENDING_PORT_FLUSH_OP); 6320 6321 async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, 6322 OMX_CommandFlush, 6323 OMX_CORE_PORT_INDEX_OP); 6324 } 6325 6326 if ((retval == OMX_ErrorNone) && 6327 (m_status_flags & (1 << PENDING_STATE_EXECUTING_TO_IDLE))) 6328 { 6329 m_status_flags &= ~(1 << PENDING_STATE_EXECUTING_TO_IDLE); 6330 6331 async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, 6332 OMX_CommandStateSet, 6333 OMX_StateIdle); 6334 } 6335 6336 if (m_port_reconfig_inprogress == false) 6337 { 6338 OMX_SWVDEC_LOG_LOW("flushing %zu elements in timestamp queue", 6339 m_queue_timestamp.size()); 6340 6341 while (m_queue_timestamp.empty() == false) 6342 { 6343 m_queue_timestamp.pop(); 6344 } 6345 } 6346 6347 m_port_op.flush_inprogress = OMX_FALSE; 6348 6349 return retval; 6350 } 6351 6352 /** 6353 * @brief Process port reconfiguration event. 6354 * 6355 * @retval OMX_ERRORTYPE 6356 */ 6357 OMX_ERRORTYPE omx_swvdec::async_process_event_port_reconfig() 6358 { 6359 OMX_ERRORTYPE retval = OMX_ErrorNone; 6360 6361 if (m_port_reconfig_inprogress) 6362 { 6363 OMX_SWVDEC_LOG_ERROR("port reconfiguration already in progress"); 6364 6365 retval = OMX_ErrorIncorrectStateOperation; 6366 } 6367 else 6368 { 6369 m_port_reconfig_inprogress = true; 6370 6371 OMX_SWVDEC_LOG_CALLBACK("EventHandler(): " 6372 "OMX_EventPortSettingsChanged, port index %d", 6373 OMX_CORE_PORT_INDEX_OP); 6374 6375 m_callback.EventHandler(&m_cmp, 6376 m_app_data, 6377 OMX_EventPortSettingsChanged, 6378 OMX_CORE_PORT_INDEX_OP, 6379 0, 6380 NULL); 6381 } 6382 6383 return retval; 6384 } 6385 6386 /** 6387 * @brief Process dimensions updated event. 6388 * 6389 * @retval OMX_ERRORTYPE 6390 */ 6391 OMX_ERRORTYPE omx_swvdec::async_process_event_dimensions_updated() 6392 { 6393 OMX_ERRORTYPE retval = OMX_ErrorNone; 6394 6395 if (m_dimensions_update_inprogress) 6396 { 6397 OMX_SWVDEC_LOG_ERROR("dimensions update already in progress"); 6398 6399 retval = OMX_ErrorIncorrectStateOperation; 6400 } 6401 else 6402 { 6403 m_dimensions_update_inprogress = true; 6404 6405 OMX_SWVDEC_LOG_CALLBACK("EventHandler(): " 6406 "OMX_EventPortSettingsChanged, port index %d, " 6407 "OMX_IndexConfigCommonOutputCrop", 6408 OMX_CORE_PORT_INDEX_OP); 6409 6410 m_callback.EventHandler(&m_cmp, 6411 m_app_data, 6412 OMX_EventPortSettingsChanged, 6413 OMX_CORE_PORT_INDEX_OP, 6414 OMX_IndexConfigCommonOutputCrop, 6415 NULL); 6416 } 6417 6418 return retval; 6419 } 6420