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