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