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