| /** |
| * @copyright |
| * |
| * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * * Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * * Neither the name of The Linux Foundation nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, |
| * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE DISCLAIMED. |
| * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY |
| * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
| * DAMAGE. |
| * |
| * @file |
| * |
| * omx_swvdec.cpp |
| * |
| * @brief |
| * |
| * OMX software video decoder component source. |
| */ |
| |
| #include <assert.h> |
| #include <fcntl.h> |
| #include <sys/mman.h> |
| |
| #include <cutils/properties.h> |
| |
| #include <media/hardware/HardwareAPI.h> |
| #include <gralloc_priv.h> |
| |
| #include "OMX_QCOMExtns.h" |
| |
| #include "omx_swvdec.h" |
| |
| #include "swvdec_api.h" |
| |
| static unsigned int split_buffer_mpeg4(unsigned int *offset_array, |
| OMX_BUFFERHEADERTYPE *p_buffer_hdr); |
| |
| /** |
| * ---------------- |
| * PUBLIC FUNCTIONS |
| * ---------------- |
| */ |
| |
| /** |
| * @brief Create & return component class instance. |
| * |
| * @retval Pointer to new component class instance. |
| */ |
| void *get_omx_component_factory_fn(void) |
| { |
| return new omx_swvdec; |
| } |
| |
| /** |
| * @brief Component constructor. |
| */ |
| omx_swvdec::omx_swvdec(): |
| m_state(OMX_StateInvalid), |
| m_status_flags(0), |
| m_swvdec_codec(SWVDEC_CODEC_INVALID), |
| m_swvdec_handle(NULL), |
| m_swvdec_created(false), |
| m_omx_video_codingtype(OMX_VIDEO_CodingUnused), |
| m_omx_color_formattype(OMX_COLOR_FormatUnused), |
| m_sync_frame_decoding_mode(false), |
| m_android_native_buffers(false), |
| m_meta_buffer_mode_disabled(false), |
| m_meta_buffer_mode(false), |
| m_adaptive_playback_mode(false), |
| m_arbitrary_bytes_mode(false), |
| m_port_reconfig_inprogress(false), |
| m_dimensions_update_inprogress(false), |
| m_buffer_array_ip(NULL), |
| m_buffer_array_op(NULL), |
| m_meta_buffer_array(NULL) |
| { |
| // memset all member variables that are composite structures |
| memset(&m_cmp, 0, sizeof(m_cmp)); // part of base class |
| memset(&m_cmp_name[0], 0, sizeof(m_cmp_name)); |
| memset(&m_role_name[0], 0, sizeof(m_role_name)); |
| memset(&m_frame_dimensions, 0, sizeof(m_frame_dimensions)); |
| memset(&m_frame_attributes, 0, sizeof(m_frame_attributes)); |
| memset(&m_frame_dimensions_max, 0, sizeof(m_frame_dimensions_max)); |
| memset(&m_async_thread, 0, sizeof(m_async_thread)); |
| memset(&m_port_ip, 0, sizeof(m_port_ip)); |
| memset(&m_port_op, 0, sizeof(m_port_op)); |
| memset(&m_callback, 0, sizeof(m_callback)); |
| memset(&m_app_data, 0, sizeof(m_app_data)); |
| memset(&m_prio_mgmt, 0, sizeof(m_prio_mgmt)); |
| memset(&m_sem_cmd, 0, sizeof(m_sem_cmd)); |
| memset(&m_meta_buffer_array_mutex, 0, sizeof(m_meta_buffer_array_mutex)); |
| |
| // null-terminate component name & role name strings |
| m_cmp_name[0] = '\0'; |
| m_role_name[0] = '\0'; |
| |
| // ports are enabled & unpopulated by default |
| m_port_ip.enabled = OMX_TRUE; |
| m_port_op.enabled = OMX_TRUE; |
| m_port_ip.unpopulated = OMX_TRUE; |
| m_port_op.unpopulated = OMX_TRUE; |
| } |
| |
| /** |
| * @brief Component destructor. |
| */ |
| omx_swvdec::~omx_swvdec() |
| { |
| } |
| |
| /** |
| * @brief Initialize component. |
| * |
| * @param[in] cmp_name: Component name string. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::component_init(OMX_STRING cmp_name) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| OMX_SWVDEC_LOG_API("'%s', version date: %s", |
| cmp_name, |
| OMX_SWVDEC_VERSION_DATE); |
| |
| omx_swvdec_log_init(); |
| |
| { |
| char property_value[PROPERTY_VALUE_MAX] = {0}; |
| |
| if (property_get("vendor.vidc.dec.meta_buffer.disable", |
| property_value, |
| NULL)) |
| { |
| m_meta_buffer_mode_disabled = (bool) atoi(property_value); |
| |
| OMX_SWVDEC_LOG_LOW("vendor.vidc.dec.meta_buffer.disable: %d", |
| m_meta_buffer_mode_disabled ? 1 : 0); |
| } |
| } |
| |
| if (m_state != OMX_StateInvalid) |
| { |
| OMX_SWVDEC_LOG_ERROR("disallowed in state %s", |
| OMX_STATETYPE_STRING(m_state)); |
| |
| retval = OMX_ErrorIncorrectStateOperation; |
| goto component_init_exit; |
| } |
| |
| if (!strncmp(cmp_name, |
| "OMX.qti.video.decoder.mpeg4sw", |
| OMX_MAX_STRINGNAME_SIZE)) |
| { |
| OMX_SWVDEC_LOG_LOW("'video_decoder.mpeg4'"); |
| |
| strlcpy(m_cmp_name, cmp_name, OMX_MAX_STRINGNAME_SIZE); |
| strlcpy(m_role_name, "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE); |
| |
| m_swvdec_codec = SWVDEC_CODEC_MPEG4; |
| m_omx_video_codingtype = OMX_VIDEO_CodingMPEG4; |
| } |
| else if (!strncmp(cmp_name, |
| "OMX.qti.video.decoder.h263sw", |
| OMX_MAX_STRINGNAME_SIZE)) |
| { |
| OMX_SWVDEC_LOG_LOW("video_decoder.h263"); |
| |
| strlcpy(m_cmp_name, cmp_name, OMX_MAX_STRINGNAME_SIZE); |
| strlcpy(m_role_name, "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE); |
| |
| m_swvdec_codec = SWVDEC_CODEC_H263; |
| m_omx_video_codingtype = OMX_VIDEO_CodingH263; |
| } |
| else if (((!strncmp(cmp_name, |
| "OMX.qti.video.decoder.divxsw", |
| OMX_MAX_STRINGNAME_SIZE))) || |
| ((!strncmp(cmp_name, |
| "OMX.qti.video.decoder.divx4sw", |
| OMX_MAX_STRINGNAME_SIZE)))) |
| { |
| OMX_SWVDEC_LOG_LOW("video_decoder.divx"); |
| |
| strlcpy(m_cmp_name, cmp_name, OMX_MAX_STRINGNAME_SIZE); |
| #ifndef _ANDROID_O_MR1_DIVX_CHANGES |
| strlcpy(m_role_name, "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE); |
| #else |
| if(!strncmp(cmp_name,"OMX.qti.video.decoder.divx4sw", OMX_MAX_STRINGNAME_SIZE)) |
| strlcpy(m_role_name, "video_decoder.divx4", OMX_MAX_STRINGNAME_SIZE); |
| else |
| strlcpy(m_role_name, "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE); |
| #endif |
| |
| m_swvdec_codec = SWVDEC_CODEC_MPEG4; |
| m_omx_video_codingtype = ((OMX_VIDEO_CODINGTYPE) QOMX_VIDEO_CodingDivx); |
| } |
| else if (((!strncmp(cmp_name, |
| "OMX.qti.video.decoder.vc1sw", |
| OMX_MAX_STRINGNAME_SIZE)))|| |
| ((!strncmp(cmp_name, |
| "OMX.qti.video.decoder.wmvsw", |
| OMX_MAX_STRINGNAME_SIZE)))) |
| { |
| char property_value[PROPERTY_VALUE_MAX] = {0}; |
| if(property_get("vendor.media.sm6150.version",property_value,0) && |
| (atoi(property_value) == 1)) |
| { |
| OMX_SWVDEC_LOG_ERROR("VC1 decoder not supported on this target"); |
| retval = OMX_ErrorInvalidComponentName; |
| goto component_init_exit; |
| } |
| |
| OMX_SWVDEC_LOG_LOW("video_decoder.vc1"); |
| |
| strlcpy(m_cmp_name, cmp_name, OMX_MAX_STRINGNAME_SIZE); |
| strlcpy(m_role_name, "video_decoder.vc1", OMX_MAX_STRINGNAME_SIZE); |
| |
| m_swvdec_codec = SWVDEC_CODEC_VC1; |
| m_omx_video_codingtype = OMX_VIDEO_CodingWMV; |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("'%s': invalid component name", cmp_name); |
| |
| retval = OMX_ErrorInvalidComponentName; |
| goto component_init_exit; |
| } |
| |
| { |
| SWVDEC_CALLBACK callback; |
| |
| SWVDEC_STATUS retval_swvdec; |
| |
| callback.pfn_empty_buffer_done = swvdec_empty_buffer_done_callback; |
| callback.pfn_fill_buffer_done = swvdec_fill_buffer_done_callback; |
| callback.pfn_event_notification = swvdec_event_handler_callback; |
| callback.p_client = this; |
| |
| if ((retval_swvdec = swvdec_init(&m_swvdec_handle, |
| m_swvdec_codec, |
| &callback)) != |
| SWVDEC_STATUS_SUCCESS) |
| { |
| retval = retval_swvdec2omx(retval_swvdec); |
| goto component_init_exit; |
| } |
| |
| if ((retval_swvdec = swvdec_check_inst_load(m_swvdec_handle)) != |
| SWVDEC_STATUS_SUCCESS) |
| { |
| retval = retval_swvdec2omx(retval_swvdec); |
| goto component_init_exit; |
| } |
| m_swvdec_created = true; |
| |
| if ((retval = set_frame_dimensions(DEFAULT_FRAME_WIDTH, |
| DEFAULT_FRAME_HEIGHT)) != |
| OMX_ErrorNone) |
| { |
| goto component_init_exit; |
| } |
| |
| m_omx_color_formattype = |
| ((OMX_COLOR_FORMATTYPE) |
| OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m); |
| |
| if ((retval = set_frame_attributes(m_omx_color_formattype)) != |
| OMX_ErrorNone) |
| { |
| goto component_init_exit; |
| } |
| } |
| |
| if ((retval = get_buffer_requirements_swvdec(OMX_CORE_PORT_INDEX_IP)) != |
| OMX_ErrorNone) |
| { |
| goto component_init_exit; |
| } |
| |
| if ((retval = get_buffer_requirements_swvdec(OMX_CORE_PORT_INDEX_OP)) != |
| OMX_ErrorNone) |
| { |
| goto component_init_exit; |
| } |
| |
| if ((retval = async_thread_create()) != OMX_ErrorNone) |
| { |
| goto component_init_exit; |
| } |
| |
| if (sem_init(&m_sem_cmd, 0, 0)) |
| { |
| OMX_SWVDEC_LOG_ERROR("failed to create command processing semaphore"); |
| |
| retval = OMX_ErrorInsufficientResources; |
| goto component_init_exit; |
| } |
| |
| if (pthread_mutex_init(&m_meta_buffer_array_mutex, NULL)) |
| { |
| OMX_SWVDEC_LOG_ERROR("failed to create meta buffer info array mutex"); |
| |
| retval = OMX_ErrorInsufficientResources; |
| goto component_init_exit; |
| } |
| |
| OMX_SWVDEC_LOG_HIGH("OMX_StateInvalid -> OMX_StateLoaded"); |
| |
| m_state = OMX_StateLoaded; |
| |
| component_init_exit: |
| return retval; |
| } |
| |
| /** |
| * @brief De-initialize component. |
| * |
| * @param[in] cmp_handle: Component handle. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::component_deinit(OMX_HANDLETYPE cmp_handle) |
| { |
| OMX_SWVDEC_LOG_API(""); |
| |
| if (cmp_handle == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); |
| } |
| |
| pthread_mutex_destroy(&m_meta_buffer_array_mutex); |
| |
| sem_destroy(&m_sem_cmd); |
| |
| async_thread_destroy(); |
| |
| if (m_swvdec_created) |
| { |
| swvdec_deinit(m_swvdec_handle); |
| |
| m_swvdec_handle = NULL; |
| } |
| |
| OMX_SWVDEC_LOG_HIGH("all done, goodbye!"); |
| |
| return OMX_ErrorNone; |
| } |
| |
| /** |
| * @brief Get component version. |
| * |
| * @param[in] cmp_handle: Component handle. |
| * @param[in] cmp_name: Component name string. |
| * @param[in,out] p_cmp_version: Pointer to component version variable. |
| * @param[in,out] p_spec_version: Pointer to OMX spec version variable. |
| * @param[in,out] p_cmp_UUID: Pointer to component UUID variable. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::get_component_version(OMX_HANDLETYPE cmp_handle, |
| OMX_STRING cmp_name, |
| OMX_VERSIONTYPE *p_cmp_version, |
| OMX_VERSIONTYPE *p_spec_version, |
| OMX_UUIDTYPE *p_cmp_UUID) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| (void) p_cmp_UUID; |
| |
| OMX_SWVDEC_LOG_API(""); |
| |
| if (m_state == OMX_StateInvalid) |
| { |
| OMX_SWVDEC_LOG_ERROR("in invalid state"); |
| |
| retval = OMX_ErrorInvalidState; |
| } |
| else if (cmp_handle == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); |
| |
| retval = OMX_ErrorInvalidComponent; |
| } |
| else if (strncmp(cmp_name, m_cmp_name, sizeof(m_cmp_name))) |
| { |
| OMX_SWVDEC_LOG_ERROR("'%s': invalid component name", cmp_name); |
| |
| retval = OMX_ErrorInvalidComponentName; |
| } |
| else if (p_cmp_version == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_cmp_version = NULL"); |
| |
| retval = OMX_ErrorBadParameter; |
| } |
| else if (p_spec_version == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_spec_version = NULL"); |
| |
| retval = OMX_ErrorBadParameter; |
| } |
| else |
| { |
| p_spec_version->nVersion = OMX_SPEC_VERSION; |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Send command to component. |
| * |
| * @param[in] cmp_handle: Component handle. |
| * @param[in] cmd: Command. |
| * @param[in] param: Command parameter. |
| * @param[in] p_cmd_data: Pointer to command data. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::send_command(OMX_HANDLETYPE cmp_handle, |
| OMX_COMMANDTYPE cmd, |
| OMX_U32 param, |
| OMX_PTR p_cmd_data) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| (void) p_cmd_data; // prevent warning for unused function argument |
| |
| if (m_state == OMX_StateInvalid) |
| { |
| OMX_SWVDEC_LOG_ERROR("in invalid state"); |
| |
| retval = OMX_ErrorInvalidState; |
| goto send_command_exit; |
| } |
| else if (cmp_handle == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); |
| |
| retval = OMX_ErrorInvalidComponent; |
| goto send_command_exit; |
| } |
| |
| switch (cmd) |
| { |
| |
| case OMX_CommandStateSet: |
| { |
| OMX_SWVDEC_LOG_API("%s, %s", |
| OMX_COMMANDTYPE_STRING(cmd), |
| OMX_STATETYPE_STRING((OMX_STATETYPE) param)); |
| break; |
| } |
| |
| case OMX_CommandFlush: |
| case OMX_CommandPortDisable: |
| case OMX_CommandPortEnable: |
| { |
| OMX_SWVDEC_LOG_API("%s, port index %d", |
| OMX_COMMANDTYPE_STRING(cmd), |
| param); |
| |
| if ((param != OMX_CORE_PORT_INDEX_IP) && |
| (param != OMX_CORE_PORT_INDEX_OP) && |
| (param != OMX_ALL)) |
| { |
| OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", param); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| |
| break; |
| } |
| |
| default: |
| { |
| OMX_SWVDEC_LOG_API("cmd %d, param %d", cmd, param); |
| |
| OMX_SWVDEC_LOG_ERROR("cmd '%d' invalid", cmd); |
| |
| retval = OMX_ErrorBadParameter; |
| break; |
| } |
| |
| } // switch (cmd) |
| |
| if (retval == OMX_ErrorNone) |
| { |
| if (cmp_handle == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); |
| |
| retval = OMX_ErrorInvalidComponent; |
| } |
| else if (m_state == OMX_StateInvalid) |
| { |
| OMX_SWVDEC_LOG_ERROR("in invalid state"); |
| |
| retval = OMX_ErrorInvalidState; |
| } |
| } |
| |
| if (retval != OMX_ErrorNone) |
| { |
| async_post_event(OMX_SWVDEC_EVENT_ERROR, retval, 0); |
| } |
| else |
| { |
| async_post_event(OMX_SWVDEC_EVENT_CMD, cmd, param); |
| |
| sem_wait(&m_sem_cmd); |
| } |
| |
| send_command_exit: |
| return retval; |
| } |
| |
| /** |
| * @brief Get a parameter from component. |
| * |
| * @param[in] cmp_handle: Component handle. |
| * @param[in] param_index: Parameter index. |
| * @param[in,out] p_param_data: Pointer to parameter data. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::get_parameter(OMX_HANDLETYPE cmp_handle, |
| OMX_INDEXTYPE param_index, |
| OMX_PTR p_param_data) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| if (m_state == OMX_StateInvalid) |
| { |
| OMX_SWVDEC_LOG_ERROR("in invalid state"); |
| |
| retval = OMX_ErrorInvalidState; |
| } |
| else if (cmp_handle == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); |
| |
| retval = OMX_ErrorInvalidComponent; |
| } |
| else if (p_param_data == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_param_data = NULL"); |
| |
| retval = OMX_ErrorBadParameter; |
| } |
| |
| if (retval != OMX_ErrorNone) |
| { |
| goto get_parameter_exit; |
| } |
| |
| switch (param_index) |
| { |
| |
| case OMX_IndexParamAudioInit: |
| { |
| OMX_PORT_PARAM_TYPE *p_port_param = |
| (OMX_PORT_PARAM_TYPE *) p_param_data; |
| |
| p_port_param->nPorts = 0; |
| p_port_param->nStartPortNumber = 0; |
| |
| OMX_SWVDEC_LOG_API("OMX_IndexParamAudioInit: " |
| "%d port(s), start port index %d", |
| p_port_param->nPorts, |
| p_port_param->nStartPortNumber); |
| break; |
| } |
| |
| case OMX_IndexParamImageInit: |
| { |
| OMX_PORT_PARAM_TYPE *p_port_param = |
| (OMX_PORT_PARAM_TYPE *) p_param_data; |
| |
| p_port_param->nPorts = 0; |
| p_port_param->nStartPortNumber = 0; |
| |
| OMX_SWVDEC_LOG_API("OMX_IndexParamImageInit: " |
| "%d port(s), start port index %d", |
| p_port_param->nPorts, |
| p_port_param->nStartPortNumber); |
| break; |
| } |
| |
| case OMX_IndexParamVideoInit: |
| { |
| OMX_PORT_PARAM_TYPE *p_port_param = |
| (OMX_PORT_PARAM_TYPE *) p_param_data; |
| |
| p_port_param->nPorts = 2; |
| p_port_param->nStartPortNumber = 0; |
| |
| OMX_SWVDEC_LOG_API("OMX_IndexParamVideoInit: " |
| "%d port(s), start port index %d", |
| p_port_param->nPorts, |
| p_port_param->nStartPortNumber); |
| break; |
| } |
| |
| case OMX_IndexParamOtherInit: |
| { |
| OMX_PORT_PARAM_TYPE *p_port_param = |
| (OMX_PORT_PARAM_TYPE *) p_param_data; |
| |
| p_port_param->nPorts = 0; |
| p_port_param->nStartPortNumber = 0; |
| |
| OMX_SWVDEC_LOG_API("OMX_IndexParamOtherInit: " |
| "%d port(s), start port index %d", |
| p_port_param->nPorts, |
| p_port_param->nStartPortNumber); |
| break; |
| } |
| |
| case OMX_IndexConfigPriorityMgmt: |
| { |
| OMX_PRIORITYMGMTTYPE *p_prio_mgmt = |
| (OMX_PRIORITYMGMTTYPE *) p_param_data; |
| |
| OMX_SWVDEC_LOG_API("OMX_IndexConfigPriorityMgmt"); |
| |
| memcpy(p_prio_mgmt, &m_prio_mgmt, sizeof(OMX_PRIORITYMGMTTYPE)); |
| break; |
| } |
| |
| case OMX_IndexParamStandardComponentRole: |
| { |
| OMX_PARAM_COMPONENTROLETYPE *p_cmp_role = |
| (OMX_PARAM_COMPONENTROLETYPE *) p_param_data; |
| |
| strlcpy((char *) p_cmp_role->cRole, |
| m_role_name, |
| OMX_MAX_STRINGNAME_SIZE); |
| |
| OMX_SWVDEC_LOG_API("OMX_IndexParamStandardComponentRole: %s", |
| p_cmp_role->cRole); |
| break; |
| } |
| |
| case OMX_IndexParamPortDefinition: |
| { |
| OMX_PARAM_PORTDEFINITIONTYPE *p_port_def = |
| (OMX_PARAM_PORTDEFINITIONTYPE *) p_param_data; |
| |
| OMX_SWVDEC_LOG_API("OMX_IndexParamPortDefinition, port index %d", |
| p_port_def->nPortIndex); |
| |
| retval = get_port_definition(p_port_def); |
| break; |
| } |
| |
| case OMX_IndexParamCompBufferSupplier: |
| { |
| OMX_PARAM_BUFFERSUPPLIERTYPE *p_buffer_supplier = |
| (OMX_PARAM_BUFFERSUPPLIERTYPE *) p_param_data; |
| |
| OMX_SWVDEC_LOG_API("OMX_IndexParamCompBufferSupplier, port index %d", |
| p_buffer_supplier->nPortIndex); |
| |
| if ((p_buffer_supplier->nPortIndex == OMX_CORE_PORT_INDEX_IP) || |
| (p_buffer_supplier->nPortIndex == OMX_CORE_PORT_INDEX_OP)) |
| { |
| p_buffer_supplier->eBufferSupplier = OMX_BufferSupplyUnspecified; |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", |
| p_buffer_supplier->nPortIndex); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| |
| break; |
| } |
| |
| case OMX_IndexParamVideoPortFormat: |
| { |
| OMX_VIDEO_PARAM_PORTFORMATTYPE *p_port_format = |
| (OMX_VIDEO_PARAM_PORTFORMATTYPE *) p_param_data; |
| |
| OMX_SWVDEC_LOG_API("OMX_IndexParamVideoPortFormat, " |
| "port index %d, index %d", |
| p_port_format->nPortIndex, |
| p_port_format->nIndex); |
| |
| retval = get_video_port_format(p_port_format); |
| break; |
| } |
| |
| case OMX_IndexParamVideoMpeg2: |
| { |
| OMX_SWVDEC_LOG_ERROR("OMX_IndexParamVideoMpeg2: unsupported"); |
| |
| retval = OMX_ErrorUnsupportedIndex; |
| break; |
| } |
| |
| case OMX_IndexParamVideoMpeg4: |
| { |
| OMX_SWVDEC_LOG_API("OMX_IndexParamVideoMpeg4: unsupported"); |
| |
| retval = OMX_ErrorUnsupportedIndex; |
| break; |
| } |
| |
| case OMX_IndexParamVideoAvc: |
| { |
| OMX_SWVDEC_LOG_API("OMX_IndexParamVideoAvc: unsupported"); |
| |
| retval = OMX_ErrorUnsupportedIndex; |
| break; |
| } |
| |
| case OMX_IndexParamVideoH263: |
| { |
| OMX_SWVDEC_LOG_API("OMX_IndexParamVideoH263: unsupported"); |
| |
| retval = OMX_ErrorUnsupportedIndex; |
| break; |
| } |
| |
| case OMX_IndexParamVideoProfileLevelQuerySupported: |
| { |
| OMX_VIDEO_PARAM_PROFILELEVELTYPE *p_profilelevel = |
| (OMX_VIDEO_PARAM_PROFILELEVELTYPE *) p_param_data; |
| |
| OMX_SWVDEC_LOG_API("OMX_IndexParamVideoProfileLevelQuerySupported, " |
| "port index %d, profile index %d", |
| p_profilelevel->nPortIndex, |
| p_profilelevel->nProfileIndex); |
| |
| retval = get_supported_profilelevel(p_profilelevel); |
| break; |
| } |
| |
| default: |
| { |
| /** |
| * Vendor-specific extension indices checked here since they are not |
| * part of the OMX_INDEXTYPE enumerated type. |
| */ |
| |
| switch ((OMX_QCOM_EXTN_INDEXTYPE) param_index) |
| { |
| |
| case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage: |
| { |
| GetAndroidNativeBufferUsageParams *p_buffer_usage = |
| (GetAndroidNativeBufferUsageParams *) p_param_data; |
| |
| OMX_SWVDEC_LOG_API( |
| "OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage, " |
| "port index %d", p_buffer_usage->nPortIndex); |
| |
| if (p_buffer_usage->nPortIndex == OMX_CORE_PORT_INDEX_OP) |
| { |
| p_buffer_usage->nUsage = (static_cast<uint32_t>(GRALLOC_USAGE_PRIVATE_IOMMU_HEAP | |
| GRALLOC_USAGE_SW_READ_OFTEN | |
| GRALLOC_USAGE_SW_WRITE_OFTEN)); |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", |
| p_buffer_usage->nPortIndex); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| break; |
| } |
| |
| case OMX_QcomIndexFlexibleYUVDescription: |
| { |
| OMX_SWVDEC_LOG_API("OMX_QcomIndexFlexibleYUVDescription"); |
| |
| retval = describe_color_format((DescribeColorFormatParams *) |
| p_param_data); |
| break; |
| } |
| |
| default: |
| { |
| OMX_SWVDEC_LOG_ERROR("param index '0x%08x' invalid", |
| (OMX_QCOM_EXTN_INDEXTYPE) param_index); |
| |
| retval = OMX_ErrorBadParameter; |
| break; |
| } |
| |
| } // switch ((OMX_QCOM_EXTN_INDEXTYPE) param_index) |
| |
| } // default case |
| |
| } // switch (param_index) |
| |
| get_parameter_exit: |
| return retval; |
| } |
| |
| /** |
| * @brief Set a parameter to component. |
| * |
| * @param[in] cmp_handle: Component handle. |
| * @param[in] param_index: Parameter index. |
| * @param[in] p_param_data: Pointer to parameter data. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::set_parameter(OMX_HANDLETYPE cmp_handle, |
| OMX_INDEXTYPE param_index, |
| OMX_PTR p_param_data) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| if (m_state == OMX_StateInvalid) |
| { |
| OMX_SWVDEC_LOG_ERROR("in invalid state"); |
| |
| retval = OMX_ErrorInvalidState; |
| } |
| else if (cmp_handle == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); |
| |
| retval = OMX_ErrorInvalidComponent; |
| } |
| else if (p_param_data == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_param_data = NULL"); |
| |
| retval = OMX_ErrorBadParameter; |
| } |
| else if ((m_state != OMX_StateLoaded) && |
| (m_port_reconfig_inprogress == false)) |
| { |
| OMX_SWVDEC_LOG_ERROR("disallowed in state %s", |
| OMX_STATETYPE_STRING(m_state)); |
| |
| retval = OMX_ErrorIncorrectStateOperation; |
| } |
| |
| if (retval != OMX_ErrorNone) |
| { |
| goto set_parameter_exit; |
| } |
| |
| switch (param_index) |
| { |
| |
| case OMX_IndexParamPriorityMgmt: |
| { |
| OMX_PRIORITYMGMTTYPE *p_prio_mgmt = |
| (OMX_PRIORITYMGMTTYPE *) p_param_data; |
| |
| OMX_SWVDEC_LOG_API("OMX_IndexConfigPriorityMgmt: " |
| "group ID %d, group priority %d", |
| p_prio_mgmt->nGroupID, |
| p_prio_mgmt->nGroupPriority); |
| |
| if (m_state != OMX_StateLoaded) |
| { |
| OMX_SWVDEC_LOG_ERROR("'%d' state invalid; " |
| "should be in loaded state", |
| m_state); |
| |
| retval = OMX_ErrorIncorrectStateOperation; |
| } |
| else |
| { |
| memcpy(&m_prio_mgmt, p_prio_mgmt, sizeof(OMX_PRIORITYMGMTTYPE)); |
| } |
| |
| break; |
| } |
| |
| case OMX_IndexParamStandardComponentRole: |
| { |
| OMX_PARAM_COMPONENTROLETYPE *p_cmp_role = |
| (OMX_PARAM_COMPONENTROLETYPE *) p_param_data; |
| |
| OMX_SWVDEC_LOG_API("OMX_IndexParamStandardComponentRole '%s'", |
| p_cmp_role->cRole); |
| |
| if (m_state != OMX_StateLoaded) |
| { |
| OMX_SWVDEC_LOG_ERROR("'%d' state invalid; " |
| "should be in loaded state", |
| m_state); |
| |
| retval = OMX_ErrorIncorrectStateOperation; |
| } |
| else |
| { |
| if (strncmp((char *) p_cmp_role->cRole, |
| m_role_name, |
| OMX_MAX_STRINGNAME_SIZE)) |
| { |
| OMX_SWVDEC_LOG_ERROR("'%s': invalid component role name", |
| p_cmp_role->cRole); |
| |
| retval = OMX_ErrorBadParameter; |
| } |
| } |
| |
| break; |
| } |
| |
| case OMX_IndexParamPortDefinition: |
| { |
| OMX_PARAM_PORTDEFINITIONTYPE *p_port_def = |
| (OMX_PARAM_PORTDEFINITIONTYPE *) p_param_data; |
| |
| OMX_SWVDEC_LOG_API("OMX_IndexParamPortDefinition, port index %d", |
| p_port_def->nPortIndex); |
| |
| if ((m_state != OMX_StateLoaded) && |
| (((p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_IP) && |
| (m_port_ip.enabled == OMX_TRUE) && |
| (m_port_ip.populated == OMX_TRUE)) || |
| ((p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_OP) && |
| (m_port_op.enabled == OMX_TRUE) && |
| (m_port_op.populated == OMX_TRUE)))) |
| { |
| OMX_SWVDEC_LOG_ERROR("OMX_IndexParamPortDefinition " |
| "disallowed in state %s " |
| "while port index %d is enabled & populated", |
| OMX_STATETYPE_STRING(m_state), |
| p_port_def->nPortIndex); |
| |
| retval = OMX_ErrorIncorrectStateOperation; |
| } |
| else |
| { |
| retval = set_port_definition(p_port_def); |
| } |
| |
| break; |
| } |
| |
| case OMX_IndexParamCompBufferSupplier: |
| { |
| OMX_PARAM_BUFFERSUPPLIERTYPE *p_buffer_supplier = |
| (OMX_PARAM_BUFFERSUPPLIERTYPE *) p_param_data; |
| |
| OMX_SWVDEC_LOG_API("OMX_IndexParamCompBufferSupplier: " |
| "port index %d, buffer supplier %d", |
| p_buffer_supplier->nPortIndex, |
| (int) p_buffer_supplier->eBufferSupplier); |
| |
| if ((p_buffer_supplier->nPortIndex != OMX_CORE_PORT_INDEX_IP) && |
| (p_buffer_supplier->nPortIndex != OMX_CORE_PORT_INDEX_OP)) |
| { |
| OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", |
| p_buffer_supplier->nPortIndex); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| |
| break; |
| } |
| |
| case OMX_IndexParamVideoPortFormat: |
| { |
| OMX_VIDEO_PARAM_PORTFORMATTYPE *p_port_format = |
| (OMX_VIDEO_PARAM_PORTFORMATTYPE *) p_param_data; |
| |
| OMX_SWVDEC_LOG_API("OMX_IndexParamVideoPortFormat, port index %d", |
| p_port_format->nPortIndex); |
| |
| if ((m_state != OMX_StateLoaded) && |
| (((p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_IP) && |
| (m_port_ip.enabled == OMX_TRUE) && |
| (m_port_ip.populated == OMX_TRUE)) || |
| ((p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_OP) && |
| (m_port_op.enabled == OMX_TRUE) && |
| (m_port_op.populated == OMX_TRUE)))) |
| { |
| OMX_SWVDEC_LOG_ERROR("OMX_IndexParamVideoPortFormat " |
| "disallowed in state %s " |
| "while port index %d is enabled & populated", |
| OMX_STATETYPE_STRING(m_state), |
| p_port_format->nPortIndex); |
| |
| retval = OMX_ErrorIncorrectStateOperation; |
| } |
| else |
| { |
| retval = set_video_port_format(p_port_format); |
| } |
| |
| break; |
| } |
| |
| case OMX_IndexParamVideoMpeg2: |
| { |
| OMX_SWVDEC_LOG_ERROR("OMX_IndexParamVideoMpeg2 unsupported"); |
| |
| retval = OMX_ErrorUnsupportedIndex; |
| break; |
| } |
| |
| case OMX_IndexParamVideoMpeg4: |
| { |
| OMX_SWVDEC_LOG_API("OMX_IndexParamVideoMpeg4 unsupported"); |
| |
| retval = OMX_ErrorUnsupportedIndex; |
| break; |
| } |
| |
| case OMX_IndexParamVideoAvc: |
| { |
| OMX_SWVDEC_LOG_API("OMX_IndexParamVideoAvc unsupported"); |
| |
| retval = OMX_ErrorUnsupportedIndex; |
| break; |
| } |
| |
| case OMX_IndexParamVideoH263: |
| { |
| OMX_SWVDEC_LOG_API("OMX_IndexParamVideoH263 unsupported"); |
| |
| retval = OMX_ErrorUnsupportedIndex; |
| break; |
| } |
| |
| default: |
| { |
| /** |
| * Vendor-specific extension indices checked here since they are not |
| * part of the OMX_INDEXTYPE enumerated type. |
| */ |
| |
| switch ((OMX_QCOM_EXTN_INDEXTYPE) param_index) |
| { |
| |
| case OMX_QcomIndexPortDefn: |
| { |
| OMX_QCOM_PARAM_PORTDEFINITIONTYPE *p_port_def = |
| (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) p_param_data; |
| |
| OMX_SWVDEC_LOG_API("OMX_QcomIndexPortDefn, port index %d", |
| p_port_def->nPortIndex); |
| |
| if ((m_state != OMX_StateLoaded) && |
| (((p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_IP) && |
| (m_port_ip.enabled == OMX_TRUE) && |
| (m_port_ip.populated == OMX_TRUE)) || |
| ((p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_OP) && |
| (m_port_op.enabled == OMX_TRUE) && |
| (m_port_op.populated == OMX_TRUE)))) |
| { |
| OMX_SWVDEC_LOG_ERROR("OMX_QcomIndexPortDefn " |
| "disallowed in state %s " |
| "while port index %d " |
| "is enabled & populated", |
| OMX_STATETYPE_STRING(m_state), |
| p_port_def->nPortIndex); |
| |
| retval = OMX_ErrorIncorrectStateOperation; |
| } |
| else |
| { |
| retval = set_port_definition_qcom(p_port_def); |
| } |
| |
| break; |
| } |
| |
| case OMX_QcomIndexParamVideoDivx: |
| { |
| OMX_SWVDEC_LOG_API("OMX_QcomIndexParamVideoDivx"); |
| |
| break; |
| } |
| |
| case OMX_QcomIndexParamVideoSyncFrameDecodingMode: |
| { |
| OMX_SWVDEC_LOG_API("OMX_QcomIndexParamVideoSyncFrameDecodingMode"); |
| |
| m_sync_frame_decoding_mode = true; |
| |
| retval = set_thumbnail_mode_swvdec(); |
| break; |
| } |
| |
| case OMX_QcomIndexParamVideoDecoderPictureOrder: |
| { |
| QOMX_VIDEO_DECODER_PICTURE_ORDER *p_picture_order = |
| (QOMX_VIDEO_DECODER_PICTURE_ORDER *) p_param_data; |
| |
| switch (p_picture_order->eOutputPictureOrder) |
| { |
| |
| case QOMX_VIDEO_DISPLAY_ORDER: |
| { |
| OMX_SWVDEC_LOG_API( |
| "OMX_QcomIndexParamVideoDecoderPictureOrder, " |
| "QOMX_VIDEO_DISPLAY_ORDER"); |
| |
| break; |
| } |
| |
| case QOMX_VIDEO_DECODE_ORDER: |
| { |
| OMX_SWVDEC_LOG_API( |
| "OMX_QcomIndexParamVideoDecoderPictureOrder, " |
| "QOMX_VIDEO_DECODE_ORDER"); |
| |
| OMX_SWVDEC_LOG_ERROR( |
| "OMX_QcomIndexParamVideoDecoderPictureOrder, " |
| "QOMX_VIDEO_DECODE_ORDER; unsupported"); |
| |
| retval = OMX_ErrorUnsupportedSetting; |
| break; |
| } |
| |
| default: |
| { |
| OMX_SWVDEC_LOG_ERROR( |
| "OMX_QcomIndexParamVideoDecoderPictureOrder, %d; invalid", |
| p_picture_order->eOutputPictureOrder); |
| |
| retval = OMX_ErrorBadParameter; |
| break; |
| } |
| |
| } |
| |
| break; |
| } |
| |
| case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers: |
| { |
| OMX_SWVDEC_LOG_API( |
| "OMX_GoogleAndroidIndexEnableAndroidNativeBuffers, %s", |
| (((EnableAndroidNativeBuffersParams *) p_param_data)->enable ? |
| "enable" : |
| "disable")); |
| |
| m_android_native_buffers = |
| (bool) (((EnableAndroidNativeBuffersParams *) |
| p_param_data)->enable); |
| |
| break; |
| } |
| |
| case OMX_GoogleAndroidIndexUseAndroidNativeBuffer: |
| { |
| OMX_SWVDEC_LOG_ERROR("OMX_GoogleAndroidIndexUseAndroidNativeBuffer " |
| "unsupported"); |
| |
| retval = OMX_ErrorUnsupportedIndex; |
| break; |
| } |
| |
| case OMX_QcomIndexParamEnableTimeStampReorder: |
| { |
| OMX_SWVDEC_LOG_API( |
| "OMX_QcomIndexParamEnableTimeStampReorder, %s", |
| (((QOMX_INDEXTIMESTAMPREORDER *) p_param_data)->bEnable ? |
| "enable" : |
| "disable")); |
| |
| break; |
| } |
| |
| case OMX_QcomIndexParamVideoMetaBufferMode: |
| { |
| StoreMetaDataInBuffersParams *p_meta_data = |
| (StoreMetaDataInBuffersParams *) p_param_data; |
| |
| OMX_SWVDEC_LOG_API("OMX_QcomIndexParamVideoMetaBufferMode, " |
| "port index %d, %s", |
| p_meta_data->nPortIndex, |
| (p_meta_data->bStoreMetaData ? |
| "enable" : |
| "disable")); |
| if(m_swvdec_codec == SWVDEC_CODEC_VC1) |
| { |
| OMX_SWVDEC_LOG_HIGH("meta buffer mode is not supprted for vc1"); |
| return OMX_ErrorUnsupportedSetting; |
| } |
| if (p_meta_data->nPortIndex == OMX_CORE_PORT_INDEX_OP) |
| { |
| if (p_meta_data->bStoreMetaData && m_meta_buffer_mode_disabled) |
| { |
| OMX_SWVDEC_LOG_ERROR("meta buffer mode disabled " |
| "via ADB setprop: " |
| "'omx_swvdec.meta_buffer.disable'"); |
| |
| retval = OMX_ErrorBadParameter; |
| } |
| else |
| { |
| m_meta_buffer_mode = (bool) p_meta_data->bStoreMetaData; |
| } |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", |
| p_meta_data->nPortIndex); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| |
| break; |
| } |
| |
| case OMX_QcomIndexParamVideoAdaptivePlaybackMode: |
| { |
| PrepareForAdaptivePlaybackParams *p_adaptive_playback_params = |
| (PrepareForAdaptivePlaybackParams *) p_param_data; |
| |
| OMX_SWVDEC_LOG_API("OMX_QcomIndexParamVideoAdaptivePlaybackMode, " |
| "port index %d, %s, max dimensions: %d x %d", |
| p_adaptive_playback_params->nPortIndex, |
| (p_adaptive_playback_params->bEnable ? |
| "enable" : |
| "disable"), |
| p_adaptive_playback_params->nMaxFrameWidth, |
| p_adaptive_playback_params->nMaxFrameHeight); |
| |
| if (p_adaptive_playback_params->nPortIndex == |
| OMX_CORE_PORT_INDEX_OP) |
| { |
| if (p_adaptive_playback_params->bEnable) |
| { |
| m_adaptive_playback_mode = true; |
| |
| retval = |
| set_adaptive_playback( |
| p_adaptive_playback_params->nMaxFrameWidth, |
| p_adaptive_playback_params->nMaxFrameHeight); |
| } |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", |
| p_adaptive_playback_params->nPortIndex); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| |
| break; |
| } |
| |
| default: |
| { |
| OMX_SWVDEC_LOG_ERROR("param index '0x%08x' invalid", |
| (OMX_QCOM_EXTN_INDEXTYPE) param_index); |
| |
| retval = OMX_ErrorBadParameter; |
| break; |
| } |
| |
| } // switch ((OMX_QCOM_EXTN_INDEXTYPE) param_index) |
| |
| break; |
| } // default case |
| |
| } // switch (param_index) |
| |
| set_parameter_exit: |
| return retval; |
| } |
| |
| /** |
| * @brief Get a configuration from component. |
| * |
| * @param[in] cmp_handle: Component handle. |
| * @param[in] config_index: Configuration index. |
| * @param[in] p_config_data: Pointer to configuration data. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::get_config(OMX_HANDLETYPE cmp_handle, |
| OMX_INDEXTYPE config_index, |
| OMX_PTR p_config_data) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| if (m_state == OMX_StateInvalid) |
| { |
| OMX_SWVDEC_LOG_ERROR("in invalid state"); |
| |
| retval = OMX_ErrorInvalidState; |
| } |
| else if (cmp_handle == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); |
| |
| retval = OMX_ErrorInvalidComponent; |
| } |
| else if (p_config_data == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_config_data = NULL"); |
| |
| retval = OMX_ErrorBadParameter; |
| } |
| |
| if (retval != OMX_ErrorNone) |
| { |
| goto get_config_exit; |
| } |
| |
| switch (config_index) |
| { |
| |
| case OMX_IndexConfigCommonOutputCrop: |
| { |
| OMX_CONFIG_RECTTYPE *p_recttype = (OMX_CONFIG_RECTTYPE *) p_config_data; |
| |
| OMX_SWVDEC_LOG_API("OMX_IndexConfigCommonOutputCrop, port index %d", |
| p_recttype->nPortIndex); |
| |
| if (p_recttype->nPortIndex == OMX_CORE_PORT_INDEX_OP) |
| { |
| if (m_dimensions_update_inprogress) |
| { |
| retval = get_frame_dimensions_swvdec(); |
| |
| m_dimensions_update_inprogress = false; |
| } |
| |
| if (retval == OMX_ErrorNone) |
| { |
| p_recttype->nLeft = 0; |
| p_recttype->nTop = 0; |
| p_recttype->nWidth = m_frame_dimensions.width; |
| p_recttype->nHeight = m_frame_dimensions.height; |
| } |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", |
| p_recttype->nPortIndex); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| |
| break; |
| } |
| |
| default: |
| { |
| switch ((OMX_QCOM_EXTN_INDEXTYPE) config_index) |
| { |
| |
| case OMX_QcomIndexConfigInterlaced: |
| { |
| OMX_QCOM_CONFIG_INTERLACETYPE *p_config_interlacetype = |
| (OMX_QCOM_CONFIG_INTERLACETYPE *) p_config_data; |
| |
| OMX_SWVDEC_LOG_API("OMX_QcomIndexConfigInterlaced, " |
| "port index %d, index %d", |
| p_config_interlacetype->nPortIndex, |
| p_config_interlacetype->nIndex); |
| |
| if (p_config_interlacetype->nPortIndex == OMX_CORE_PORT_INDEX_OP) |
| { |
| if (p_config_interlacetype->nIndex == 0) |
| { |
| p_config_interlacetype->eInterlaceType = |
| OMX_QCOM_InterlaceFrameProgressive; |
| } |
| else if (p_config_interlacetype->nIndex == 1) |
| { |
| p_config_interlacetype->eInterlaceType = |
| OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst; |
| } |
| else if (p_config_interlacetype->nIndex == 2) |
| { |
| p_config_interlacetype->eInterlaceType = |
| OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst; |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("index '%d' unsupported; " |
| "no more interlaced types", |
| p_config_interlacetype->nIndex); |
| |
| retval = OMX_ErrorNoMore; |
| } |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", |
| p_config_interlacetype->nPortIndex); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| |
| break; |
| } |
| |
| case OMX_QcomIndexQueryNumberOfVideoDecInstance: |
| { |
| QOMX_VIDEO_QUERY_DECODER_INSTANCES *p_decoder_instances = |
| (QOMX_VIDEO_QUERY_DECODER_INSTANCES *) p_config_data; |
| |
| OMX_SWVDEC_LOG_API("OMX_QcomIndexQueryNumberOfVideoDecInstance"); |
| |
| p_decoder_instances->nNumOfInstances = OMX_SWVDEC_NUM_INSTANCES; |
| break; |
| } |
| |
| case OMX_QcomIndexConfigVideoFramePackingArrangement: |
| { |
| OMX_SWVDEC_LOG_API( |
| "OMX_QcomIndexConfigVideoFramePackingArrangement"); |
| |
| OMX_SWVDEC_LOG_ERROR( |
| "OMX_QcomIndexConfigVideoFramePackingArrangement unsupported"); |
| |
| retval = OMX_ErrorUnsupportedIndex; |
| break; |
| } |
| |
| default: |
| { |
| OMX_SWVDEC_LOG_ERROR("config index '0x%08x' invalid", config_index); |
| |
| retval = OMX_ErrorBadParameter; |
| break; |
| } |
| |
| } // switch ((OMX_QCOM_EXTN_INDEXTYPE) config_index) |
| |
| break; |
| } |
| |
| } // switch (config_index) |
| |
| get_config_exit: |
| return retval; |
| } |
| |
| /** |
| * @brief Set a configuration to component. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::set_config(OMX_HANDLETYPE cmp_handle, |
| OMX_INDEXTYPE config_index, |
| OMX_PTR p_config_data) |
| { |
| (void) cmp_handle; |
| (void) p_config_data; |
| |
| OMX_SWVDEC_LOG_API("config index 0x%08x", config_index); |
| |
| OMX_SWVDEC_LOG_ERROR("not implemented"); |
| |
| return OMX_ErrorNotImplemented; |
| } |
| |
| /** |
| * @brief Translate a vendor-specific extension string to a standard index type. |
| * |
| * @param[in] cmp_handle: Component handle. |
| * @param[in] param_name: Parameter name (extension string). |
| * @param[in,out] p_index_type: Pointer to extension string's index type. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::get_extension_index(OMX_HANDLETYPE cmp_handle, |
| OMX_STRING param_name, |
| OMX_INDEXTYPE *p_index_type) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| if (m_state == OMX_StateInvalid) |
| { |
| OMX_SWVDEC_LOG_ERROR("in invalid state"); |
| |
| retval = OMX_ErrorInvalidState; |
| } |
| else if (cmp_handle == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); |
| |
| retval = OMX_ErrorInvalidComponent; |
| } |
| else if (p_index_type == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_index_type = NULL"); |
| |
| retval = OMX_ErrorBadParameter; |
| } |
| |
| if (retval != OMX_ErrorNone) |
| { |
| goto get_extension_index_exit; |
| } |
| |
| OMX_SWVDEC_LOG_API("'%s'", param_name); |
| |
| if (!strncmp(param_name, |
| "OMX.QCOM.index.param.video.SyncFrameDecodingMode", |
| OMX_MAX_STRINGNAME_SIZE)) |
| { |
| *p_index_type = |
| (OMX_INDEXTYPE) OMX_QcomIndexParamVideoSyncFrameDecodingMode; |
| } |
| else if (!strncmp(param_name, |
| "OMX.QCOM.index.param.IndexExtraData", |
| OMX_MAX_STRINGNAME_SIZE)) |
| { |
| *p_index_type = (OMX_INDEXTYPE) OMX_QcomIndexParamIndexExtraDataType; |
| } |
| else if (!strncmp(param_name, |
| "OMX.google.android.index.enableAndroidNativeBuffers", |
| OMX_MAX_STRINGNAME_SIZE)) |
| { |
| *p_index_type = |
| (OMX_INDEXTYPE) OMX_GoogleAndroidIndexEnableAndroidNativeBuffers; |
| } |
| else if (!strncmp(param_name, |
| "OMX.google.android.index.useAndroidNativeBuffer2", |
| OMX_MAX_STRINGNAME_SIZE)) |
| { |
| *p_index_type = |
| (OMX_INDEXTYPE) OMX_GoogleAndroidIndexUseAndroidNativeBuffer2; |
| } |
| else if (!strncmp(param_name, |
| "OMX.google.android.index.useAndroidNativeBuffer", |
| OMX_MAX_STRINGNAME_SIZE)) |
| { |
| *p_index_type = |
| (OMX_INDEXTYPE) OMX_GoogleAndroidIndexUseAndroidNativeBuffer; |
| } |
| else if (!strncmp(param_name, |
| "OMX.google.android.index.getAndroidNativeBufferUsage", |
| OMX_MAX_STRINGNAME_SIZE)) |
| { |
| *p_index_type = |
| (OMX_INDEXTYPE) OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage; |
| } |
| else if (!strncmp(param_name, |
| "OMX.google.android.index.storeMetaDataInBuffers", |
| OMX_MAX_STRINGNAME_SIZE)) |
| { |
| *p_index_type = (OMX_INDEXTYPE) OMX_QcomIndexParamVideoMetaBufferMode; |
| } |
| else if (!strncmp(param_name, |
| "OMX.google.android.index.describeColorFormat", |
| OMX_MAX_STRINGNAME_SIZE)) |
| { |
| *p_index_type = (OMX_INDEXTYPE) OMX_QcomIndexFlexibleYUVDescription; |
| } |
| else if (!strncmp(param_name, |
| "OMX.google.android.index.prepareForAdaptivePlayback", |
| OMX_MAX_STRINGNAME_SIZE)) |
| { |
| *p_index_type = |
| (OMX_INDEXTYPE) OMX_QcomIndexParamVideoAdaptivePlaybackMode; |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("'%s': not implemented", param_name); |
| |
| retval = OMX_ErrorNotImplemented; |
| } |
| |
| get_extension_index_exit: |
| return retval; |
| } |
| |
| /** |
| * @brief Get component state. |
| * |
| * @param[in] cmp_handle: Component handle. |
| * @param[in,out] p_state: Pointer to state variable. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::get_state(OMX_HANDLETYPE cmp_handle, |
| OMX_STATETYPE *p_state) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| if (cmp_handle == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); |
| |
| retval = OMX_ErrorInvalidComponent; |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_API("%s", OMX_STATETYPE_STRING(m_state)); |
| |
| *p_state = m_state; |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Component tunnel request. |
| * |
| * @retval OMX_ErrorNotImplemented |
| */ |
| OMX_ERRORTYPE omx_swvdec::component_tunnel_request( |
| OMX_HANDLETYPE cmp_handle, |
| OMX_U32 port, |
| OMX_HANDLETYPE peer_component, |
| OMX_U32 peer_port, |
| OMX_TUNNELSETUPTYPE *p_tunnel_setup) |
| { |
| (void) cmp_handle; |
| (void) port; |
| (void) peer_component; |
| (void) peer_port; |
| (void) p_tunnel_setup; |
| |
| OMX_SWVDEC_LOG_API(""); |
| |
| OMX_SWVDEC_LOG_ERROR("not implemented"); |
| |
| return OMX_ErrorNotImplemented; |
| } |
| |
| /** |
| * @brief Use buffer. |
| * |
| * @param[in] cmp_handle: Component handle. |
| * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type |
| * structure. |
| * @param[in] port: Port index. |
| * @param[in] p_app_data: Pointer to IL client app data. |
| * @param[in] bytes: Size of buffer to be allocated in bytes. |
| * @param[in] p_buffer: Pointer to buffer to be used. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::use_buffer(OMX_HANDLETYPE cmp_handle, |
| OMX_BUFFERHEADERTYPE **pp_buffer_hdr, |
| OMX_U32 port, |
| OMX_PTR p_app_data, |
| OMX_U32 bytes, |
| OMX_U8 *p_buffer) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| if (m_state == OMX_StateInvalid) |
| { |
| OMX_SWVDEC_LOG_ERROR("in invalid state"); |
| |
| retval = OMX_ErrorInvalidState; |
| } |
| else if (cmp_handle == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); |
| |
| retval = OMX_ErrorInvalidComponent; |
| } |
| else if (pp_buffer_hdr == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("pp_buffer_hdr = NULL"); |
| |
| retval = OMX_ErrorBadParameter; |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_API("port index %d, %p", port, p_buffer); |
| |
| if (port == OMX_CORE_PORT_INDEX_OP) |
| { |
| retval = buffer_use_op(pp_buffer_hdr, p_app_data, bytes, p_buffer); |
| |
| if (retval == OMX_ErrorNone) |
| { |
| SWVDEC_STATUS retval_swvdec; |
| |
| if ((m_status_flags & (1 << PENDING_STATE_LOADED_TO_IDLE)) && |
| (m_port_ip.populated == OMX_TRUE) && |
| (m_port_op.populated == OMX_TRUE)) |
| { |
| if ((retval_swvdec = swvdec_start(m_swvdec_handle)) != |
| SWVDEC_STATUS_SUCCESS) |
| { |
| OMX_SWVDEC_LOG_ERROR("failed to start SwVdec"); |
| |
| retval = retval_swvdec2omx(retval_swvdec); |
| goto use_buffer_exit; |
| } |
| |
| m_status_flags &= ~(1 << PENDING_STATE_LOADED_TO_IDLE); |
| |
| async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, |
| OMX_CommandStateSet, |
| OMX_StateIdle); |
| } |
| |
| if ((m_status_flags & (1 << PENDING_PORT_ENABLE_OP)) && |
| (m_port_op.populated == OMX_TRUE)) |
| { |
| if (m_port_reconfig_inprogress) |
| { |
| if ((retval_swvdec = swvdec_start(m_swvdec_handle)) != |
| SWVDEC_STATUS_SUCCESS) |
| { |
| OMX_SWVDEC_LOG_ERROR("failed to start SwVdec"); |
| |
| retval = retval_swvdec2omx(retval_swvdec); |
| } |
| } |
| |
| m_status_flags &= ~(1 << PENDING_PORT_ENABLE_OP); |
| |
| async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, |
| OMX_CommandPortEnable, |
| OMX_CORE_PORT_INDEX_OP); |
| } |
| } |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", port); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| } |
| |
| use_buffer_exit: |
| return retval; |
| } |
| |
| /** |
| * @brief Allocate new buffer & associated header. |
| * |
| * @param[in] cmp_handle: Component handle. |
| * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type |
| * structure. |
| * @param[in] port: Port index. |
| * @param[in] p_app_data: Pointer to IL client app data. |
| * @param[in] bytes: Size of buffer to be allocated in bytes. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::allocate_buffer(OMX_HANDLETYPE cmp_handle, |
| OMX_BUFFERHEADERTYPE **pp_buffer_hdr, |
| OMX_U32 port, |
| OMX_PTR p_app_data, |
| OMX_U32 bytes) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| if (m_state == OMX_StateInvalid) |
| { |
| OMX_SWVDEC_LOG_ERROR("in invalid state"); |
| |
| retval = OMX_ErrorInvalidState; |
| } |
| else if (cmp_handle == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); |
| |
| retval = OMX_ErrorInvalidComponent; |
| } |
| else if (pp_buffer_hdr == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("pp_buffer_hdr = NULL"); |
| |
| retval = OMX_ErrorBadParameter; |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_API("port index %d, %d bytes", port, bytes); |
| |
| if (port == OMX_CORE_PORT_INDEX_IP) |
| { |
| retval = buffer_allocate_ip(pp_buffer_hdr, |
| p_app_data, |
| bytes); |
| } |
| else if (port == OMX_CORE_PORT_INDEX_OP) |
| { |
| if (m_meta_buffer_mode == true) |
| { |
| OMX_SWVDEC_LOG_ERROR("'meta buffer mode' enabled"); |
| |
| retval = OMX_ErrorBadParameter; |
| } |
| else if (m_android_native_buffers == true) |
| { |
| OMX_SWVDEC_LOG_ERROR("'android native buffers' enabled"); |
| |
| retval = OMX_ErrorBadParameter; |
| } |
| else |
| { |
| retval = buffer_allocate_op(pp_buffer_hdr, |
| p_app_data, |
| bytes); |
| } |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("port index %d invalid", port); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| |
| if (retval == OMX_ErrorNone) |
| { |
| SWVDEC_STATUS retval_swvdec; |
| |
| if ((m_status_flags & (1 << PENDING_STATE_LOADED_TO_IDLE)) && |
| (m_port_ip.populated == OMX_TRUE) && |
| (m_port_op.populated == OMX_TRUE)) |
| { |
| if ((retval_swvdec = swvdec_start(m_swvdec_handle)) != |
| SWVDEC_STATUS_SUCCESS) |
| { |
| OMX_SWVDEC_LOG_ERROR("failed to start SwVdec"); |
| |
| retval = retval_swvdec2omx(retval_swvdec); |
| goto allocate_buffer_exit; |
| } |
| |
| m_status_flags &= ~(1 << PENDING_STATE_LOADED_TO_IDLE); |
| |
| async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, |
| OMX_CommandStateSet, |
| OMX_StateIdle); |
| } |
| |
| if ((m_status_flags & (1 << PENDING_PORT_ENABLE_IP)) && |
| (m_port_ip.populated == OMX_TRUE)) |
| { |
| m_status_flags &= ~(1 << PENDING_PORT_ENABLE_IP); |
| |
| async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, |
| OMX_CommandPortEnable, |
| OMX_CORE_PORT_INDEX_IP); |
| } |
| |
| if ((m_status_flags & (1 << PENDING_PORT_ENABLE_OP)) && |
| (m_port_op.populated == OMX_TRUE)) |
| { |
| if (m_port_reconfig_inprogress) |
| { |
| if ((retval_swvdec = swvdec_start(m_swvdec_handle)) != |
| SWVDEC_STATUS_SUCCESS) |
| { |
| OMX_SWVDEC_LOG_ERROR("failed to start SwVdec"); |
| |
| retval = retval_swvdec2omx(retval_swvdec); |
| } |
| } |
| |
| m_status_flags &= ~(1 << PENDING_PORT_ENABLE_OP); |
| |
| async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, |
| OMX_CommandPortEnable, |
| OMX_CORE_PORT_INDEX_OP); |
| } |
| } |
| } |
| |
| allocate_buffer_exit: |
| return retval; |
| } |
| |
| /** |
| * @brief Release buffer & associated header. |
| * |
| * @param[in] cmp_handle: Component handle. |
| * @param[in] port: Port index. |
| * @param[in] p_buffer_hdr: Pointer to buffer's buffer header. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::free_buffer(OMX_HANDLETYPE cmp_handle, |
| OMX_U32 port, |
| OMX_BUFFERHEADERTYPE *p_buffer_hdr) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| if (cmp_handle == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); |
| |
| retval = OMX_ErrorInvalidComponent; |
| } |
| else if (p_buffer_hdr == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL"); |
| |
| retval = OMX_ErrorBadParameter; |
| } |
| else if ((port != OMX_CORE_PORT_INDEX_IP) && |
| (port != OMX_CORE_PORT_INDEX_OP)) |
| { |
| OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", port); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| else if (m_state != OMX_StateIdle) |
| { |
| if (m_state != OMX_StateExecuting) |
| { |
| OMX_SWVDEC_LOG_ERROR("disallowed in state %s", |
| OMX_STATETYPE_STRING(m_state)); |
| |
| retval = OMX_ErrorIncorrectStateOperation; |
| } |
| else |
| { |
| if (((port == OMX_CORE_PORT_INDEX_IP) && m_port_ip.enabled) || |
| ((port == OMX_CORE_PORT_INDEX_OP) && m_port_op.enabled)) |
| { |
| OMX_SWVDEC_LOG_ERROR("port index %d not disabled", port); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| } |
| } |
| |
| if (retval == OMX_ErrorNone) |
| { |
| OMX_SWVDEC_LOG_API("port index %d, %p", port, p_buffer_hdr); |
| |
| if (port == OMX_CORE_PORT_INDEX_IP) |
| { |
| retval = buffer_deallocate_ip(p_buffer_hdr); |
| } |
| else |
| { |
| retval = buffer_deallocate_op(p_buffer_hdr); |
| } |
| } |
| |
| if ((retval == OMX_ErrorNone) && |
| (m_status_flags & (1 << PENDING_STATE_IDLE_TO_LOADED))) |
| { |
| if ((m_port_ip.unpopulated == OMX_TRUE) && |
| (m_port_op.unpopulated == OMX_TRUE)) |
| { |
| SWVDEC_STATUS retval_swvdec; |
| |
| if ((retval_swvdec = swvdec_stop(m_swvdec_handle)) == |
| SWVDEC_STATUS_SUCCESS) |
| { |
| m_status_flags &= ~(1 << PENDING_STATE_IDLE_TO_LOADED); |
| |
| async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, |
| OMX_CommandStateSet, |
| OMX_StateLoaded); |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("failed to stop SwVdec"); |
| |
| retval = retval_swvdec2omx(retval_swvdec); |
| } |
| } |
| } |
| |
| if ((retval == OMX_ErrorNone) && |
| (m_status_flags & (1 << PENDING_PORT_DISABLE_IP)) && |
| m_port_ip.unpopulated) |
| { |
| m_status_flags &= ~(1 << PENDING_PORT_DISABLE_IP); |
| |
| async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, |
| OMX_CommandPortDisable, |
| OMX_CORE_PORT_INDEX_IP); |
| } |
| |
| if ((retval == OMX_ErrorNone) && |
| (m_status_flags & (1 << PENDING_PORT_DISABLE_OP)) && |
| m_port_op.unpopulated) |
| { |
| if (m_port_reconfig_inprogress) |
| { |
| SWVDEC_STATUS retval_swvdec; |
| |
| if ((retval_swvdec = swvdec_stop(m_swvdec_handle)) != |
| SWVDEC_STATUS_SUCCESS) |
| { |
| OMX_SWVDEC_LOG_ERROR("failed to stop SwVdec"); |
| |
| retval = retval_swvdec2omx(retval_swvdec); |
| } |
| } |
| |
| m_status_flags &= ~(1 << PENDING_PORT_DISABLE_OP); |
| |
| async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, |
| OMX_CommandPortDisable, |
| OMX_CORE_PORT_INDEX_OP); |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Send a buffer to component's input port to be emptied. |
| * |
| * @param[in] cmp_handle: Component handle. |
| * @param[in] p_buffer_hdr: Pointer to buffer's buffer header. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::empty_this_buffer(OMX_HANDLETYPE cmp_handle, |
| OMX_BUFFERHEADERTYPE *p_buffer_hdr) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| unsigned int ii; |
| |
| if (m_state == OMX_StateInvalid) |
| { |
| OMX_SWVDEC_LOG_ERROR("in invalid state"); |
| |
| retval = OMX_ErrorInvalidState; |
| } |
| else if (cmp_handle == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); |
| |
| retval = OMX_ErrorInvalidComponent; |
| } |
| else if (p_buffer_hdr == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL"); |
| |
| retval = OMX_ErrorBadParameter; |
| } |
| else if (p_buffer_hdr->pBuffer == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_buffer_hdr->pBuffer = NULL"); |
| |
| retval = OMX_ErrorBadParameter; |
| } |
| else if (p_buffer_hdr->pInputPortPrivate == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_buffer_hdr->pInputPortPrivate = NULL"); |
| |
| retval = OMX_ErrorBadParameter; |
| } |
| else if (m_port_ip.enabled == OMX_FALSE) |
| { |
| OMX_SWVDEC_LOG_ERROR("ip port disabled"); |
| |
| retval = OMX_ErrorIncorrectStateOperation; |
| } |
| else if (p_buffer_hdr->nInputPortIndex != OMX_CORE_PORT_INDEX_IP) |
| { |
| OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", |
| p_buffer_hdr->nInputPortIndex); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| |
| if (retval != OMX_ErrorNone) |
| { |
| goto empty_this_buffer_exit; |
| } |
| |
| for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++) |
| { |
| if (p_buffer_hdr == &(m_buffer_array_ip[ii].buffer_header)) |
| { |
| OMX_SWVDEC_LOG_LOW("ip buffer %p has index %d", |
| p_buffer_hdr->pBuffer, |
| ii); |
| break; |
| } |
| } |
| |
| if (ii == m_port_ip.def.nBufferCountActual) |
| { |
| OMX_SWVDEC_LOG_ERROR("ip buffer %p not found", |
| p_buffer_hdr->pBuffer); |
| |
| retval = OMX_ErrorBadParameter; |
| goto empty_this_buffer_exit; |
| } |
| |
| OMX_SWVDEC_LOG_API("%p: buffer %p, flags 0x%08x, filled length %d, " |
| "timestamp %lld", |
| p_buffer_hdr, |
| p_buffer_hdr->pBuffer, |
| p_buffer_hdr->nFlags, |
| p_buffer_hdr->nFilledLen, |
| p_buffer_hdr->nTimeStamp); |
| |
| async_post_event(OMX_SWVDEC_EVENT_ETB, |
| (unsigned long) p_buffer_hdr, |
| (unsigned long) ii); |
| |
| empty_this_buffer_exit: |
| return retval; |
| } |
| |
| /** |
| * @brief Send a buffer to component's output port to be filled. |
| * |
| * @param[in] cmp_handle: Component handle. |
| * @param[in] p_buffer_hdr: Pointer to buffer's buffer header. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::fill_this_buffer(OMX_HANDLETYPE cmp_handle, |
| OMX_BUFFERHEADERTYPE *p_buffer_hdr) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| unsigned int ii; |
| |
| SWVDEC_BUFFER *p_buffer_swvdec; |
| |
| if (m_state == OMX_StateInvalid) |
| { |
| OMX_SWVDEC_LOG_ERROR("in invalid state"); |
| |
| retval = OMX_ErrorInvalidState; |
| } |
| else if (cmp_handle == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); |
| |
| retval = OMX_ErrorInvalidComponent; |
| } |
| else if (p_buffer_hdr == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL"); |
| |
| retval = OMX_ErrorBadParameter; |
| } |
| else if (p_buffer_hdr->pBuffer == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_buffer_hdr->pBuffer = NULL"); |
| |
| retval = OMX_ErrorBadParameter; |
| } |
| else if (p_buffer_hdr->pOutputPortPrivate == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_buffer_hdr->pOutputPortPrivate = NULL"); |
| |
| retval = OMX_ErrorBadParameter; |
| } |
| else if (m_port_op.enabled == OMX_FALSE) |
| { |
| OMX_SWVDEC_LOG_ERROR("op port disabled"); |
| |
| retval = OMX_ErrorIncorrectStateOperation; |
| } |
| else if (p_buffer_hdr->nOutputPortIndex != OMX_CORE_PORT_INDEX_OP) |
| { |
| OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", |
| p_buffer_hdr->nOutputPortIndex); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| |
| if (retval != OMX_ErrorNone) |
| { |
| goto fill_this_buffer_exit; |
| } |
| |
| OMX_SWVDEC_LOG_API("%p", p_buffer_hdr); |
| |
| for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++) |
| { |
| if (p_buffer_hdr == &(m_buffer_array_op[ii].buffer_header)) |
| { |
| OMX_SWVDEC_LOG_LOW("op buffer %p has index %d", |
| p_buffer_hdr->pBuffer, |
| ii); |
| break; |
| } |
| } |
| |
| if (ii == m_port_op.def.nBufferCountActual) |
| { |
| OMX_SWVDEC_LOG_ERROR("op buffer %p not found", |
| p_buffer_hdr->pBuffer); |
| |
| retval = OMX_ErrorBadParameter; |
| goto fill_this_buffer_exit; |
| } |
| |
| p_buffer_swvdec = &m_buffer_array_op[ii].buffer_swvdec; |
| |
| if (m_meta_buffer_mode) |
| { |
| struct VideoDecoderOutputMetaData *p_meta_data; |
| |
| private_handle_t *p_private_handle; |
| |
| struct vdec_bufferpayload *p_buffer_payload; |
| |
| p_meta_data = |
| (struct VideoDecoderOutputMetaData *) p_buffer_hdr->pBuffer; |
| |
| p_private_handle = (private_handle_t *) (p_meta_data->pHandle); |
| |
| p_buffer_payload = &m_buffer_array_op[ii].buffer_payload; |
| |
| if (p_private_handle == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR( |
| "p_buffer_hdr->pBuffer->pHandle = NULL"); |
| |
| retval = OMX_ErrorBadParameter; |
| goto fill_this_buffer_exit; |
| } |
| |
| pthread_mutex_lock(&m_meta_buffer_array_mutex); |
| |
| if (m_meta_buffer_array[ii].ref_count == 0) |
| { |
| unsigned char *bufferaddr; |
| |
| bufferaddr = ion_map(p_private_handle->fd,p_private_handle->size); |
| |
| if (bufferaddr == MAP_FAILED) |
| { |
| OMX_SWVDEC_LOG_ERROR("mmap() failed for " |
| "fd %d of size %d", |
| p_private_handle->fd, |
| p_private_handle->size); |
| |
| pthread_mutex_unlock(&m_meta_buffer_array_mutex); |
| |
| retval = OMX_ErrorInsufficientResources; |
| goto fill_this_buffer_exit; |
| } |
| |
| p_buffer_payload->bufferaddr = bufferaddr; |
| p_buffer_payload->pmem_fd = p_private_handle->fd; |
| p_buffer_payload->buffer_len = p_private_handle->size; |
| p_buffer_payload->mmaped_size = p_private_handle->size; |
| |
| p_buffer_swvdec->p_buffer = bufferaddr; |
| p_buffer_swvdec->size = p_private_handle->size; |
| p_buffer_swvdec->p_client_data = (void *) ((unsigned long) ii); |
| } |
| |
| meta_buffer_ref_add(ii, p_buffer_payload->pmem_fd); |
| |
| pthread_mutex_unlock(&m_meta_buffer_array_mutex); |
| } |
| |
| OMX_SWVDEC_LOG_LOW("%p: buffer %p", |
| p_buffer_hdr, |
| p_buffer_swvdec->p_buffer); |
| |
| async_post_event(OMX_SWVDEC_EVENT_FTB, |
| (unsigned long) p_buffer_hdr, |
| (unsigned long) ii); |
| |
| fill_this_buffer_exit: |
| return retval; |
| } |
| |
| /** |
| * @brief Set component's callback structure. |
| * |
| * @param[in] cmp_handle: Component handle. |
| * @param[in] p_callbacks: Pointer to callback structure. |
| * @param[in] p_app_data: Pointer to IL client app data. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::set_callbacks(OMX_HANDLETYPE cmp_handle, |
| OMX_CALLBACKTYPE *p_callbacks, |
| OMX_PTR p_app_data) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| OMX_SWVDEC_LOG_API(""); |
| |
| if (m_state == OMX_StateInvalid) |
| { |
| OMX_SWVDEC_LOG_ERROR("in invalid state"); |
| |
| retval = OMX_ErrorInvalidState; |
| } |
| else if (cmp_handle == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); |
| |
| retval = OMX_ErrorInvalidComponent; |
| } |
| else if (p_callbacks->EventHandler == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_callbacks->EventHandler = NULL"); |
| |
| retval = OMX_ErrorBadParameter; |
| } |
| else if (p_callbacks->EmptyBufferDone == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_callbacks->EmptyBufferDone = NULL"); |
| |
| retval = OMX_ErrorBadParameter; |
| } |
| else if (p_callbacks->FillBufferDone == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_callbacks->FillBufferDone = NULL"); |
| |
| retval = OMX_ErrorBadParameter; |
| } |
| else |
| { |
| m_callback = *p_callbacks; |
| m_app_data = p_app_data; |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Use EGL image. |
| * |
| * @retval OMX_ErrorNotImplemented |
| */ |
| OMX_ERRORTYPE omx_swvdec::use_EGL_image(OMX_HANDLETYPE cmp_handle, |
| OMX_BUFFERHEADERTYPE **pp_buffer_hdr, |
| OMX_U32 port, |
| OMX_PTR p_app_data, |
| void *egl_image) |
| { |
| (void) cmp_handle; |
| (void) pp_buffer_hdr; |
| (void) port; |
| (void) p_app_data; |
| (void) egl_image; |
| |
| OMX_SWVDEC_LOG_API(""); |
| |
| OMX_SWVDEC_LOG_ERROR("not implemented"); |
| |
| return OMX_ErrorNotImplemented; |
| } |
| |
| /** |
| * @brief Enumerate component role. |
| * |
| * @param[in] cmp_handle: Component handle. |
| * @param[in,out] p_role: Pointer to component role string. |
| * @param[in] index: Role index being queried. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::component_role_enum(OMX_HANDLETYPE cmp_handle, |
| OMX_U8 *p_role, |
| OMX_U32 index) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| if (m_state == OMX_StateInvalid) |
| { |
| OMX_SWVDEC_LOG_ERROR("in invalid state"); |
| |
| retval = OMX_ErrorInvalidState; |
| } |
| else if (cmp_handle == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("cmp_handle = NULL"); |
| |
| retval = OMX_ErrorInvalidComponent; |
| } |
| else if (index > 0) |
| { |
| OMX_SWVDEC_LOG_HIGH("index '%d' unsupported; no more roles", index); |
| |
| retval = OMX_ErrorNoMore; |
| } |
| else |
| { |
| memcpy(p_role, m_role_name, OMX_MAX_STRINGNAME_SIZE); |
| |
| OMX_SWVDEC_LOG_API("index '%d': '%s'", index, p_role); |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * ------------------------- |
| * SwVdec callback functions |
| * ------------------------- |
| */ |
| |
| /** |
| * @brief SwVdec empty buffer done callback. |
| * |
| * @param[in] swvdec_handle: SwVdec handle. |
| * @param[in] p_buffer_ip: Pointer to input buffer structure. |
| * @param[in] p_client_handle: Pointer to SwVdec's client handle. |
| * |
| * @retval SWVDEC_STATUS_SUCCESS |
| * @retval SWVDEC_STATUS_NULL_POINTER |
| * @retval SWVDEC_STATUS_INVALID_PARAMETERS |
| */ |
| SWVDEC_STATUS omx_swvdec::swvdec_empty_buffer_done_callback( |
| SWVDEC_HANDLE swvdec_handle, |
| SWVDEC_BUFFER *p_buffer_ip, |
| void *p_client_handle) |
| { |
| SWVDEC_STATUS retval = SWVDEC_STATUS_SUCCESS; |
| |
| if (p_buffer_ip == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_buffer_ip = NULL"); |
| |
| retval = SWVDEC_STATUS_NULL_POINTER; |
| } |
| else if (p_client_handle == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_client_handle = NULL"); |
| |
| retval = SWVDEC_STATUS_NULL_POINTER; |
| } |
| else |
| { |
| omx_swvdec *p_omx_swvdec = (omx_swvdec *) p_client_handle; |
| |
| if (swvdec_handle != p_omx_swvdec->m_swvdec_handle) |
| { |
| OMX_SWVDEC_LOG_ERROR("invalid SwVdec handle"); |
| |
| retval = SWVDEC_STATUS_INVALID_PARAMETERS; |
| } |
| else |
| { |
| p_omx_swvdec->swvdec_empty_buffer_done(p_buffer_ip); |
| } |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief SwVdec fill buffer done callback. |
| * |
| * @param[in] swvdec_handle: SwVdec handle. |
| * @param[in] p_buffer_op: Pointer to output buffer structure. |
| * @param[in] p_client_handle: Pointer to SwVdec's client handle. |
| * |
| * @retval SWVDEC_STATUS_SUCCESS |
| * @retval SWVDEC_STATUS_NULL_POINTER |
| * @retval SWVDEC_STATUS_INVALID_PARAMETERS |
| */ |
| SWVDEC_STATUS omx_swvdec::swvdec_fill_buffer_done_callback( |
| SWVDEC_HANDLE swvdec_handle, |
| SWVDEC_BUFFER *p_buffer_op, |
| void *p_client_handle) |
| { |
| SWVDEC_STATUS retval = SWVDEC_STATUS_SUCCESS; |
| |
| if (p_buffer_op == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_buffer_op = NULL"); |
| |
| retval = SWVDEC_STATUS_NULL_POINTER; |
| } |
| else if (p_client_handle == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_client_handle = NULL"); |
| |
| retval = SWVDEC_STATUS_NULL_POINTER; |
| } |
| else |
| { |
| omx_swvdec *p_omx_swvdec = (omx_swvdec *) p_client_handle; |
| |
| if (swvdec_handle != p_omx_swvdec->m_swvdec_handle) |
| { |
| OMX_SWVDEC_LOG_ERROR("invalid SwVdec handle"); |
| |
| retval = SWVDEC_STATUS_INVALID_PARAMETERS; |
| } |
| else |
| { |
| p_omx_swvdec->swvdec_fill_buffer_done(p_buffer_op); |
| } |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief SwVdec event handler callback. |
| * |
| * @param[in] swvdec_handle: SwVdec handle. |
| * @param[in] event: Event. |
| * @param[in] p_data: Pointer to event-specific data. |
| * @param[in] p_client_handle: Pointer to SwVdec's client handle. |
| * |
| * @retval SWVDEC_STATUS_SUCCESS |
| * @retval SWVDEC_STATUS_NULL_POINTER |
| * @retval SWVDEC_STATUS_INVALID_PARAMETERS |
| */ |
| SWVDEC_STATUS omx_swvdec::swvdec_event_handler_callback( |
| SWVDEC_HANDLE swvdec_handle, |
| SWVDEC_EVENT event, |
| void *p_data, |
| void *p_client_handle) |
| { |
| SWVDEC_STATUS retval = SWVDEC_STATUS_SUCCESS; |
| |
| if ((event == SWVDEC_EVENT_RELEASE_REFERENCE) && (p_data == NULL)) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_data = NULL"); |
| |
| retval = SWVDEC_STATUS_NULL_POINTER; |
| } |
| else if (p_client_handle == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_client_handle = NULL"); |
| |
| retval = SWVDEC_STATUS_NULL_POINTER; |
| } |
| else |
| { |
| omx_swvdec *p_omx_swvdec = (omx_swvdec *) p_client_handle; |
| |
| if (swvdec_handle != p_omx_swvdec->m_swvdec_handle) |
| { |
| OMX_SWVDEC_LOG_ERROR("invalid SwVdec handle"); |
| |
| retval = SWVDEC_STATUS_INVALID_PARAMETERS; |
| } |
| else |
| { |
| p_omx_swvdec->swvdec_event_handler(event, p_data); |
| } |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * ----------------- |
| * PRIVATE FUNCTIONS |
| * ----------------- |
| */ |
| |
| /** |
| * @brief Set frame dimensions for OMX component & SwVdec core. |
| * |
| * @param[in] width: Frame width. |
| * @param[in] height: Frame height. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::set_frame_dimensions(unsigned int width, |
| unsigned int height) |
| { |
| OMX_ERRORTYPE retval; |
| |
| m_frame_dimensions.width = width; |
| m_frame_dimensions.height = height; |
| |
| OMX_SWVDEC_LOG_HIGH("%d x %d", |
| m_frame_dimensions.width, |
| m_frame_dimensions.height); |
| |
| retval = set_frame_dimensions_swvdec(); |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Set frame attributes for OMX component & SwVdec core, based on |
| * frame dimensions & color format. |
| * |
| * @param[in] color_format: Color format. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::set_frame_attributes( |
| OMX_COLOR_FORMATTYPE color_format) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| unsigned int width = m_frame_dimensions.width; |
| unsigned int height = m_frame_dimensions.height; |
| |
| unsigned int scanlines_uv; |
| |
| unsigned int plane_size_y; |
| unsigned int plane_size_uv; |
| |
| switch (color_format) |
| { |
| |
| case OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m: |
| { |
| m_frame_attributes.stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, width); |
| m_frame_attributes.scanlines = VENUS_Y_SCANLINES(COLOR_FMT_NV12, height); |
| |
| m_frame_attributes.size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height); |
| |
| OMX_SWVDEC_LOG_HIGH("'OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m': " |
| "stride %d, scanlines %d, size %d", |
| m_frame_attributes.stride, |
| m_frame_attributes.scanlines, |
| m_frame_attributes.size); |
| |
| break; |
| } |
| |
| case OMX_COLOR_FormatYUV420SemiPlanar: |
| { |
| /** |
| * alignment factors: |
| * |
| * - stride: 16 |
| * - scanlines_y: 16 |
| * - scanlines_uv: 16 |
| * - size: 4096 |
| */ |
| |
| m_frame_attributes.stride = ALIGN(width, 16); |
| m_frame_attributes.scanlines = ALIGN(height, 16); |
| |
| scanlines_uv = ALIGN(height / 2, 16); |
| |
| plane_size_y = (m_frame_attributes.stride * |
| m_frame_attributes.scanlines); |
| |
| plane_size_uv = m_frame_attributes.stride * scanlines_uv; |
| |
| m_frame_attributes.size = ALIGN(plane_size_y + plane_size_uv, 4096); |
| |
| OMX_SWVDEC_LOG_HIGH("'OMX_COLOR_FormatYUV420SemiPlanar': " |
| "stride %d, scanlines %d, size %d", |
| m_frame_attributes.stride, |
| m_frame_attributes.scanlines, |
| m_frame_attributes.size); |
| |
| break; |
| } |
| |
| default: |
| { |
| OMX_SWVDEC_LOG_ERROR("'0x%08x' color format invalid or unsupported", |
| color_format); |
| |
| retval = OMX_ErrorBadParameter; |
| break; |
| } |
| |
| } // switch (color_format) |
| |
| if (retval == OMX_ErrorNone) |
| { |
| m_omx_color_formattype = color_format; |
| |
| retval = set_frame_attributes_swvdec(); |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Set maximum adaptive playback frame dimensions for OMX component & |
| * SwVdec core. |
| * |
| * @param[in] width: Max adaptive playback frame width. |
| * @param[in] height: Max adaptive playback frame height. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::set_adaptive_playback(unsigned int max_width, |
| unsigned int max_height) |
| { |
| OMX_ERRORTYPE retval; |
| |
| m_frame_dimensions_max.width = max_width; |
| m_frame_dimensions_max.height = max_height; |
| |
| OMX_SWVDEC_LOG_HIGH("%d x %d", |
| m_frame_dimensions_max.width, |
| m_frame_dimensions_max.height); |
| |
| retval = set_adaptive_playback_swvdec(); |
| |
| if (retval == OMX_ErrorNone) |
| { |
| retval = set_frame_dimensions(max_width, max_height); |
| } |
| |
| if (retval == OMX_ErrorNone) |
| { |
| retval = set_frame_attributes(m_omx_color_formattype); |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Get video port format for input or output port. |
| * |
| * @param[in,out] p_port_format: Pointer to video port format type. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::get_video_port_format( |
| OMX_VIDEO_PARAM_PORTFORMATTYPE *p_port_format) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| if (p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_IP) |
| { |
| if (p_port_format->nIndex == 0) |
| { |
| p_port_format->eColorFormat = OMX_COLOR_FormatUnused; |
| |
| p_port_format->eCompressionFormat = m_omx_video_codingtype; |
| |
| OMX_SWVDEC_LOG_HIGH("color format 0x%08x, " |
| "compression format 0x%08x", |
| p_port_format->eColorFormat, |
| p_port_format->eCompressionFormat); |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_HIGH("index '%d' unsupported; " |
| "no more compression formats", |
| p_port_format->nIndex); |
| |
| retval = OMX_ErrorNoMore; |
| } |
| } |
| else if (p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_OP) |
| { |
| if (p_port_format->nIndex == 0) |
| { |
| p_port_format->eColorFormat = |
| OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m; |
| |
| p_port_format->eCompressionFormat = OMX_VIDEO_CodingUnused; |
| |
| OMX_SWVDEC_LOG_HIGH("color format 0x%08x, " |
| "compression format 0x%08x", |
| p_port_format->eColorFormat, |
| p_port_format->eCompressionFormat); |
| } |
| else if (p_port_format->nIndex == 1) |
| { |
| p_port_format->eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; |
| |
| p_port_format->eCompressionFormat = OMX_VIDEO_CodingUnused; |
| |
| OMX_SWVDEC_LOG_HIGH("color format 0x%08x, " |
| "compression format 0x%08x", |
| p_port_format->eColorFormat, |
| p_port_format->eCompressionFormat); |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_HIGH("index '%d' unsupported; no more color formats", |
| p_port_format->nIndex); |
| |
| retval = OMX_ErrorNoMore; |
| } |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", |
| p_port_format->nPortIndex); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Set video port format for input or output port. |
| * |
| * @param[in] p_port_format: Pointer to video port format type. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::set_video_port_format( |
| OMX_VIDEO_PARAM_PORTFORMATTYPE *p_port_format) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| if (p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_IP) |
| { |
| OMX_SWVDEC_LOG_HIGH("OMX_IndexParamVideoPortFormat, port index 0; " |
| "doing nothing"); |
| } |
| else if (p_port_format->nPortIndex == OMX_CORE_PORT_INDEX_OP) |
| { |
| retval = set_frame_attributes(p_port_format->eColorFormat); |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", |
| p_port_format->nPortIndex); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Get port definition for input or output port. |
| * |
| * @param[in,out] p_port_def: Pointer to port definition type. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::get_port_definition( |
| OMX_PARAM_PORTDEFINITIONTYPE *p_port_def) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| p_port_def->eDomain = OMX_PortDomainVideo; |
| |
| if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_IP) |
| { |
| if ((retval = get_buffer_requirements_swvdec(OMX_CORE_PORT_INDEX_IP)) != |
| OMX_ErrorNone) |
| { |
| goto get_port_definition_exit; |
| } |
| |
| p_port_def->eDir = OMX_DirInput; |
| p_port_def->nBufferCountActual = m_port_ip.def.nBufferCountActual; |
| p_port_def->nBufferCountMin = m_port_ip.def.nBufferCountMin; |
| p_port_def->nBufferSize = m_port_ip.def.nBufferSize; |
| p_port_def->bEnabled = m_port_ip.enabled; |
| p_port_def->bPopulated = m_port_ip.populated; |
| |
| // VTS uses input port dimensions to set OP dimensions |
| if ((retval = get_frame_dimensions_swvdec()) != OMX_ErrorNone) |
| { |
| goto get_port_definition_exit; |
| } |
| |
| p_port_def->format.video.nFrameWidth = m_frame_dimensions.width; |
| p_port_def->format.video.nFrameHeight = m_frame_dimensions.height; |
| |
| OMX_SWVDEC_LOG_HIGH("port index %d: " |
| "count actual %d, count min %d, size %d, %d x %d", |
| p_port_def->nPortIndex, |
| p_port_def->nBufferCountActual, |
| p_port_def->nBufferCountMin, |
| p_port_def->nBufferSize, |
| p_port_def->format.video.nFrameWidth, |
| p_port_def->format.video.nFrameHeight); |
| |
| p_port_def->format.video.eColorFormat = OMX_COLOR_FormatUnused; |
| p_port_def->format.video.eCompressionFormat = m_omx_video_codingtype; |
| } |
| else if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_OP) |
| { |
| if ((retval = get_frame_dimensions_swvdec()) != OMX_ErrorNone) |
| { |
| goto get_port_definition_exit; |
| } |
| |
| p_port_def->format.video.nFrameWidth = m_frame_dimensions.width; |
| p_port_def->format.video.nFrameHeight = m_frame_dimensions.height; |
| |
| if (m_port_reconfig_inprogress) |
| { |
| if ((retval = set_frame_attributes(m_omx_color_formattype)) != |
| OMX_ErrorNone) |
| { |
| goto get_port_definition_exit; |
| } |
| } |
| |
| if ((retval = get_frame_attributes_swvdec()) != OMX_ErrorNone) |
| { |
| goto get_port_definition_exit; |
| } |
| |
| p_port_def->format.video.nStride = m_frame_attributes.stride; |
| p_port_def->format.video.nSliceHeight = m_frame_attributes.scanlines; |
| |
| OMX_SWVDEC_LOG_HIGH("port index %d: " |
| "%d x %d, stride %d, sliceheight %d", |
| p_port_def->nPortIndex, |
| p_port_def->format.video.nFrameWidth, |
| p_port_def->format.video.nFrameHeight, |
| p_port_def->format.video.nStride, |
| p_port_def->format.video.nSliceHeight); |
| |
| /** |
| * Query to SwVdec core for buffer requirements is not allowed in |
| * executing state since it will overwrite the component's buffer |
| * requirements updated via the most recent set_parameter(). |
| * |
| * Buffer requirements communicated to component via set_parameter() are |
| * not propagated to SwVdec core. |
| * |
| * The only execption is if port reconfiguration is in progress, in |
| * which case the query to SwVdec core is required since buffer |
| * requirements can change based on new dimensions. |
| */ |
| if ((m_state != OMX_StateExecuting) || m_port_reconfig_inprogress) |
| { |
| if ((retval = |
| get_buffer_requirements_swvdec(OMX_CORE_PORT_INDEX_OP)) != |
| OMX_ErrorNone) |
| { |
| goto get_port_definition_exit; |
| } |
| } |
| |
| p_port_def->eDir = OMX_DirOutput; |
| p_port_def->nBufferCountActual = m_port_op.def.nBufferCountActual; |
| p_port_def->nBufferCountMin = m_port_op.def.nBufferCountMin; |
| p_port_def->nBufferSize = m_port_op.def.nBufferSize; |
| p_port_def->bEnabled = m_port_op.enabled; |
| p_port_def->bPopulated = m_port_op.populated; |
| |
| OMX_SWVDEC_LOG_HIGH("port index %d: " |
| "count actual %d, count min %d, size %d", |
| p_port_def->nPortIndex, |
| p_port_def->nBufferCountActual, |
| p_port_def->nBufferCountMin, |
| p_port_def->nBufferSize); |
| |
| p_port_def->format.video.eColorFormat = m_omx_color_formattype; |
| p_port_def->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; |
| |
| if (m_omx_color_formattype == |
| OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m) |
| { |
| OMX_SWVDEC_LOG_HIGH( |
| "port index %d: color format '0x%08x': " |
| "OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m", |
| p_port_def->nPortIndex, |
| p_port_def->format.video.eColorFormat); |
| } |
| else if (m_omx_color_formattype == OMX_COLOR_FormatYUV420SemiPlanar) |
| { |
| OMX_SWVDEC_LOG_HIGH("port index %d: color format '0x%08x': " |
| "OMX_COLOR_FormatYUV420SemiPlanar", |
| p_port_def->nPortIndex, |
| p_port_def->format.video.eColorFormat); |
| } |
| else |
| { |
| assert(0); |
| retval = OMX_ErrorUndefined; |
| } |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", p_port_def->nPortIndex); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| |
| get_port_definition_exit: |
| return retval; |
| } |
| |
| /** |
| * @brief Set port definition for input or output port. |
| * |
| * @param[in] p_port_def: Pointer to port definition type. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::set_port_definition( |
| OMX_PARAM_PORTDEFINITIONTYPE *p_port_def) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| OMX_SWVDEC_LOG_HIGH("port index %d: " |
| "count actual %d, count min %d, size %d", |
| p_port_def->nPortIndex, |
| p_port_def->nBufferCountActual, |
| p_port_def->nBufferCountMin, |
| p_port_def->nBufferSize); |
| |
| if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_IP) |
| { |
| m_port_ip.def.nBufferCountActual = p_port_def->nBufferCountActual; |
| m_port_ip.def.nBufferCountMin = p_port_def->nBufferCountMin; |
| m_port_ip.def.nBufferSize = p_port_def->nBufferSize; |
| } |
| else if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_OP) |
| { |
| /** |
| * OMX component's output port nBufferSize is not updated based on what |
| * IL client sends; instead it is updated based on the possibly updated |
| * frame attributes. |
| * |
| * This is because set_parameter() for output port definition only has |
| * updates to buffer counts or frame dimensions. |
| */ |
| |
| m_port_op.def.nBufferCountActual = p_port_def->nBufferCountActual; |
| |
| OMX_SWVDEC_LOG_HIGH("port index %d: %d x %d", |
| p_port_def->nPortIndex, |
| p_port_def->format.video.nFrameWidth, |
| p_port_def->format.video.nFrameHeight); |
| |
| /** |
| * Update frame dimensions & attributes if: |
| * |
| * 1. not in adaptive playback mode |
| * OR |
| * 2. new frame dimensions greater than adaptive playback mode's |
| * max frame dimensions |
| */ |
| |
| if ((m_adaptive_playback_mode == false) || |
| (p_port_def->format.video.nFrameWidth > |
| m_frame_dimensions_max.width) || |
| (p_port_def->format.video.nFrameHeight > |
| m_frame_dimensions_max.height)) |
| { |
| OMX_SWVDEC_LOG_HIGH("updating frame dimensions & attributes"); |
| |
| if ((retval = |
| set_frame_dimensions(p_port_def->format.video.nFrameWidth, |
| p_port_def->format.video.nFrameHeight)) != |
| OMX_ErrorNone) |
| { |
| goto set_port_definition_exit; |
| } |
| |
| if ((retval = set_frame_attributes(m_omx_color_formattype)) != |
| OMX_ErrorNone) |
| { |
| goto set_port_definition_exit; |
| } |
| |
| // nBufferSize updated based on (possibly new) frame attributes |
| |
| m_port_op.def.nBufferSize = m_frame_attributes.size; |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_HIGH("not updating frame dimensions & attributes"); |
| } |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", p_port_def->nPortIndex); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| |
| set_port_definition_exit: |
| return retval; |
| } |
| |
| /** |
| * @brief Get supported profile & level. |
| * |
| * The supported profiles & levels are not queried from SwVdec core, but |
| * hard-coded. This should ideally be replaced with a query to SwVdec core. |
| * |
| * @param[in,out] p_profilelevel: Pointer to video profile & level type. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::get_supported_profilelevel( |
| OMX_VIDEO_PARAM_PROFILELEVELTYPE *p_profilelevel) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| if (p_profilelevel == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_profilelevel = NULL"); |
| |
| retval = OMX_ErrorBadParameter; |
| goto get_supported_profilelevel_exit; |
| } |
| |
| if (p_profilelevel->nPortIndex != OMX_CORE_PORT_INDEX_IP) |
| { |
| OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", |
| p_profilelevel->nPortIndex); |
| |
| retval = OMX_ErrorBadPortIndex; |
| goto get_supported_profilelevel_exit; |
| } |
| |
| if (m_omx_video_codingtype == OMX_VIDEO_CodingH263) |
| { |
| if (p_profilelevel->nProfileIndex == 0) |
| { |
| p_profilelevel->eProfile = OMX_VIDEO_H263ProfileBaseline; |
| p_profilelevel->eLevel = OMX_VIDEO_H263Level70; |
| |
| OMX_SWVDEC_LOG_HIGH("H.263 baseline profile, level 70"); |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_HIGH("profile index '%d' unsupported; " |
| "no more profiles", |
| p_profilelevel->nProfileIndex); |
| |
| retval = OMX_ErrorNoMore; |
| } |
| } |
| else if ((m_omx_video_codingtype == OMX_VIDEO_CodingMPEG4) || |
| (m_omx_video_codingtype == |
| ((OMX_VIDEO_CODINGTYPE) QOMX_VIDEO_CodingDivx))) |
| { |
| if (p_profilelevel->nProfileIndex == 0) |
| { |
| p_profilelevel->eProfile = OMX_VIDEO_MPEG4ProfileSimple; |
| p_profilelevel->eLevel = OMX_VIDEO_MPEG4Level6; |
| |
| OMX_SWVDEC_LOG_HIGH("MPEG-4 simple profile, level 6"); |
| } |
| else if (p_profilelevel->nProfileIndex == 1) |
| { |
| p_profilelevel->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple; |
| p_profilelevel->eLevel = OMX_VIDEO_MPEG4Level5; |
| |
| OMX_SWVDEC_LOG_HIGH("MPEG-4 advanced simple profile, level 5"); |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_HIGH("profile index '%d' unsupported; " |
| "no more profiles", |
| p_profilelevel->nProfileIndex); |
| |
| retval = OMX_ErrorNoMore; |
| } |
| } |
| else |
| { |
| assert(0); |
| retval = OMX_ErrorUndefined; |
| } |
| |
| get_supported_profilelevel_exit: |
| return retval; |
| } |
| |
| /** |
| * @brief Describe color format. |
| * |
| * @param[in,out] p_params: Pointer to 'DescribeColorFormatParams' structure. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::describe_color_format( |
| DescribeColorFormatParams *p_params) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| if (p_params == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_params = NULL"); |
| |
| retval = OMX_ErrorBadParameter; |
| } |
| else |
| { |
| MediaImage *p_img = &p_params->sMediaImage; |
| |
| switch (p_params->eColorFormat) |
| { |
| |
| case OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m: |
| { |
| size_t stride, scanlines; |
| |
| p_img->mType = MediaImage::MEDIA_IMAGE_TYPE_YUV; |
| p_img->mNumPlanes = 3; |
| |
| p_img->mWidth = p_params->nFrameWidth; |
| p_img->mHeight = p_params->nFrameHeight; |
| |
| /** |
| * alignment factors: |
| * |
| * - stride: 512 |
| * - scanlines: 512 |
| */ |
| stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, p_img->mWidth); |
| scanlines = VENUS_Y_SCANLINES(COLOR_FMT_NV12, p_img->mHeight); |
| |
| p_img->mBitDepth = 8; |
| |
| // plane 0 (Y) |
| p_img->mPlane[MediaImage::Y].mOffset = 0; |
| p_img->mPlane[MediaImage::Y].mColInc = 1; |
| p_img->mPlane[MediaImage::Y].mRowInc = stride; |
| p_img->mPlane[MediaImage::Y].mHorizSubsampling = 1; |
| p_img->mPlane[MediaImage::Y].mVertSubsampling = 1; |
| |
| // plane 1 (U) |
| p_img->mPlane[MediaImage::U].mOffset = stride * scanlines; |
| p_img->mPlane[MediaImage::U].mColInc = 2; |
| p_img->mPlane[MediaImage::U].mRowInc = stride; |
| p_img->mPlane[MediaImage::U].mHorizSubsampling = 2; |
| p_img->mPlane[MediaImage::U].mVertSubsampling = 2; |
| |
| // plane 2 (V) |
| p_img->mPlane[MediaImage::V].mOffset = stride * scanlines + 1; |
| p_img->mPlane[MediaImage::V].mColInc = 2; |
| p_img->mPlane[MediaImage::V].mRowInc = stride; |
| p_img->mPlane[MediaImage::V].mHorizSubsampling = 2; |
| p_img->mPlane[MediaImage::V].mVertSubsampling = 2; |
| |
| break; |
| } |
| |
| case OMX_COLOR_FormatYUV420SemiPlanar: |
| { |
| // do nothing; standard OMX color formats should not be described |
| retval = OMX_ErrorUnsupportedSetting; |
| break; |
| } |
| |
| default: |
| { |
| OMX_SWVDEC_LOG_ERROR("color format '0x%08x' invalid/unsupported", |
| p_params->eColorFormat); |
| |
| p_img->mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN; |
| |
| retval = OMX_ErrorBadParameter; |
| break; |
| } |
| |
| } // switch (p_params->eColorFormat) |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Set QTI vendor-specific port definition for input or output port. |
| * |
| * @param[in] p_port_def: Pointer to QTI vendor-specific port definition type. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::set_port_definition_qcom( |
| OMX_QCOM_PARAM_PORTDEFINITIONTYPE *p_port_def) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_IP) |
| { |
| switch (p_port_def->nFramePackingFormat) |
| { |
| |
| case OMX_QCOM_FramePacking_Arbitrary: |
| { |
| OMX_SWVDEC_LOG_HIGH("OMX_QCOM_FramePacking_Arbitrary"); |
| |
| m_arbitrary_bytes_mode = true; |
| |
| break; |
| } |
| |
| case OMX_QCOM_FramePacking_OnlyOneCompleteFrame: |
| { |
| OMX_SWVDEC_LOG_HIGH( |
| "OMX_QCOM_FramePacking_OnlyOneCompleteFrame"); |
| |
| break; |
| } |
| |
| default: |
| { |
| OMX_SWVDEC_LOG_ERROR( |
| "frame packing format '%d' unsupported", |
| p_port_def->nFramePackingFormat); |
| |
| retval = OMX_ErrorUnsupportedSetting; |
| break; |
| } |
| |
| } |
| } |
| else if (p_port_def->nPortIndex == OMX_CORE_PORT_INDEX_OP) |
| { |
| OMX_SWVDEC_LOG_HIGH("nMemRegion %d, nCacheAttr %d", |
| p_port_def->nMemRegion, |
| p_port_def->nCacheAttr); |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", |
| p_port_def->nPortIndex); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Set SwVdec frame dimensions based on OMX component frame dimensions. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::set_frame_dimensions_swvdec() |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| SWVDEC_PROPERTY property; |
| |
| SWVDEC_STATUS retval_swvdec; |
| |
| property.id = SWVDEC_PROPERTY_ID_FRAME_DIMENSIONS; |
| |
| property.info.frame_dimensions.width = m_frame_dimensions.width; |
| property.info.frame_dimensions.height = m_frame_dimensions.height; |
| |
| if ((retval_swvdec = swvdec_setproperty(m_swvdec_handle, &property)) != |
| SWVDEC_STATUS_SUCCESS) |
| { |
| retval = retval_swvdec2omx(retval_swvdec); |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Set SwVdec frame attributes based on OMX component frame attributes. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::set_frame_attributes_swvdec() |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| SWVDEC_FRAME_ATTRIBUTES *p_frame_attributes; |
| |
| SWVDEC_PROPERTY property; |
| |
| SWVDEC_STATUS retval_swvdec; |
| |
| p_frame_attributes = &property.info.frame_attributes; |
| |
| property.id = SWVDEC_PROPERTY_ID_FRAME_ATTRIBUTES; |
| |
| if(m_omx_color_formattype == OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m) |
| p_frame_attributes->color_format = SWVDEC_COLOR_FORMAT_SEMIPLANAR_NV12_32; |
| else |
| p_frame_attributes->color_format = SWVDEC_COLOR_FORMAT_SEMIPLANAR_NV12; |
| |
| p_frame_attributes->stride = m_frame_attributes.stride; |
| p_frame_attributes->scanlines = m_frame_attributes.scanlines; |
| p_frame_attributes->size = m_frame_attributes.size; |
| |
| if ((retval_swvdec = swvdec_setproperty(m_swvdec_handle, &property)) != |
| SWVDEC_STATUS_SUCCESS) |
| { |
| retval = retval_swvdec2omx(retval_swvdec); |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Set maximum adaptive playback frame dimensions for SwVdec core. |
| */ |
| OMX_ERRORTYPE omx_swvdec::set_adaptive_playback_swvdec() |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| SWVDEC_PROPERTY property; |
| |
| SWVDEC_STATUS retval_swvdec; |
| |
| property.id = SWVDEC_PROPERTY_ID_ADAPTIVE_PLAYBACK; |
| |
| property.info.frame_dimensions.width = m_frame_dimensions_max.width; |
| property.info.frame_dimensions.height = m_frame_dimensions_max.height; |
| |
| if ((retval_swvdec = swvdec_setproperty(m_swvdec_handle, &property)) != |
| SWVDEC_STATUS_SUCCESS) |
| { |
| retval = retval_swvdec2omx(retval_swvdec); |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Set thumbnail mode for SwVdec core. |
| */ |
| OMX_ERRORTYPE omx_swvdec::set_thumbnail_mode_swvdec() |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| SWVDEC_PROPERTY property; |
| |
| SWVDEC_STATUS retval_swvdec; |
| |
| property.id = SWVDEC_PROPERTY_ID_THUMBNAIL_MODE; |
| |
| if ((retval_swvdec = swvdec_setproperty(m_swvdec_handle, &property)) != |
| SWVDEC_STATUS_SUCCESS) |
| { |
| retval = retval_swvdec2omx(retval_swvdec); |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Get SwVdec frame dimensions and set OMX component frame dimensions. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::get_frame_dimensions_swvdec() |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| SWVDEC_PROPERTY property; |
| |
| SWVDEC_STATUS retval_swvdec; |
| |
| property.id = SWVDEC_PROPERTY_ID_FRAME_DIMENSIONS; |
| |
| if ((retval_swvdec = swvdec_getproperty(m_swvdec_handle, &property)) != |
| SWVDEC_STATUS_SUCCESS) |
| { |
| retval = retval_swvdec2omx(retval_swvdec); |
| } |
| else |
| { |
| m_frame_dimensions.width = property.info.frame_dimensions.width; |
| m_frame_dimensions.height = property.info.frame_dimensions.height; |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Get SwVdec frame attributes and set OMX component frame attributes. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::get_frame_attributes_swvdec() |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| SWVDEC_PROPERTY property; |
| |
| SWVDEC_STATUS retval_swvdec; |
| |
| property.id = SWVDEC_PROPERTY_ID_FRAME_ATTRIBUTES; |
| |
| if ((retval_swvdec = swvdec_getproperty(m_swvdec_handle, &property)) != |
| SWVDEC_STATUS_SUCCESS) |
| { |
| retval = retval_swvdec2omx(retval_swvdec); |
| } |
| else |
| { |
| m_frame_attributes.stride = property.info.frame_attributes.stride; |
| m_frame_attributes.scanlines = property.info.frame_attributes.scanlines; |
| m_frame_attributes.size = property.info.frame_attributes.size; |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Get SwVdec buffer requirements; set input or output port definitions. |
| * |
| * @param[in] port_index: Port index. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::get_buffer_requirements_swvdec( |
| unsigned int port_index) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| SWVDEC_PROPERTY property; |
| |
| SWVDEC_STATUS retval_swvdec; |
| |
| SWVDEC_BUFFER_REQ *p_buffer_req; |
| |
| if (port_index == OMX_CORE_PORT_INDEX_IP) |
| { |
| property.id = SWVDEC_PROPERTY_ID_BUFFER_REQ_IP; |
| |
| p_buffer_req = &property.info.buffer_req_ip; |
| |
| if ((retval_swvdec = swvdec_getproperty(m_swvdec_handle, &property)) != |
| SWVDEC_STATUS_SUCCESS) |
| { |
| retval = retval_swvdec2omx(retval_swvdec); |
| goto get_buffer_requirements_swvdec_exit; |
| } |
| |
| m_port_ip.def.nBufferSize = p_buffer_req->size; |
| m_port_ip.def.nBufferCountMin = p_buffer_req->mincount; |
| m_port_ip.def.nBufferCountActual = MAX((MAX(p_buffer_req->mincount, |
| OMX_SWVDEC_IP_BUFFER_COUNT_MIN)), |
| m_port_ip.def.nBufferCountActual); |
| m_port_ip.def.nBufferAlignment = p_buffer_req->alignment; |
| |
| OMX_SWVDEC_LOG_HIGH("ip port: %d bytes x %d, %d-byte aligned", |
| m_port_ip.def.nBufferSize, |
| m_port_ip.def.nBufferCountActual, |
| m_port_ip.def.nBufferAlignment); |
| } |
| else if (port_index == OMX_CORE_PORT_INDEX_OP) |
| { |
| property.id = SWVDEC_PROPERTY_ID_BUFFER_REQ_OP; |
| |
| p_buffer_req = &property.info.buffer_req_op; |
| |
| if ((retval_swvdec = swvdec_getproperty(m_swvdec_handle, &property)) != |
| SWVDEC_STATUS_SUCCESS) |
| { |
| retval = retval_swvdec2omx(retval_swvdec); |
| goto get_buffer_requirements_swvdec_exit; |
| } |
| |
| if (m_sync_frame_decoding_mode) |
| { |
| p_buffer_req->mincount = 1; |
| } |
| |
| m_port_op.def.nBufferSize = p_buffer_req->size; |
| m_port_op.def.nBufferCountMin = p_buffer_req->mincount; |
| m_port_op.def.nBufferCountActual = MAX(p_buffer_req->mincount, |
| m_port_op.def.nBufferCountActual); |
| m_port_op.def.nBufferAlignment = p_buffer_req->alignment; |
| |
| OMX_SWVDEC_LOG_HIGH("op port: %d bytes x %d, %d-byte aligned", |
| m_port_op.def.nBufferSize, |
| m_port_op.def.nBufferCountActual, |
| m_port_op.def.nBufferAlignment); |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", port_index); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| |
| get_buffer_requirements_swvdec_exit: |
| return retval; |
| } |
| |
| /** |
| * @brief Allocate input buffer, and input buffer info array if ncessary. |
| * |
| * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type |
| * structure. |
| * @param[in] p_app_data: Pointer to IL client app data. |
| * @param[in] size: Size of buffer to be allocated in bytes. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::buffer_allocate_ip( |
| OMX_BUFFERHEADERTYPE **pp_buffer_hdr, |
| OMX_PTR p_app_data, |
| OMX_U32 size) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| SWVDEC_STATUS retval_swvdec = SWVDEC_STATUS_SUCCESS; |
| |
| unsigned int ii; |
| |
| if (size != m_port_ip.def.nBufferSize) |
| { |
| OMX_SWVDEC_LOG_ERROR("requested size (%d bytes) not equal to " |
| "configured size (%d bytes)", |
| size, |
| m_port_ip.def.nBufferSize); |
| |
| retval = OMX_ErrorBadParameter; |
| goto buffer_allocate_ip_exit; |
| } |
| |
| if (m_buffer_array_ip == NULL) |
| { |
| OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s", |
| m_port_ip.def.nBufferCountActual, |
| (m_port_ip.def.nBufferCountActual > 1) ? "s" : ""); |
| |
| if ((retval = buffer_allocate_ip_info_array()) != OMX_ErrorNone) |
| { |
| goto buffer_allocate_ip_exit; |
| } |
| } |
| |
| for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++) |
| { |
| if (m_buffer_array_ip[ii].buffer_populated == false) |
| { |
| OMX_SWVDEC_LOG_LOW("buffer %d not populated", ii); |
| break; |
| } |
| } |
| |
| if (ii < m_port_ip.def.nBufferCountActual) |
| { |
| int pmem_fd = -1; |
| |
| unsigned char *bufferaddr; |
| |
| OMX_SWVDEC_LOG_HIGH("ip buffer %d: %d bytes being allocated", |
| ii, |
| size); |
| |
| m_buffer_array_ip[ii].ion_info.dev_fd= |
| ion_memory_alloc_map(&m_buffer_array_ip[ii].ion_info,size, |
| m_port_ip.def.nBufferAlignment); |
| |
| if (m_buffer_array_ip[ii].ion_info.dev_fd< 0) |
| { |
| retval = OMX_ErrorInsufficientResources; |
| goto buffer_allocate_ip_exit; |
| } |
| |
| pmem_fd = m_buffer_array_ip[ii].ion_info.data_fd; |
| |
| bufferaddr = ion_map(pmem_fd,size); |
| |
| if (bufferaddr == MAP_FAILED) |
| { |
| OMX_SWVDEC_LOG_ERROR("mmap() failed for fd %d of size %d error %s", |
| pmem_fd, |
| size, strerror(errno)); |
| |
| close(pmem_fd); |
| ion_memory_free(&m_buffer_array_ip[ii].ion_info); |
| |
| retval = OMX_ErrorInsufficientResources; |
| goto buffer_allocate_ip_exit; |
| } |
| |
| *pp_buffer_hdr = &m_buffer_array_ip[ii].buffer_header; |
| |
| m_buffer_array_ip[ii].buffer_payload.bufferaddr = bufferaddr; |
| m_buffer_array_ip[ii].buffer_payload.pmem_fd = pmem_fd; |
| m_buffer_array_ip[ii].buffer_payload.buffer_len = size; |
| m_buffer_array_ip[ii].buffer_payload.mmaped_size = size; |
| m_buffer_array_ip[ii].buffer_payload.offset = 0; |
| |
| m_buffer_array_ip[ii].buffer_swvdec.p_buffer = bufferaddr; |
| m_buffer_array_ip[ii].buffer_swvdec.size = size; |
| m_buffer_array_ip[ii].buffer_swvdec.p_client_data = |
| (void *) ((unsigned long) ii); |
| m_buffer_array_ip[ii].buffer_swvdec.fd = pmem_fd; |
| |
| m_buffer_array_ip[ii].buffer_populated = true; |
| |
| if(m_swvdec_codec == SWVDEC_CODEC_VC1) |
| { |
| OMX_SWVDEC_LOG_LOW("map ip buffer"); |
| |
| if((retval_swvdec = swvdec_register_buffer(m_swvdec_handle, |
| &m_buffer_array_ip[ii].buffer_swvdec)) |
| != SWVDEC_STATUS_SUCCESS) |
| { |
| OMX_SWVDEC_LOG_ERROR("swvdec_map failed for ip buffer %d: %p",ii,bufferaddr); |
| retval = retval_swvdec2omx(retval_swvdec);; |
| goto buffer_allocate_ip_exit; |
| } |
| } |
| |
| OMX_SWVDEC_LOG_HIGH("ip buffer %d: %p, fd = %d %d bytes", |
| ii, |
| bufferaddr, |
| pmem_fd, |
| size); |
| |
| (*pp_buffer_hdr)->pBuffer = (OMX_U8 *) bufferaddr; |
| (*pp_buffer_hdr)->nSize = sizeof(OMX_BUFFERHEADERTYPE); |
| (*pp_buffer_hdr)->nVersion.nVersion = OMX_SPEC_VERSION; |
| (*pp_buffer_hdr)->nAllocLen = size; |
| (*pp_buffer_hdr)->pAppPrivate = p_app_data; |
| (*pp_buffer_hdr)->nInputPortIndex = OMX_CORE_PORT_INDEX_IP; |
| (*pp_buffer_hdr)->pInputPortPrivate = |
| (void *) &(m_buffer_array_ip[ii].buffer_payload); |
| |
| m_port_ip.populated = port_ip_populated(); |
| m_port_ip.unpopulated = OMX_FALSE; |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("all %d ip buffers allocated", |
| m_port_ip.def.nBufferCountActual); |
| |
| retval = OMX_ErrorInsufficientResources; |
| } |
| |
| buffer_allocate_ip_exit: |
| return retval; |
| } |
| |
| /** |
| * @brief Allocate output buffer, and output buffer info array if necessary. |
| * |
| * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type |
| * structure. |
| * @param[in] p_app_data: Pointer to IL client app data. |
| * @param[in] size: Size of buffer to be allocated in bytes. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::buffer_allocate_op( |
| OMX_BUFFERHEADERTYPE **pp_buffer_hdr, |
| OMX_PTR p_app_data, |
| OMX_U32 size) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| SWVDEC_STATUS retval_swvdec = SWVDEC_STATUS_SUCCESS; |
| unsigned int ii; |
| |
| if (size != m_port_op.def.nBufferSize) |
| { |
| OMX_SWVDEC_LOG_ERROR("requested size (%d bytes) not equal to " |
| "configured size (%d bytes)", |
| size, |
| m_port_op.def.nBufferSize); |
| |
| retval = OMX_ErrorBadParameter; |
| goto buffer_allocate_op_exit; |
| } |
| |
| if (m_buffer_array_op == NULL) |
| { |
| OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s", |
| m_port_op.def.nBufferCountActual, |
| (m_port_op.def.nBufferCountActual > 1) ? "s" : ""); |
| |
| if ((retval = buffer_allocate_op_info_array()) != OMX_ErrorNone) |
| { |
| goto buffer_allocate_op_exit; |
| } |
| } |
| |
| for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++) |
| { |
| if (m_buffer_array_op[ii].buffer_populated == false) |
| { |
| OMX_SWVDEC_LOG_LOW("buffer %d not populated", ii); |
| break; |
| } |
| } |
| |
| if (ii < m_port_op.def.nBufferCountActual) |
| { |
| int pmem_fd = -1; |
| |
| unsigned char *bufferaddr; |
| |
| OMX_SWVDEC_LOG_HIGH("op buffer %d: %d bytes being allocated", |
| ii, |
| size); |
| |
| m_buffer_array_op[ii].ion_info.dev_fd= |
| ion_memory_alloc_map(&m_buffer_array_op[ii].ion_info,size, |
| m_port_op.def.nBufferAlignment); |
| |
| if (m_buffer_array_op[ii].ion_info.dev_fd < 0) |
| { |
| retval = OMX_ErrorInsufficientResources; |
| goto buffer_allocate_op_exit; |
| } |
| |
| pmem_fd = m_buffer_array_op[ii].ion_info.data_fd; |
| |
| bufferaddr = ion_map(pmem_fd,size); |
| |
| if (bufferaddr == MAP_FAILED) |
| { |
| OMX_SWVDEC_LOG_ERROR("mmap() failed for fd %d of size %d", |
| pmem_fd, |
| size); |
| |
| close(pmem_fd); |
| ion_memory_free(&m_buffer_array_op[ii].ion_info); |
| |
| retval = OMX_ErrorInsufficientResources; |
| goto buffer_allocate_op_exit; |
| } |
| |
| *pp_buffer_hdr = &m_buffer_array_op[ii].buffer_header; |
| |
| m_buffer_array_op[ii].buffer_payload.bufferaddr = bufferaddr; |
| m_buffer_array_op[ii].buffer_payload.pmem_fd = pmem_fd; |
| m_buffer_array_op[ii].buffer_payload.buffer_len = size; |
| m_buffer_array_op[ii].buffer_payload.mmaped_size = size; |
| m_buffer_array_op[ii].buffer_payload.offset = 0; |
| |
| m_buffer_array_op[ii].buffer_swvdec.p_buffer = bufferaddr; |
| m_buffer_array_op[ii].buffer_swvdec.size = size; |
| m_buffer_array_op[ii].buffer_swvdec.p_client_data = |
| (void *) ((unsigned long) ii); |
| |
| m_buffer_array_op[ii].buffer_populated = true; |
| |
| m_buffer_array_op[ii].buffer_swvdec.fd = pmem_fd ; |
| |
| if(m_swvdec_codec == SWVDEC_CODEC_VC1) |
| { |
| OMX_SWVDEC_LOG_LOW("map op buffer"); |
| |
| if((retval_swvdec = swvdec_map(m_swvdec_handle,&m_buffer_array_op[ii].buffer_swvdec)) != SWVDEC_STATUS_SUCCESS) |
| { |
| OMX_SWVDEC_LOG_ERROR("swvdec_map failed for op buffer %d: %p",ii,bufferaddr); |
| retval = retval_swvdec2omx(retval_swvdec);; |
| goto buffer_allocate_op_exit; |
| } |
| } |
| OMX_SWVDEC_LOG_HIGH("op buffer %d: %p, fd = %d %d bytes", |
| ii, |
| bufferaddr, |
| pmem_fd, |
| size); |
| |
| (*pp_buffer_hdr)->pBuffer = (OMX_U8 *) bufferaddr; |
| (*pp_buffer_hdr)->nSize = sizeof(OMX_BUFFERHEADERTYPE); |
| (*pp_buffer_hdr)->nVersion.nVersion = OMX_SPEC_VERSION; |
| (*pp_buffer_hdr)->nAllocLen = size; |
| (*pp_buffer_hdr)->pAppPrivate = p_app_data; |
| (*pp_buffer_hdr)->nOutputPortIndex = OMX_CORE_PORT_INDEX_OP; |
| (*pp_buffer_hdr)->pOutputPortPrivate = |
| (void *) &(m_buffer_array_op[ii].buffer_payload); |
| |
| m_port_op.populated = port_op_populated(); |
| m_port_op.unpopulated = OMX_FALSE; |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("all %d op buffers allocated", |
| m_port_op.def.nBufferCountActual); |
| |
| retval = OMX_ErrorInsufficientResources; |
| } |
| |
| buffer_allocate_op_exit: |
| return retval; |
| } |
| |
| /** |
| * @brief Allocate input buffer info array. |
| */ |
| OMX_ERRORTYPE omx_swvdec::buffer_allocate_ip_info_array() |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| unsigned int ii; |
| |
| OMX_BUFFERHEADERTYPE *p_buffer_hdr; |
| |
| if (m_buffer_array_ip != NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("buffer info array already allocated"); |
| |
| retval = OMX_ErrorInsufficientResources; |
| goto buffer_allocate_ip_info_array_exit; |
| } |
| |
| OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s", |
| m_port_ip.def.nBufferCountActual, |
| (m_port_ip.def.nBufferCountActual > 1) ? "s" : ""); |
| |
| m_buffer_array_ip = |
| (OMX_SWVDEC_BUFFER_INFO *) calloc(sizeof(OMX_SWVDEC_BUFFER_INFO), |
| m_port_ip.def.nBufferCountActual); |
| |
| if (m_buffer_array_ip == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("failed to allocate buffer info array; " |
| "%d element%s, %zu bytes requested", |
| m_port_ip.def.nBufferCountActual, |
| (m_port_ip.def.nBufferCountActual > 1) ? "s" : "", |
| sizeof(OMX_SWVDEC_BUFFER_INFO) * |
| m_port_ip.def.nBufferCountActual); |
| |
| retval = OMX_ErrorInsufficientResources; |
| goto buffer_allocate_ip_info_array_exit; |
| } |
| |
| for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++) |
| { |
| p_buffer_hdr = &m_buffer_array_ip[ii].buffer_header; |
| |
| // reset file descriptors |
| |
| m_buffer_array_ip[ii].buffer_payload.pmem_fd = -1; |
| m_buffer_array_ip[ii].ion_info.dev_fd= -1; |
| |
| m_buffer_array_ip[ii].buffer_swvdec.p_client_data = |
| (void *) ((unsigned long) ii); |
| |
| p_buffer_hdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); |
| p_buffer_hdr->nVersion.nVersion = OMX_SPEC_VERSION; |
| p_buffer_hdr->nInputPortIndex = OMX_CORE_PORT_INDEX_IP; |
| p_buffer_hdr->pInputPortPrivate = |
| (void *) &(m_buffer_array_ip[ii].buffer_payload); |
| } |
| |
| buffer_allocate_ip_info_array_exit: |
| return retval; |
| } |
| |
| /** |
| * @brief Allocate output buffer info array. |
| */ |
| OMX_ERRORTYPE omx_swvdec::buffer_allocate_op_info_array() |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| unsigned int ii; |
| |
| OMX_BUFFERHEADERTYPE *p_buffer_hdr; |
| |
| if (m_buffer_array_op != NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("buffer info array already allocated"); |
| |
| retval = OMX_ErrorInsufficientResources; |
| goto buffer_allocate_op_info_array_exit; |
| } |
| |
| OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s", |
| m_port_op.def.nBufferCountActual, |
| (m_port_op.def.nBufferCountActual > 1) ? "s" : ""); |
| |
| m_buffer_array_op = |
| (OMX_SWVDEC_BUFFER_INFO *) calloc(sizeof(OMX_SWVDEC_BUFFER_INFO), |
| m_port_op.def.nBufferCountActual); |
| |
| if (m_buffer_array_op == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("failed to allocate buffer info array; " |
| "%d element%s, %zu bytes requested", |
| m_port_op.def.nBufferCountActual, |
| (m_port_op.def.nBufferCountActual > 1) ? "s" : "", |
| sizeof(OMX_SWVDEC_BUFFER_INFO) * |
| m_port_op.def.nBufferCountActual); |
| |
| retval = OMX_ErrorInsufficientResources; |
| goto buffer_allocate_op_info_array_exit; |
| } |
| |
| for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++) |
| { |
| p_buffer_hdr = &m_buffer_array_op[ii].buffer_header; |
| |
| // reset file descriptors |
| |
| m_buffer_array_op[ii].buffer_payload.pmem_fd = -1; |
| m_buffer_array_op[ii].ion_info.dev_fd = -1; |
| |
| m_buffer_array_op[ii].buffer_swvdec.p_client_data = |
| (void *) ((unsigned long) ii); |
| |
| p_buffer_hdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); |
| p_buffer_hdr->nVersion.nVersion = OMX_SPEC_VERSION; |
| p_buffer_hdr->nOutputPortIndex = OMX_CORE_PORT_INDEX_OP; |
| p_buffer_hdr->pOutputPortPrivate = |
| (void *) &(m_buffer_array_op[ii].buffer_payload); |
| } |
| |
| buffer_allocate_op_info_array_exit: |
| return retval; |
| } |
| |
| /** |
| * @brief Use buffer allocated by IL client; allocate output buffer info array |
| * if necessary. |
| * |
| * @param[in,out] pp_buffer_hdr: Pointer to pointer to buffer header type |
| * structure. |
| * @param[in] p_app_data: Pointer to IL client app data. |
| * @param[in] size: Size of buffer to be allocated in bytes. |
| * @param[in] p_buffer: Pointer to buffer to be used. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::buffer_use_op( |
| OMX_BUFFERHEADERTYPE **pp_buffer_hdr, |
| OMX_PTR p_app_data, |
| OMX_U32 size, |
| OMX_U8 *p_buffer) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| SWVDEC_STATUS retval_swvdec; |
| unsigned int ii; |
| |
| (void) size; |
| |
| if (m_buffer_array_op == NULL) |
| { |
| OMX_SWVDEC_LOG_HIGH("allocating buffer info array, %d element%s", |
| m_port_op.def.nBufferCountActual, |
| (m_port_op.def.nBufferCountActual > 1) ? "s" : ""); |
| |
| if ((retval = buffer_allocate_op_info_array()) != OMX_ErrorNone) |
| { |
| goto buffer_use_op_exit; |
| } |
| } |
| |
| if (m_meta_buffer_mode && (m_meta_buffer_array == NULL)) |
| { |
| OMX_SWVDEC_LOG_HIGH("allocating meta buffer info array, %d element%s", |
| m_port_op.def.nBufferCountActual, |
| (m_port_op.def.nBufferCountActual > 1) ? "s" : ""); |
| |
| if ((retval = meta_buffer_array_allocate()) != OMX_ErrorNone) |
| { |
| goto buffer_use_op_exit; |
| } |
| } |
| |
| for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++) |
| { |
| if (m_buffer_array_op[ii].buffer_populated == false) |
| { |
| OMX_SWVDEC_LOG_LOW("buffer %d not populated", ii); |
| break; |
| } |
| } |
| |
| if (ii < m_port_op.def.nBufferCountActual) |
| { |
| struct vdec_bufferpayload *p_buffer_payload; |
| |
| SWVDEC_BUFFER *p_buffer_swvdec; |
| |
| *pp_buffer_hdr = &m_buffer_array_op[ii].buffer_header; |
| p_buffer_payload = &m_buffer_array_op[ii].buffer_payload; |
| p_buffer_swvdec = &m_buffer_array_op[ii].buffer_swvdec; |
| |
| if (m_meta_buffer_mode) |
| { |
| p_buffer_swvdec->size = m_port_op.def.nBufferSize; |
| p_buffer_swvdec->p_client_data = (void *) ((unsigned long) ii); |
| |
| m_buffer_array_op[ii].buffer_populated = true; |
| |
| (*pp_buffer_hdr)->pBuffer = p_buffer; |
| (*pp_buffer_hdr)->pAppPrivate = p_app_data; |
| (*pp_buffer_hdr)->nAllocLen = |
| sizeof(struct VideoDecoderOutputMetaData); |
| |
| OMX_SWVDEC_LOG_HIGH("op buffer %d: %p (meta buffer)", |
| ii, |
| *pp_buffer_hdr); |
| |
| m_port_op.populated = port_op_populated(); |
| m_port_op.unpopulated = OMX_FALSE; |
| } |
| else if (m_android_native_buffers) |
| { |
| private_handle_t *p_handle; |
| |
| OMX_U8 *p_buffer_mapped; |
| |
| p_handle = (private_handle_t *) p_buffer; |
| |
| if (((OMX_U32) p_handle->size) < m_port_op.def.nBufferSize) |
| { |
| OMX_SWVDEC_LOG_ERROR("requested size (%d bytes) not equal to " |
| "configured size (%d bytes)", |
| p_handle->size, |
| m_port_op.def.nBufferSize); |
| |
| retval = OMX_ErrorBadParameter; |
| goto buffer_use_op_exit; |
| } |
| |
| m_port_op.def.nBufferSize = p_handle->size; |
| |
| p_buffer_mapped = ion_map(p_handle->fd,p_handle->size); |
| |
| if (p_buffer_mapped == MAP_FAILED) |
| { |
| OMX_SWVDEC_LOG_ERROR("mmap() failed for fd %d of size %d", |
| p_handle->fd, |
| p_handle->size); |
| |
| retval = OMX_ErrorInsufficientResources; |
| goto buffer_use_op_exit; |
| } |
| |
| p_buffer_payload->bufferaddr = p_buffer_mapped; |
| p_buffer_payload->pmem_fd = p_handle->fd; |
| p_buffer_payload->buffer_len = p_handle->size; |
| p_buffer_payload->mmaped_size = p_handle->size; |
| p_buffer_payload->offset = 0; |
| |
| p_buffer_swvdec->p_buffer = p_buffer_mapped; |
| p_buffer_swvdec->size = m_port_op.def.nBufferSize; |
| p_buffer_swvdec->p_client_data = (void *) ((unsigned long) ii); |
| p_buffer_swvdec->fd = p_buffer_payload->pmem_fd ; |
| |
| if(m_swvdec_codec == SWVDEC_CODEC_VC1) |
| { |
| OMX_SWVDEC_LOG_LOW("map op buffer"); |
| |
| if((retval_swvdec = swvdec_map(m_swvdec_handle,p_buffer_swvdec)) != SWVDEC_STATUS_SUCCESS) |
| { |
| OMX_SWVDEC_LOG_ERROR("swvdec_map failed for op buffer %d: %p",ii,p_buffer_mapped); |
| retval = retval_swvdec2omx(retval_swvdec);; |
| goto buffer_use_op_exit; |
| } |
| } |
| m_buffer_array_op[ii].buffer_populated = true; |
| |
| (*pp_buffer_hdr)->pBuffer = (m_android_native_buffers ? |
| ((OMX_U8 *) p_handle) : |
| p_buffer_mapped); |
| (*pp_buffer_hdr)->pAppPrivate = p_app_data; |
| (*pp_buffer_hdr)->nAllocLen = m_port_op.def.nBufferSize; |
| |
| m_buffer_array_op[ii].ion_info.data_fd = p_handle->fd; |
| |
| OMX_SWVDEC_LOG_HIGH("op buffer %d: %p", |
| ii, |
| *pp_buffer_hdr); |
| |
| m_port_op.populated = port_op_populated(); |
| m_port_op.unpopulated = OMX_FALSE; |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("neither 'meta buffer mode' nor " |
| "'android native buffers' enabled"); |
| |
| retval = OMX_ErrorBadParameter; |
| } |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("all %d op buffers populated", |
| m_port_op.def.nBufferCountActual); |
| |
| retval = OMX_ErrorInsufficientResources; |
| } |
| |
| buffer_use_op_exit: |
| return retval; |
| } |
| |
| /** |
| * @brief De-allocate input buffer. |
| * |
| * @param[in] p_buffer_hdr: Pointer to buffer header structure. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::buffer_deallocate_ip( |
| OMX_BUFFERHEADERTYPE *p_buffer_hdr) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| SWVDEC_STATUS retval_swvdec = SWVDEC_STATUS_SUCCESS; |
| |
| unsigned int ii; |
| |
| if (p_buffer_hdr == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL"); |
| |
| retval = OMX_ErrorBadParameter; |
| goto buffer_deallocate_ip_exit; |
| } |
| else if (m_buffer_array_ip == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("ip buffer array not allocated"); |
| |
| retval = OMX_ErrorBadParameter; |
| goto buffer_deallocate_ip_exit; |
| } |
| |
| for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++) |
| { |
| if (p_buffer_hdr == &(m_buffer_array_ip[ii].buffer_header)) |
| { |
| OMX_SWVDEC_LOG_LOW("%p has index %d", |
| p_buffer_hdr->pBuffer, |
| ii); |
| break; |
| } |
| } |
| |
| if (ii < m_port_ip.def.nBufferCountActual) |
| { |
| if (m_buffer_array_ip[ii].buffer_payload.pmem_fd > 0) |
| { |
| |
| if(m_swvdec_codec == SWVDEC_CODEC_VC1) |
| { |
| SWVDEC_BUFFER *p_buffer_swvdec; |
| p_buffer_swvdec = &m_buffer_array_ip[ii].buffer_swvdec; |
| OMX_SWVDEC_LOG_LOW("unmap ip buffer"); |
| |
| if((retval_swvdec = swvdec_unregister_buffer(m_swvdec_handle,p_buffer_swvdec)) |
| != SWVDEC_STATUS_SUCCESS) |
| { |
| OMX_SWVDEC_LOG_ERROR("swvdec_unmap failed for ip buffer %d: %p", |
| ii,p_buffer_swvdec->p_buffer); |
| retval = retval_swvdec2omx(retval_swvdec);; |
| } |
| } |
| |
| m_buffer_array_ip[ii].buffer_populated = false; |
| |
| m_port_ip.populated = OMX_FALSE; |
| |
| ion_unmap(m_buffer_array_ip[ii].buffer_payload.pmem_fd, |
| m_buffer_array_ip[ii].buffer_payload.bufferaddr, |
| m_buffer_array_ip[ii].buffer_payload.mmaped_size); |
| |
| close(m_buffer_array_ip[ii].buffer_payload.pmem_fd); |
| m_buffer_array_ip[ii].buffer_payload.pmem_fd = -1; |
| |
| ion_memory_free(&m_buffer_array_ip[ii].ion_info); |
| |
| for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++) |
| { |
| if (m_buffer_array_ip[ii].buffer_populated) |
| { |
| break; |
| } |
| } |
| |
| if (ii == m_port_ip.def.nBufferCountActual) |
| { |
| buffer_deallocate_ip_info_array(); |
| |
| m_port_ip.unpopulated = OMX_TRUE; |
| } |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("%p: pmem_fd %d", |
| p_buffer_hdr->pBuffer, |
| m_buffer_array_ip[ii].buffer_payload.pmem_fd); |
| } |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("%p not found", p_buffer_hdr->pBuffer); |
| |
| retval = OMX_ErrorBadParameter; |
| } |
| |
| buffer_deallocate_ip_exit: |
| return retval; |
| } |
| |
| /** |
| * @brief De-allocate output buffer. |
| * |
| * @param[in] p_buffer_hdr: Pointer to buffer header structure. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::buffer_deallocate_op( |
| OMX_BUFFERHEADERTYPE *p_buffer_hdr) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| SWVDEC_STATUS retval_swvdec = SWVDEC_STATUS_SUCCESS; |
| unsigned int ii; |
| |
| if (p_buffer_hdr == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_buffer_hdr = NULL"); |
| |
| retval = OMX_ErrorBadParameter; |
| goto buffer_deallocate_op_exit; |
| } |
| else if (m_buffer_array_op == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("op buffer array not allocated"); |
| |
| retval = OMX_ErrorBadParameter; |
| goto buffer_deallocate_op_exit; |
| } |
| |
| for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++) |
| { |
| if (p_buffer_hdr == &(m_buffer_array_op[ii].buffer_header)) |
| { |
| OMX_SWVDEC_LOG_LOW("%p has index %d", |
| p_buffer_hdr->pBuffer, |
| ii); |
| break; |
| } |
| } |
| |
| if (ii < m_port_op.def.nBufferCountActual) |
| { |
| if (m_meta_buffer_mode) |
| { |
| // do nothing; munmap() & FD reset done in FBD or RR |
| } |
| else if (m_android_native_buffers) |
| { |
| |
| if(m_swvdec_codec == SWVDEC_CODEC_VC1) |
| { |
| SWVDEC_BUFFER *p_buffer_swvdec; |
| p_buffer_swvdec = &m_buffer_array_op[ii].buffer_swvdec; |
| OMX_SWVDEC_LOG_LOW("unmap op buffer"); |
| |
| if((retval_swvdec = swvdec_unmap(m_swvdec_handle,p_buffer_swvdec)) != SWVDEC_STATUS_SUCCESS) |
| { |
| OMX_SWVDEC_LOG_ERROR("swvdec_unmap failed for op buffer %d: %p",ii,p_buffer_swvdec->p_buffer); |
| retval = retval_swvdec2omx(retval_swvdec);; |
| } |
| } |
| ion_unmap(m_buffer_array_op[ii].buffer_payload.pmem_fd , |
| m_buffer_array_op[ii].buffer_payload.bufferaddr, |
| m_buffer_array_op[ii].buffer_payload.mmaped_size); |
| |
| m_buffer_array_op[ii].buffer_payload.pmem_fd = -1; |
| } |
| else |
| { |
| if(m_swvdec_codec == SWVDEC_CODEC_VC1) |
| { |
| SWVDEC_BUFFER *p_buffer_swvdec; |
| p_buffer_swvdec = &m_buffer_array_op[ii].buffer_swvdec; |
| OMX_SWVDEC_LOG_LOW("unmap op buffer"); |
| |
| if((retval_swvdec = swvdec_unmap(m_swvdec_handle,p_buffer_swvdec)) != SWVDEC_STATUS_SUCCESS) |
| { |
| OMX_SWVDEC_LOG_ERROR("swvdec_unmap failed for op buffer %d: %p",ii,p_buffer_swvdec->p_buffer); |
| retval = retval_swvdec2omx(retval_swvdec);; |
| } |
| } |
| ion_unmap(m_buffer_array_op[ii].buffer_payload.pmem_fd, |
| m_buffer_array_op[ii].buffer_payload.bufferaddr, |
| m_buffer_array_op[ii].buffer_payload.mmaped_size); |
| |
| close(m_buffer_array_op[ii].buffer_payload.pmem_fd); |
| |
| m_buffer_array_op[ii].buffer_payload.pmem_fd = -1; |
| |
| ion_memory_free(&m_buffer_array_op[ii].ion_info); |
| } |
| |
| m_buffer_array_op[ii].buffer_populated = false; |
| |
| m_port_op.populated = OMX_FALSE; |
| |
| for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++) |
| { |
| if (m_buffer_array_op[ii].buffer_populated) |
| { |
| break; |
| } |
| } |
| |
| if (ii == m_port_op.def.nBufferCountActual) |
| { |
| buffer_deallocate_op_info_array(); |
| |
| m_port_op.unpopulated = OMX_TRUE; |
| |
| if (m_meta_buffer_mode) |
| { |
| meta_buffer_array_deallocate(); |
| } |
| } |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("%p not found", p_buffer_hdr->pBuffer); |
| |
| retval = OMX_ErrorBadParameter; |
| } |
| |
| buffer_deallocate_op_exit: |
| return retval; |
| } |
| |
| /** |
| * @brief De-allocate input buffer info array. |
| */ |
| void omx_swvdec::buffer_deallocate_ip_info_array() |
| { |
| assert(m_buffer_array_ip != NULL); |
| |
| free(m_buffer_array_ip); |
| |
| m_buffer_array_ip = NULL; |
| } |
| |
| /** |
| * @brief De-allocate output buffer info array. |
| */ |
| void omx_swvdec::buffer_deallocate_op_info_array() |
| { |
| assert(m_buffer_array_op != NULL); |
| |
| free(m_buffer_array_op); |
| |
| m_buffer_array_op = NULL; |
| } |
| |
| /** |
| * @brief Allocate meta buffer info array. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::meta_buffer_array_allocate() |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| m_meta_buffer_array = ((OMX_SWVDEC_META_BUFFER_INFO *) |
| calloc(sizeof(OMX_SWVDEC_META_BUFFER_INFO), |
| m_port_op.def.nBufferCountActual)); |
| |
| if (m_meta_buffer_array == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("failed to allocate meta_buffer info array; " |
| "%d element%s, %zu bytes requested", |
| m_port_op.def.nBufferCountActual, |
| (m_port_op.def.nBufferCountActual > 1) ? "s" : "", |
| sizeof(OMX_SWVDEC_META_BUFFER_INFO) * |
| m_port_op.def.nBufferCountActual); |
| |
| retval = OMX_ErrorInsufficientResources; |
| } |
| else |
| { |
| unsigned int ii; |
| |
| for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++) |
| { |
| m_meta_buffer_array[ii].fd = -1; |
| } |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief De-allocate meta buffer info array. |
| */ |
| void omx_swvdec::meta_buffer_array_deallocate() |
| { |
| assert(m_meta_buffer_array != NULL); |
| |
| free(m_meta_buffer_array); |
| |
| m_meta_buffer_array = NULL; |
| } |
| |
| /** |
| * @brief Add meta buffer reference. |
| * |
| * @param[in] index: Buffer index. |
| * @param[in] fd: File descriptor. |
| */ |
| void omx_swvdec::meta_buffer_ref_add(unsigned int index, int fd) |
| { |
| if (m_meta_buffer_array[index].ref_count == 0) |
| { |
| m_meta_buffer_array[index].fd = fd; |
| } |
| |
| m_meta_buffer_array[index].ref_count++; |
| } |
| |
| /** |
| * @brief Remove meta buffer reference. |
| * |
| * @param[in] index: Buffer index. |
| */ |
| void omx_swvdec::meta_buffer_ref_remove(unsigned int index) |
| { |
| pthread_mutex_lock(&m_meta_buffer_array_mutex); |
| |
| m_meta_buffer_array[index].ref_count--; |
| |
| if (m_meta_buffer_array[index].ref_count == 0) |
| { |
| ion_unmap(m_meta_buffer_array[index].fd, |
| m_buffer_array_op[index].buffer_payload.bufferaddr, |
| m_buffer_array_op[index].buffer_payload.mmaped_size); |
| |
| m_meta_buffer_array[index].fd = -1; |
| m_buffer_array_op[index].buffer_payload.bufferaddr = NULL; |
| m_buffer_array_op[index].buffer_payload.offset = 0; |
| m_buffer_array_op[index].buffer_payload.mmaped_size = 0; |
| |
| m_buffer_array_op[index].buffer_swvdec.p_buffer = NULL; |
| m_buffer_array_op[index].buffer_swvdec.size = 0; |
| } |
| |
| pthread_mutex_unlock(&m_meta_buffer_array_mutex); |
| } |
| |
| /** |
| * @brief Split MPEG-4 bitstream buffer into multiple frames (if they exist). |
| * |
| * @param[in,out] offset_array: Array of offsets to frame headers. |
| * @param[in] p_buffer_hdr: Pointer to buffer header. |
| * |
| * @retval Number of frames in buffer. |
| */ |
| unsigned int split_buffer_mpeg4(unsigned int *offset_array, |
| OMX_BUFFERHEADERTYPE *p_buffer_hdr) |
| { |
| unsigned char *p_buffer = p_buffer_hdr->pBuffer; |
| |
| unsigned int byte_count = 0; |
| |
| unsigned int num_frame_headers = 0; |
| |
| unsigned int next_4bytes; |
| |
| while ((byte_count < p_buffer_hdr->nFilledLen) && |
| (num_frame_headers < OMX_SWVDEC_MAX_FRAMES_PER_ETB)) |
| { |
| next_4bytes = *((unsigned int *) p_buffer); |
| |
| next_4bytes = __builtin_bswap32(next_4bytes); |
| |
| if (next_4bytes == 0x000001B6) |
| { |
| OMX_SWVDEC_LOG_HIGH("%p, buffer %p: " |
| "frame header at %d bytes offset", |
| p_buffer_hdr, |
| p_buffer_hdr->pBuffer, |
| byte_count); |
| |
| offset_array[num_frame_headers] = byte_count; |
| |
| num_frame_headers++; |
| |
| p_buffer += 4; |
| byte_count += 4; |
| } |
| else |
| { |
| p_buffer++; |
| byte_count++; |
| } |
| } |
| |
| return num_frame_headers; |
| } |
| |
| /** |
| * @brief Check if ip port is populated, i.e., if all ip buffers are populated. |
| * |
| * @retval true |
| * @retval false |
| */ |
| OMX_BOOL omx_swvdec::port_ip_populated() |
| { |
| OMX_BOOL retval = OMX_FALSE; |
| |
| if (m_buffer_array_ip != NULL) |
| { |
| unsigned int ii; |
| |
| for (ii = 0; ii < m_port_ip.def.nBufferCountActual; ii++) |
| { |
| if (m_buffer_array_ip[ii].buffer_populated == false) |
| { |
| break; |
| } |
| } |
| |
| if (ii == m_port_ip.def.nBufferCountActual) |
| { |
| retval = OMX_TRUE; |
| } |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Check if op port is populated, i.e., if all op buffers are populated. |
| * |
| * @retval true |
| * @retval false |
| */ |
| OMX_BOOL omx_swvdec::port_op_populated() |
| { |
| OMX_BOOL retval = OMX_FALSE; |
| |
| if (m_buffer_array_op != NULL) |
| { |
| unsigned int ii; |
| |
| for (ii = 0; ii < m_port_op.def.nBufferCountActual; ii++) |
| { |
| if (m_buffer_array_op[ii].buffer_populated == false) |
| { |
| break; |
| } |
| } |
| |
| if (ii == m_port_op.def.nBufferCountActual) |
| { |
| retval = OMX_TRUE; |
| } |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Flush input, output, or both input & output ports. |
| * |
| * @param[in] port_index: Index of port to flush. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::flush(unsigned int port_index) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| if (((port_index == OMX_CORE_PORT_INDEX_IP) && |
| m_port_ip.flush_inprogress) || |
| ((port_index == OMX_CORE_PORT_INDEX_OP) && |
| m_port_op.flush_inprogress) || |
| ((port_index == OMX_ALL) && |
| m_port_ip.flush_inprogress && |
| m_port_op.flush_inprogress)) |
| { |
| OMX_SWVDEC_LOG_HIGH("flush port index %d already in progress", |
| port_index); |
| } |
| else |
| { |
| SWVDEC_FLUSH_TYPE swvdec_flush_type; |
| |
| SWVDEC_STATUS retval_swvdec; |
| |
| if (port_index == OMX_CORE_PORT_INDEX_IP) |
| { |
| m_port_ip.flush_inprogress = OMX_TRUE; |
| |
| //for VTS test case IP flush , trigger flush all |
| // for IP flush, similar behavior is for hwcodecs |
| m_port_ip.flush_inprogress = OMX_TRUE; |
| m_port_op.flush_inprogress = OMX_TRUE; |
| |
| swvdec_flush_type = SWVDEC_FLUSH_TYPE_ALL; |
| |
| if ((retval_swvdec = swvdec_flush(m_swvdec_handle, |
| swvdec_flush_type)) != |
| SWVDEC_STATUS_SUCCESS) |
| { |
| retval = retval_swvdec2omx(retval_swvdec); |
| } |
| } |
| else if (port_index == OMX_CORE_PORT_INDEX_OP) |
| { |
| m_port_op.flush_inprogress = OMX_TRUE; |
| |
| swvdec_flush_type = (m_port_ip.flush_inprogress ? |
| SWVDEC_FLUSH_TYPE_ALL : |
| SWVDEC_FLUSH_TYPE_OP); |
| |
| if ((retval_swvdec = swvdec_flush(m_swvdec_handle, |
| swvdec_flush_type)) != |
| SWVDEC_STATUS_SUCCESS) |
| { |
| retval = retval_swvdec2omx(retval_swvdec); |
| } |
| } |
| else if (port_index == OMX_ALL) |
| { |
| m_port_ip.flush_inprogress = OMX_TRUE; |
| m_port_op.flush_inprogress = OMX_TRUE; |
| |
| swvdec_flush_type = SWVDEC_FLUSH_TYPE_ALL; |
| |
| if ((retval_swvdec = swvdec_flush(m_swvdec_handle, |
| swvdec_flush_type)) != |
| SWVDEC_STATUS_SUCCESS) |
| { |
| retval = retval_swvdec2omx(retval_swvdec); |
| } |
| } |
| else |
| { |
| assert(0); |
| } |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Allocate & map ION memory. |
| */ |
| int omx_swvdec::ion_memory_alloc_map(vdec_ion *p_ion_info, OMX_U32 size, OMX_U32 alignment) |
| { |
| int rc = -EINVAL; |
| |
| if((!p_ion_info) || (size == 0)) |
| { |
| OMX_SWVDEC_LOG_ERROR("invalid arguments"); |
| goto ion_memory_alloc_map_exit; |
| } |
| |
| p_ion_info->dev_fd = -EINVAL; |
| |
| if ((p_ion_info->dev_fd = ion_open()) < 0) |
| { |
| OMX_SWVDEC_LOG_ERROR("failed to open ion device; fd = %d", p_ion_info->dev_fd); |
| goto ion_memory_alloc_map_exit; |
| } |
| |
| p_ion_info->alloc_data.len = size; |
| p_ion_info->alloc_data.heap_id_mask = ION_HEAP(ION_SYSTEM_HEAP_ID); |
| p_ion_info->alloc_data.flags = 0;//check if ION_FLAG_CACHED need to be set; |
| alignment = ALIGN(alignment,4096); |
| |
| OMX_SWVDEC_LOG_LOW("heap_id_mask 0x%08x, len %zu", |
| p_ion_info->alloc_data.heap_id_mask, |
| p_ion_info->alloc_data.len); |
| |
| rc = ion_alloc_fd(p_ion_info->dev_fd, p_ion_info->alloc_data.len, alignment, |
| p_ion_info->alloc_data.heap_id_mask, p_ion_info->alloc_data.flags, |
| &p_ion_info->data_fd); |
| |
| if (rc || p_ion_info->data_fd == 0) |
| { |
| OMX_SWVDEC_LOG_ERROR("ion_alloc_fd() for allocation failed"); |
| ion_close(p_ion_info->dev_fd); |
| p_ion_info->data_fd = -1; |
| p_ion_info->dev_fd = -1; |
| goto ion_memory_alloc_map_exit; |
| } |
| |
| |
| OMX_SWVDEC_LOG_HIGH("Alloc ion memory: fd (dev:%d data:%d) len %d flags %#x mask %#x", |
| p_ion_info->dev_fd, p_ion_info->data_fd, (unsigned int)p_ion_info->alloc_data.len, |
| (unsigned int)p_ion_info->alloc_data.flags, |
| (unsigned int)p_ion_info->alloc_data.heap_id_mask); |
| |
| ion_memory_alloc_map_exit: |
| return (p_ion_info == nullptr) ? -EINVAL : p_ion_info->dev_fd; |
| } |
| |
| /** |
| * @brief Free ION memory. |
| */ |
| void omx_swvdec::ion_memory_free(struct vdec_ion *p_ion_buf_info) |
| { |
| if (p_ion_buf_info == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_ion_buf_info = NULL"); |
| goto ion_memory_free_exit; |
| } |
| |
| OMX_SWVDEC_LOG_HIGH("Free ion memory: map fd %d ion_dev fd %d len %d flags %#x mask %#x", |
| p_ion_buf_info->data_fd, p_ion_buf_info->dev_fd, |
| (unsigned int)p_ion_buf_info->alloc_data.len, |
| (unsigned int)p_ion_buf_info->alloc_data.flags, |
| (unsigned int)p_ion_buf_info->alloc_data.heap_id_mask); |
| |
| if (p_ion_buf_info->data_fd >= 0) { |
| p_ion_buf_info->data_fd = -1; |
| } |
| |
| if (p_ion_buf_info->dev_fd >= 0) { |
| ion_close(p_ion_buf_info->dev_fd); |
| p_ion_buf_info->dev_fd = -1; |
| } |
| |
| ion_memory_free_exit: |
| return; |
| } |
| |
| /** |
| * @brief Flush cached ION output buffer. |
| * |
| * @param[in] index: Index of buffer in output buffer info array. |
| */ |
| void omx_swvdec::ion_flush_op(unsigned int index) |
| { |
| if (index < m_port_op.def.nBufferCountActual) |
| { |
| #ifdef USE_ION |
| struct dma_buf_sync dma_buf_sync_data[2]; |
| dma_buf_sync_data[0].flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_WRITE; |
| dma_buf_sync_data[1].flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_WRITE; |
| |
| for (unsigned int i=0; i<2; i++) |
| { |
| int ret = ioctl(m_buffer_array_op[index].buffer_swvdec.fd, |
| DMA_BUF_IOCTL_SYNC, &dma_buf_sync_data[i]); |
| if (ret < 0) |
| { |
| OMX_SWVDEC_LOG_ERROR("Cache %s failed for fd %d : %s\n", |
| (i==0) ? "START" : "END", |
| m_buffer_array_op[index].buffer_swvdec.fd, |
| strerror(errno)); |
| goto ion_flush_op_exit; |
| } |
| } |
| #endif |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("buffer index '%d' invalid", index); |
| } |
| |
| ion_flush_op_exit: |
| return; |
| } |
| |
| |
| /** |
| * ---------------------------- |
| * component callback functions |
| * ---------------------------- |
| */ |
| |
| /** |
| * @brief Empty buffer done callback. |
| * |
| * @param[in] p_buffer_ip: Pointer to input buffer structure. |
| */ |
| void omx_swvdec::swvdec_empty_buffer_done(SWVDEC_BUFFER *p_buffer_ip) |
| { |
| unsigned long index = (unsigned long) p_buffer_ip->p_client_data; |
| |
| m_buffer_array_ip[index].buffer_header.nFilledLen = |
| p_buffer_ip->filled_length; |
| |
| async_post_event(OMX_SWVDEC_EVENT_EBD, |
| (unsigned long) &m_buffer_array_ip[index].buffer_header, |
| index); |
| } |
| |
| /** |
| * @brief Fill buffer done callback. |
| * |
| * @param[in] p_buffer_op: Pointer to output buffer structure. |
| */ |
| void omx_swvdec::swvdec_fill_buffer_done(SWVDEC_BUFFER *p_buffer_op) |
| { |
| unsigned long index = (unsigned long) p_buffer_op->p_client_data; |
| |
| OMX_BUFFERHEADERTYPE *p_buffer_hdr; |
| |
| if (index < ((unsigned long) m_port_op.def.nBufferCountActual)) |
| { |
| p_buffer_hdr = &m_buffer_array_op[index].buffer_header; |
| |
| p_buffer_hdr->nFlags = p_buffer_op->flags; |
| p_buffer_hdr->nTimeStamp = p_buffer_op->timestamp; |
| p_buffer_hdr->nFilledLen = ((m_meta_buffer_mode && |
| p_buffer_op->filled_length) ? |
| p_buffer_hdr->nAllocLen : |
| p_buffer_op->filled_length); |
| } |
| |
| async_post_event(OMX_SWVDEC_EVENT_FBD, |
| (unsigned long) &m_buffer_array_op[index].buffer_header, |
| index); |
| } |
| |
| /** |
| * @brief Event handler callback. |
| * |
| * @param[in] event: Event. |
| * @param[in] p_data: Pointer to event-specific data. |
| */ |
| void omx_swvdec::swvdec_event_handler(SWVDEC_EVENT event, void *p_data) |
| { |
| switch (event) |
| { |
| |
| case SWVDEC_EVENT_FLUSH_ALL_DONE: |
| { |
| async_post_event(OMX_SWVDEC_EVENT_FLUSH_PORT_IP, 0, 0); |
| async_post_event(OMX_SWVDEC_EVENT_FLUSH_PORT_OP, 0, 0); |
| |
| break; |
| } |
| |
| case SWVDEC_EVENT_FLUSH_OP_DONE: |
| { |
| async_post_event(OMX_SWVDEC_EVENT_FLUSH_PORT_OP, 0, 0); |
| |
| break; |
| } |
| |
| case SWVDEC_EVENT_RELEASE_REFERENCE: |
| { |
| SWVDEC_BUFFER *p_buffer_op = (SWVDEC_BUFFER *) p_data; |
| |
| unsigned long index = (unsigned long) p_buffer_op->p_client_data; |
| |
| OMX_SWVDEC_LOG_LOW("release reference: %p", p_buffer_op->p_buffer); |
| |
| assert(index < ((unsigned long) m_port_op.def.nBufferCountActual)); |
| |
| if (m_meta_buffer_mode) |
| { |
| meta_buffer_ref_remove(index); |
| } |
| |
| break; |
| } |
| |
| case SWVDEC_EVENT_RECONFIG_REQUIRED: |
| { |
| async_post_event(OMX_SWVDEC_EVENT_PORT_RECONFIG, 0, 0); |
| |
| break; |
| } |
| |
| case SWVDEC_EVENT_DIMENSIONS_UPDATED: |
| { |
| async_post_event(OMX_SWVDEC_EVENT_DIMENSIONS_UPDATED, 0, 0); |
| |
| break; |
| } |
| |
| case SWVDEC_EVENT_FATAL_ERROR: |
| default: |
| { |
| async_post_event(OMX_SWVDEC_EVENT_ERROR, OMX_ErrorHardware, 0); |
| |
| break; |
| } |
| |
| } |
| } |
| |
| /** |
| * @brief Translate SwVdec status return value to OMX error type return value. |
| * |
| * @param[in] retval_swvdec: SwVdec status return value. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::retval_swvdec2omx(SWVDEC_STATUS retval_swvdec) |
| { |
| OMX_ERRORTYPE retval_omx; |
| |
| switch (retval_swvdec) { |
| case SWVDEC_STATUS_SUCCESS: |
| retval_omx = OMX_ErrorNone; |
| break; |
| |
| case SWVDEC_STATUS_FAILURE: |
| retval_omx = OMX_ErrorUndefined; |
| break; |
| |
| case SWVDEC_STATUS_NULL_POINTER: |
| case SWVDEC_STATUS_INVALID_PARAMETERS: |
| retval_omx = OMX_ErrorBadParameter; |
| break; |
| |
| case SWVDEC_STATUS_INVALID_STATE: |
| retval_omx = OMX_ErrorInvalidState; |
| break; |
| |
| case SWVDEC_STATUS_INSUFFICIENT_RESOURCES: |
| retval_omx = OMX_ErrorInsufficientResources; |
| break; |
| |
| case SWVDEC_STATUS_UNSUPPORTED: |
| retval_omx = OMX_ErrorUnsupportedSetting; |
| break; |
| |
| case SWVDEC_STATUS_NOT_IMPLEMENTED: |
| retval_omx = OMX_ErrorNotImplemented; |
| break; |
| |
| default: |
| retval_omx = OMX_ErrorUndefined; |
| break; |
| } |
| |
| return retval_omx; |
| } |
| |
| /** |
| * @brief Create asynchronous thread. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::async_thread_create() |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| pthread_attr_t thread_attributes; |
| |
| if (sem_init(&m_async_thread.sem_thread_created, 0, 0)) |
| { |
| OMX_SWVDEC_LOG_ERROR("failed to create async thread created semaphore"); |
| |
| retval = OMX_ErrorInsufficientResources; |
| } |
| else if (sem_init(&m_async_thread.sem_event, 0, 0)) |
| { |
| OMX_SWVDEC_LOG_ERROR("failed to create async thread event semaphore"); |
| |
| retval = OMX_ErrorInsufficientResources; |
| } |
| else if (pthread_attr_init(&thread_attributes)) |
| { |
| OMX_SWVDEC_LOG_ERROR("failed to create thread attributes object"); |
| |
| retval = OMX_ErrorInsufficientResources; |
| } |
| else if (pthread_attr_setdetachstate(&thread_attributes, |
| PTHREAD_CREATE_JOINABLE)) |
| { |
| OMX_SWVDEC_LOG_ERROR("failed to set detach state attribute"); |
| |
| retval = OMX_ErrorInsufficientResources; |
| |
| pthread_attr_destroy(&thread_attributes); |
| } |
| else |
| { |
| m_async_thread.created = false; |
| m_async_thread.exit = false; |
| |
| if (pthread_create(&m_async_thread.handle, |
| &thread_attributes, |
| (void *(*)(void *)) async_thread, |
| this)) |
| { |
| OMX_SWVDEC_LOG_ERROR("failed to create async thread"); |
| |
| retval = OMX_ErrorInsufficientResources; |
| |
| pthread_attr_destroy(&thread_attributes); |
| } |
| else |
| { |
| if (pthread_setname_np(m_async_thread.handle, "swvdec_async")) |
| { |
| // don't return error |
| OMX_SWVDEC_LOG_ERROR("failed to set async thread name"); |
| } |
| |
| sem_wait(&m_async_thread.sem_thread_created); |
| |
| m_async_thread.created = true; |
| } |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Destroy asynchronous thread. |
| */ |
| void omx_swvdec::async_thread_destroy() |
| { |
| if (m_async_thread.created) |
| { |
| m_async_thread.exit = true; |
| |
| sem_post(&m_async_thread.sem_event); |
| |
| pthread_join(m_async_thread.handle, NULL); |
| |
| m_async_thread.created = false; |
| } |
| |
| m_async_thread.exit = false; |
| |
| sem_destroy(&m_async_thread.sem_event); |
| sem_destroy(&m_async_thread.sem_thread_created); |
| } |
| |
| /** |
| * @brief Post event to appropriate queue. |
| * |
| * @param[in] event_id: Event ID. |
| * @param[in] event_param1: Event parameter 1. |
| * @param[in] event_param2: Event parameter 2. |
| */ |
| void omx_swvdec::async_post_event(unsigned long event_id, |
| unsigned long event_param1, |
| unsigned long event_param2) |
| { |
| OMX_SWVDEC_EVENT_INFO event_info; |
| |
| event_info.event_id = event_id; |
| event_info.event_param1 = event_param1; |
| event_info.event_param2 = event_param2; |
| |
| switch (event_id) |
| { |
| |
| case OMX_SWVDEC_EVENT_ETB: |
| case OMX_SWVDEC_EVENT_EBD: |
| { |
| m_queue_port_ip.push(&event_info); |
| break; |
| } |
| |
| case OMX_SWVDEC_EVENT_FTB: |
| case OMX_SWVDEC_EVENT_FBD: |
| { |
| m_queue_port_op.push(&event_info); |
| break; |
| } |
| |
| default: |
| { |
| m_queue_command.push(&event_info); |
| break; |
| } |
| |
| } |
| |
| sem_post(&m_async_thread.sem_event); |
| } |
| |
| /** |
| * @brief Asynchronous thread. |
| * |
| * @param[in] p_cmp: Pointer to OMX SwVdec component class. |
| */ |
| void omx_swvdec::async_thread(void *p_cmp) |
| { |
| if (p_cmp == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_cmp = NULL"); |
| } |
| else |
| { |
| omx_swvdec *p_omx_swvdec = (omx_swvdec *) p_cmp; |
| |
| ASYNC_THREAD *p_async_thread = &p_omx_swvdec->m_async_thread; |
| |
| OMX_SWVDEC_LOG_HIGH("created"); |
| |
| sem_post(&p_async_thread->sem_thread_created); |
| |
| while (p_async_thread->exit == false) |
| { |
| sem_wait(&p_async_thread->sem_event); |
| |
| if (p_async_thread->exit == true) |
| { |
| break; |
| } |
| |
| p_omx_swvdec->async_process_event(p_cmp); |
| } |
| } |
| |
| OMX_SWVDEC_LOG_HIGH("exiting"); |
| } |
| |
| /** |
| * @brief Process event. |
| * |
| * @param[in] p_cmp: Pointer to OMX SwVdec component class. |
| */ |
| void omx_swvdec::async_process_event(void *p_cmp) |
| { |
| omx_swvdec *p_omx_swvdec; |
| |
| OMX_SWVDEC_EVENT_INFO event_info; |
| |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| if (p_cmp == NULL) |
| { |
| OMX_SWVDEC_LOG_ERROR("p_cmp = NULL"); |
| |
| goto async_process_event_exit; |
| } |
| |
| p_omx_swvdec = (omx_swvdec *) p_cmp; |
| |
| // NOTE: queues popped in order of priority; do not change! |
| |
| if ((p_omx_swvdec->m_queue_command.pop(&event_info) == false) && |
| (p_omx_swvdec->m_queue_port_op.pop(&event_info) == false) && |
| (p_omx_swvdec->m_queue_port_ip.pop(&event_info) == false)) |
| { |
| OMX_SWVDEC_LOG_LOW("no event popped"); |
| |
| goto async_process_event_exit; |
| } |
| |
| switch (event_info.event_id) |
| { |
| |
| case OMX_SWVDEC_EVENT_CMD: |
| { |
| OMX_COMMANDTYPE cmd = (OMX_COMMANDTYPE) event_info.event_param1; |
| OMX_U32 param = (OMX_U32) event_info.event_param2; |
| |
| retval = p_omx_swvdec->async_process_event_cmd(cmd, param); |
| break; |
| } |
| |
| case OMX_SWVDEC_EVENT_CMD_ACK: |
| { |
| OMX_COMMANDTYPE cmd = (OMX_COMMANDTYPE) event_info.event_param1; |
| OMX_U32 param = (OMX_U32) event_info.event_param2; |
| |
| retval = p_omx_swvdec->async_process_event_cmd_ack(cmd, param); |
| break; |
| } |
| |
| case OMX_SWVDEC_EVENT_ERROR: |
| { |
| OMX_ERRORTYPE error_code = (OMX_ERRORTYPE) event_info.event_param1; |
| |
| retval = p_omx_swvdec->async_process_event_error(error_code); |
| break; |
| } |
| |
| case OMX_SWVDEC_EVENT_ETB: |
| { |
| OMX_BUFFERHEADERTYPE *p_buffer_hdr = |
| (OMX_BUFFERHEADERTYPE *) event_info.event_param1; |
| |
| unsigned int index = event_info.event_param2; |
| |
| retval = p_omx_swvdec->async_process_event_etb(p_buffer_hdr, index); |
| break; |
| } |
| |
| case OMX_SWVDEC_EVENT_FTB: |
| { |
| OMX_BUFFERHEADERTYPE *p_buffer_hdr = |
| (OMX_BUFFERHEADERTYPE *) event_info.event_param1; |
| |
| unsigned int index = event_info.event_param2; |
| |
| retval = p_omx_swvdec->async_process_event_ftb(p_buffer_hdr, index); |
| break; |
| } |
| |
| case OMX_SWVDEC_EVENT_EBD: |
| { |
| OMX_BUFFERHEADERTYPE *p_buffer_hdr = |
| (OMX_BUFFERHEADERTYPE *) event_info.event_param1; |
| |
| unsigned int index = event_info.event_param2; |
| |
| retval = p_omx_swvdec->async_process_event_ebd(p_buffer_hdr, index); |
| break; |
| } |
| |
| case OMX_SWVDEC_EVENT_FBD: |
| { |
| OMX_BUFFERHEADERTYPE *p_buffer_hdr = |
| (OMX_BUFFERHEADERTYPE *) event_info.event_param1; |
| |
| unsigned int index = event_info.event_param2; |
| |
| retval = p_omx_swvdec->async_process_event_fbd(p_buffer_hdr, index); |
| break; |
| } |
| |
| case OMX_SWVDEC_EVENT_EOS: |
| { |
| retval = p_omx_swvdec->async_process_event_eos(); |
| break; |
| } |
| |
| case OMX_SWVDEC_EVENT_FLUSH_PORT_IP: |
| { |
| retval = p_omx_swvdec->async_process_event_flush_port_ip(); |
| break; |
| } |
| |
| case OMX_SWVDEC_EVENT_FLUSH_PORT_OP: |
| { |
| retval = p_omx_swvdec->async_process_event_flush_port_op(); |
| break; |
| } |
| |
| case OMX_SWVDEC_EVENT_PORT_RECONFIG: |
| { |
| retval = p_omx_swvdec->async_process_event_port_reconfig(); |
| break; |
| } |
| |
| case OMX_SWVDEC_EVENT_DIMENSIONS_UPDATED: |
| { |
| retval = p_omx_swvdec->async_process_event_dimensions_updated(); |
| break; |
| } |
| |
| default: |
| { |
| assert(0); |
| |
| retval = OMX_ErrorUndefined; |
| break; |
| } |
| |
| } |
| |
| if (retval != OMX_ErrorNone) |
| { |
| p_omx_swvdec->async_post_event(OMX_SWVDEC_EVENT_ERROR, retval, 0); |
| } |
| |
| async_process_event_exit: |
| return; |
| } |
| |
| /** |
| * @brief Process command event. |
| * |
| * @param[in] cmd: Command. |
| * @param[in] param: Command parameter. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::async_process_event_cmd(OMX_COMMANDTYPE cmd, |
| OMX_U32 param) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| bool cmd_ack = false; |
| |
| switch (cmd) |
| { |
| |
| case OMX_CommandStateSet: |
| { |
| retval = async_process_event_cmd_state_set(&cmd_ack, |
| (OMX_STATETYPE) param); |
| break; |
| } |
| |
| case OMX_CommandFlush: |
| { |
| retval = async_process_event_cmd_flush((unsigned int) param); |
| break; |
| } |
| |
| case OMX_CommandPortDisable: |
| { |
| retval = async_process_event_cmd_port_disable(&cmd_ack, |
| (unsigned int) param); |
| break; |
| } |
| |
| case OMX_CommandPortEnable: |
| { |
| retval = async_process_event_cmd_port_enable(&cmd_ack, |
| (unsigned int) param); |
| break; |
| } |
| |
| default: |
| { |
| OMX_SWVDEC_LOG_ERROR("cmd '%d' invalid", (int) cmd); |
| |
| retval = OMX_ErrorBadParameter; |
| break; |
| } |
| |
| } // switch (cmd) |
| |
| if (retval != OMX_ErrorNone) |
| { |
| async_post_event(OMX_SWVDEC_EVENT_ERROR, retval, 0); |
| } |
| else if (cmd_ack) |
| { |
| async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, cmd, param); |
| } |
| |
| sem_post(&m_sem_cmd); |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Process command acknowledgement event. |
| * |
| * @param[in] cmd: Command. |
| * @param[in] param: Command parameter. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_ack(OMX_COMMANDTYPE cmd, |
| OMX_U32 param) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| switch (cmd) |
| { |
| |
| case OMX_CommandStateSet: |
| { |
| OMX_SWVDEC_LOG_HIGH("%s -> %s", |
| OMX_STATETYPE_STRING(m_state), |
| OMX_STATETYPE_STRING((OMX_STATETYPE) param)); |
| |
| m_state = (OMX_STATETYPE) param; |
| |
| OMX_SWVDEC_LOG_CALLBACK("EventHandler(): OMX_EventCmdComplete, " |
| "OMX_CommandStateSet, %s", |
| OMX_STATETYPE_STRING(m_state)); |
| |
| m_callback.EventHandler(&m_cmp, |
| m_app_data, |
| OMX_EventCmdComplete, |
| OMX_CommandStateSet, |
| (OMX_U32) m_state, |
| NULL); |
| break; |
| } |
| |
| case OMX_CommandFlush: |
| case OMX_CommandPortEnable: |
| case OMX_CommandPortDisable: |
| { |
| if ((cmd == OMX_CommandPortEnable) && m_port_reconfig_inprogress) |
| { |
| m_port_reconfig_inprogress = false; |
| } |
| |
| OMX_SWVDEC_LOG_CALLBACK("EventHandler(): OMX_EventCmdComplete, " |
| "%s, port index %d", |
| OMX_COMMANDTYPE_STRING(cmd), |
| param); |
| |
| m_callback.EventHandler(&m_cmp, |
| m_app_data, |
| OMX_EventCmdComplete, |
| cmd, |
| param, |
| NULL); |
| break; |
| } |
| |
| default: |
| { |
| OMX_SWVDEC_LOG_ERROR("cmd '%d' invalid", (int) cmd); |
| |
| retval = OMX_ErrorBadParameter; |
| break; |
| } |
| |
| } // switch (cmd) |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Process error event. |
| * |
| * @param[in] error_code: Error code. |
| * |
| * @retval OMX_ErrorNone |
| */ |
| OMX_ERRORTYPE omx_swvdec::async_process_event_error(OMX_ERRORTYPE error_code) |
| { |
| if (error_code == OMX_ErrorInvalidState) |
| { |
| OMX_SWVDEC_LOG_HIGH("%s -> OMX_StateInvalid", |
| OMX_STATETYPE_STRING(m_state)); |
| |
| m_state = OMX_StateInvalid; |
| } |
| |
| OMX_SWVDEC_LOG_CALLBACK("EventHandler(): OMX_EventError, 0x%08x", |
| error_code); |
| |
| m_callback.EventHandler(&m_cmp, |
| m_app_data, |
| OMX_EventError, |
| (OMX_U32) error_code, |
| 0, |
| NULL); |
| |
| return OMX_ErrorNone; |
| } |
| |
| /** |
| * @brief Process OMX_CommandStateSet. |
| * |
| * @param[in,out] p_cmd_ack: Pointer to 'command acknowledge' boolean variable. |
| * @param[in] state_new: New state to which transition is requested. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_state_set( |
| bool *p_cmd_ack, |
| OMX_STATETYPE state_new) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| SWVDEC_STATUS retval_swvdec; |
| |
| OMX_SWVDEC_LOG_HIGH("'%s-to-%s' requested", |
| OMX_STATETYPE_STRING(m_state), |
| OMX_STATETYPE_STRING(state_new)); |
| |
| /** |
| * Only the following state transitions are allowed via CommandStateSet: |
| * |
| * LOADED -> IDLE -> EXECUTING |
| * LOADED <- IDLE <- EXECUTING |
| */ |
| |
| if (m_state == OMX_StateInvalid) |
| { |
| OMX_SWVDEC_LOG_ERROR("in state %s", OMX_STATETYPE_STRING(m_state)); |
| |
| retval = OMX_ErrorInvalidState; |
| } |
| else if (state_new == OMX_StateInvalid) |
| { |
| OMX_SWVDEC_LOG_ERROR("requested transition to state %s", |
| OMX_STATETYPE_STRING(state_new)); |
| |
| retval = OMX_ErrorInvalidState; |
| } |
| else if ((m_state == OMX_StateLoaded) && |
| (state_new == OMX_StateIdle)) |
| { |
| if ((m_port_ip.populated == OMX_TRUE) && |
| (m_port_op.populated == OMX_TRUE)) |
| { |
| if ((retval_swvdec = swvdec_start(m_swvdec_handle)) == |
| SWVDEC_STATUS_SUCCESS) |
| { |
| *p_cmd_ack = true; |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("failed to start SwVdec"); |
| |
| retval = retval_swvdec2omx(retval_swvdec); |
| } |
| } |
| else |
| { |
| m_status_flags |= (1 << PENDING_STATE_LOADED_TO_IDLE); |
| |
| OMX_SWVDEC_LOG_LOW("'loaded-to-idle' pending"); |
| } |
| } |
| else if ((m_state == OMX_StateIdle) && |
| (state_new == OMX_StateExecuting)) |
| { |
| *p_cmd_ack = true; |
| } |
| else if ((m_state == OMX_StateExecuting) && |
| (state_new == OMX_StateIdle)) |
| { |
| m_status_flags |= (1 << PENDING_STATE_EXECUTING_TO_IDLE); |
| |
| OMX_SWVDEC_LOG_LOW("'executing-to-idle' pending"); |
| |
| retval = flush(OMX_ALL); |
| } |
| else if ((m_state == OMX_StateIdle) && |
| (state_new == OMX_StateLoaded)) |
| { |
| if ((m_port_ip.unpopulated == OMX_TRUE) && |
| (m_port_op.unpopulated == OMX_TRUE)) |
| { |
| if ((retval_swvdec = swvdec_stop(m_swvdec_handle)) == |
| SWVDEC_STATUS_SUCCESS) |
| { |
| *p_cmd_ack = true; |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("failed to stop SwVdec"); |
| |
| retval = retval_swvdec2omx(retval_swvdec); |
| } |
| } |
| else |
| { |
| m_status_flags |= (1 << PENDING_STATE_IDLE_TO_LOADED); |
| |
| OMX_SWVDEC_LOG_LOW("'idle-to-loaded' pending"); |
| } |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("state transition '%s -> %s' illegal", |
| OMX_STATETYPE_STRING(m_state), |
| OMX_STATETYPE_STRING(state_new)); |
| |
| retval = ((state_new == m_state) ? |
| OMX_ErrorSameState : |
| OMX_ErrorIncorrectStateTransition); |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Process OMX_CommandFlush. |
| * |
| * @param[in] port_index: Index of port to flush. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_flush(unsigned int port_index) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| OMX_SWVDEC_LOG_HIGH("flush port index %d requested", port_index); |
| |
| if (port_index == OMX_CORE_PORT_INDEX_IP) |
| { |
| m_status_flags |= (1 << PENDING_PORT_FLUSH_IP); |
| |
| OMX_SWVDEC_LOG_LOW("ip port flush pending"); |
| } |
| else if (port_index == OMX_CORE_PORT_INDEX_OP) |
| { |
| m_status_flags |= (1 << PENDING_PORT_FLUSH_OP); |
| |
| OMX_SWVDEC_LOG_LOW("op port flush pending"); |
| } |
| else if (port_index == OMX_ALL) |
| { |
| m_status_flags |= (1 << PENDING_PORT_FLUSH_IP); |
| m_status_flags |= (1 << PENDING_PORT_FLUSH_OP); |
| |
| OMX_SWVDEC_LOG_LOW("ip & op ports flush pending"); |
| } |
| |
| retval = flush(port_index); |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Process OMX_CommandPortDisable. |
| * |
| * @param[in,out] p_cmd_ack: Pointer to 'command acknowledge' boolean variable. |
| * @param[in] port_index: Index of port to disable. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_port_disable( |
| bool *p_cmd_ack, |
| unsigned int port_index) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| OMX_SWVDEC_LOG_HIGH("disable port index %d requested", port_index); |
| |
| if (port_index == OMX_CORE_PORT_INDEX_IP) |
| { |
| if (m_port_ip.enabled == OMX_FALSE) |
| { |
| OMX_SWVDEC_LOG_ERROR("ip port already disabled"); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| else |
| { |
| m_port_ip.enabled = OMX_FALSE; |
| |
| if (m_port_ip.unpopulated) |
| { |
| *p_cmd_ack = true; |
| } |
| else |
| { |
| m_status_flags |= (1 << PENDING_PORT_DISABLE_IP); |
| |
| OMX_SWVDEC_LOG_LOW("ip port disable pending"); |
| |
| if (m_port_ip.num_pending_buffers) |
| { |
| retval = flush(port_index); |
| } |
| } |
| } |
| } |
| else if (port_index == OMX_CORE_PORT_INDEX_OP) |
| { |
| if (m_port_op.enabled == OMX_FALSE) |
| { |
| OMX_SWVDEC_LOG_ERROR("op port already disabled"); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| else |
| { |
| m_port_op.enabled = OMX_FALSE; |
| |
| if (m_port_op.unpopulated) |
| { |
| *p_cmd_ack = true; |
| } |
| else |
| { |
| m_status_flags |= (1 << PENDING_PORT_DISABLE_OP); |
| |
| OMX_SWVDEC_LOG_LOW("op port disable pending"); |
| |
| if (m_port_op.num_pending_buffers) |
| { |
| retval = flush(port_index); |
| } |
| } |
| } |
| } |
| else if (port_index == OMX_ALL) |
| { |
| if (m_port_ip.enabled == OMX_FALSE) |
| { |
| OMX_SWVDEC_LOG_ERROR("ip port already disabled"); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| else if (m_port_op.enabled == OMX_FALSE) |
| { |
| OMX_SWVDEC_LOG_ERROR("op port already disabled"); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| else |
| { |
| if (m_port_ip.unpopulated && m_port_op.unpopulated) |
| { |
| *p_cmd_ack = true; |
| } |
| else |
| { |
| m_port_ip.enabled = OMX_FALSE; |
| m_port_op.enabled = OMX_FALSE; |
| |
| if (m_port_ip.unpopulated == OMX_FALSE) |
| { |
| m_status_flags |= (1 << PENDING_PORT_DISABLE_IP); |
| |
| OMX_SWVDEC_LOG_LOW("ip port disable pending"); |
| |
| if (m_port_ip.num_pending_buffers) |
| { |
| retval = flush(port_index); |
| } |
| } |
| |
| if ((retval == OMX_ErrorNone) && |
| (m_port_op.unpopulated == OMX_FALSE)) |
| { |
| m_status_flags |= (1 << PENDING_PORT_DISABLE_OP); |
| |
| OMX_SWVDEC_LOG_LOW("op port disable pending"); |
| |
| if (m_port_op.num_pending_buffers) |
| { |
| retval = flush(port_index); |
| } |
| } |
| } |
| } |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", |
| port_index); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Process OMX_CommandPortEnable. |
| * |
| * @param[in,out] p_cmd_ack: Pointer to 'command acknowledge' boolean variable. |
| * @param[in] port_index: Index of port to enable. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::async_process_event_cmd_port_enable( |
| bool *p_cmd_ack, |
| unsigned int port_index) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| OMX_SWVDEC_LOG_HIGH("enable port index %d requested", port_index); |
| |
| if (port_index == OMX_CORE_PORT_INDEX_IP) |
| { |
| if (m_port_ip.enabled) |
| { |
| OMX_SWVDEC_LOG_ERROR("ip port already enabled"); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| else |
| { |
| m_port_ip.enabled = OMX_TRUE; |
| |
| if (m_port_ip.populated) |
| { |
| *p_cmd_ack = true; |
| } |
| else |
| { |
| m_status_flags |= (1 << PENDING_PORT_ENABLE_IP); |
| |
| OMX_SWVDEC_LOG_LOW("ip port enable pending"); |
| } |
| } |
| } |
| else if (port_index == OMX_CORE_PORT_INDEX_OP) |
| { |
| if (m_port_op.enabled) |
| { |
| OMX_SWVDEC_LOG_ERROR("op port already enabled"); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| else |
| { |
| m_port_op.enabled = OMX_TRUE; |
| |
| if (m_port_op.populated) |
| { |
| *p_cmd_ack = true; |
| } |
| else |
| { |
| m_status_flags |= (1 << PENDING_PORT_ENABLE_OP); |
| |
| OMX_SWVDEC_LOG_LOW("op port enable pending"); |
| } |
| } |
| } |
| else if (port_index == OMX_ALL) |
| { |
| if (m_port_ip.enabled) |
| { |
| OMX_SWVDEC_LOG_ERROR("ip port already enabled"); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| else if (m_port_op.enabled) |
| { |
| OMX_SWVDEC_LOG_ERROR("op port already enabled"); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| else |
| { |
| m_port_ip.enabled = OMX_TRUE; |
| m_port_op.enabled = OMX_TRUE; |
| |
| if (m_port_ip.populated && m_port_op.populated) |
| { |
| *p_cmd_ack = true; |
| } |
| else if (m_port_ip.populated == false) |
| { |
| m_status_flags |= (1 << PENDING_PORT_ENABLE_IP); |
| |
| OMX_SWVDEC_LOG_LOW("ip port enable pending"); |
| } |
| else if (m_port_op.populated == false) |
| { |
| m_status_flags |= (1 << PENDING_PORT_ENABLE_OP); |
| |
| OMX_SWVDEC_LOG_LOW("op port enable pending"); |
| } |
| } |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("port index '%d' invalid", |
| port_index); |
| |
| retval = OMX_ErrorBadPortIndex; |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Process ETB event. |
| * |
| * @param[in] p_buffer_hdr: Pointer to buffer header. |
| * @param[in] index: Index of buffer in input buffer info array. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::async_process_event_etb( |
| OMX_BUFFERHEADERTYPE *p_buffer_hdr, |
| unsigned int index) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| m_port_ip.num_pending_buffers++; |
| |
| if ((p_buffer_hdr->nFilledLen == 0) && |
| ((p_buffer_hdr->nFlags & OMX_BUFFERFLAG_EOS) == 0)) |
| { |
| OMX_SWVDEC_LOG_HIGH("returning %p, buffer %p," |
| "zero length & no EOS flag", |
| p_buffer_hdr, |
| p_buffer_hdr->pBuffer); |
| |
| async_post_event(OMX_SWVDEC_EVENT_EBD, |
| (unsigned long) p_buffer_hdr, |
| (unsigned long) index); |
| } |
| else if (m_port_ip.flush_inprogress) |
| { |
| OMX_SWVDEC_LOG_HIGH("returning %p, buffer %p; " |
| "ip port flush in progress", |
| p_buffer_hdr, |
| p_buffer_hdr->pBuffer); |
| |
| async_post_event(OMX_SWVDEC_EVENT_EBD, |
| (unsigned long) p_buffer_hdr, |
| (unsigned long) index); |
| } |
| else |
| { |
| SWVDEC_STATUS retval_swvdec; |
| |
| SWVDEC_BUFFER *p_buffer_swvdec = |
| &(m_buffer_array_ip[index].buffer_swvdec); |
| |
| if (p_buffer_hdr->nFilledLen && |
| ((p_buffer_hdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) == 0)) |
| { |
| m_queue_timestamp.push(p_buffer_hdr->nTimeStamp); |
| } |
| |
| assert(p_buffer_swvdec->p_buffer == p_buffer_hdr->pBuffer); |
| //sending the fd info |
| p_buffer_swvdec->fd = m_buffer_array_ip[index].buffer_payload.pmem_fd; |
| if (m_arbitrary_bytes_mode && |
| p_buffer_hdr->nFilledLen && |
| ((p_buffer_hdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) == 0)) |
| { |
| unsigned int offset_array[OMX_SWVDEC_MAX_FRAMES_PER_ETB] = {0}; |
| |
| unsigned int num_frame_headers = 1; |
| |
| if ((m_omx_video_codingtype == |
| ((OMX_VIDEO_CODINGTYPE) QOMX_VIDEO_CodingDivx)) || |
| (m_omx_video_codingtype == OMX_VIDEO_CodingMPEG4)) |
| { |
| num_frame_headers = split_buffer_mpeg4(offset_array, |
| p_buffer_hdr); |
| } |
| else |
| { |
| assert(0); |
| } |
| |
| if(num_frame_headers > 1) |
| { |
| m_buffer_array_ip[index].split_count = num_frame_headers - 1; |
| |
| for (unsigned int ii = 0; ii < num_frame_headers; ii++) |
| { |
| p_buffer_swvdec->flags = p_buffer_hdr->nFlags; |
| p_buffer_swvdec->timestamp = p_buffer_hdr->nTimeStamp; |
| |
| if (ii == 0) |
| { |
| p_buffer_swvdec->offset = 0; |
| p_buffer_swvdec->filled_length = (offset_array[ii + 1] ? |
| offset_array[ii + 1] : |
| p_buffer_hdr->nFilledLen); |
| } |
| else |
| { |
| p_buffer_swvdec->offset = offset_array[ii]; |
| p_buffer_swvdec->filled_length = |
| p_buffer_hdr->nFilledLen - offset_array[ii]; |
| } |
| |
| m_diag.dump_ip(p_buffer_swvdec->p_buffer + |
| p_buffer_swvdec->offset, |
| p_buffer_swvdec->filled_length); |
| |
| retval_swvdec = swvdec_emptythisbuffer(m_swvdec_handle, |
| p_buffer_swvdec); |
| |
| if (retval_swvdec != SWVDEC_STATUS_SUCCESS) |
| { |
| retval = retval_swvdec2omx(retval_swvdec); |
| break; |
| } |
| } |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_HIGH("No frame detected for Buffer %p, with TS %lld", |
| p_buffer_hdr->pBuffer, p_buffer_hdr->nTimeStamp ); |
| |
| p_buffer_swvdec->flags = p_buffer_hdr->nFlags; |
| p_buffer_swvdec->offset = 0; |
| p_buffer_swvdec->timestamp = p_buffer_hdr->nTimeStamp; |
| p_buffer_swvdec->filled_length = p_buffer_hdr->nFilledLen; |
| |
| m_diag.dump_ip(p_buffer_swvdec->p_buffer + p_buffer_swvdec->offset, |
| p_buffer_swvdec->filled_length); |
| |
| retval_swvdec = swvdec_emptythisbuffer(m_swvdec_handle, |
| p_buffer_swvdec); |
| |
| if (retval_swvdec != SWVDEC_STATUS_SUCCESS) |
| { |
| retval = retval_swvdec2omx(retval_swvdec); |
| } |
| } |
| } |
| else |
| { |
| p_buffer_swvdec->flags = p_buffer_hdr->nFlags; |
| p_buffer_swvdec->offset = 0; |
| p_buffer_swvdec->timestamp = p_buffer_hdr->nTimeStamp; |
| p_buffer_swvdec->filled_length = p_buffer_hdr->nFilledLen; |
| |
| m_diag.dump_ip(p_buffer_swvdec->p_buffer + p_buffer_swvdec->offset, |
| p_buffer_swvdec->filled_length); |
| |
| retval_swvdec = swvdec_emptythisbuffer(m_swvdec_handle, |
| p_buffer_swvdec); |
| |
| if (retval_swvdec != SWVDEC_STATUS_SUCCESS) |
| { |
| retval = retval_swvdec2omx(retval_swvdec); |
| } |
| } |
| } |
| return retval; |
| } |
| |
| /** |
| * @brief Process FTB event. |
| * |
| * @param[in] p_buffer_hdr: Pointer to buffer header. |
| * @param[in] index: Index of buffer in output buffer info array. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::async_process_event_ftb( |
| OMX_BUFFERHEADERTYPE *p_buffer_hdr, |
| unsigned int index) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| m_port_op.num_pending_buffers++; |
| |
| if (m_port_op.flush_inprogress) |
| { |
| OMX_SWVDEC_LOG_HIGH("returning %p, buffer %p; " |
| "op port flush in progress", |
| p_buffer_hdr, |
| m_buffer_array_op[index].buffer_swvdec.p_buffer); |
| |
| async_post_event(OMX_SWVDEC_EVENT_FBD, |
| (unsigned long) p_buffer_hdr, |
| (unsigned long) index); |
| } |
| else |
| { |
| SWVDEC_STATUS retval_swvdec; |
| |
| SWVDEC_BUFFER *p_buffer_swvdec = |
| &(m_buffer_array_op[index].buffer_swvdec); |
| p_buffer_swvdec->fd = m_buffer_array_op[index].buffer_payload.pmem_fd; |
| retval_swvdec = swvdec_fillthisbuffer(m_swvdec_handle, p_buffer_swvdec); |
| |
| if (retval_swvdec != SWVDEC_STATUS_SUCCESS) |
| { |
| retval = retval_swvdec2omx(retval_swvdec); |
| } |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Process EBD event. |
| * |
| * @param[in] p_buffer_hdr: Pointer to buffer header. |
| * @param[in] index: Index of buffer in output buffer info array. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::async_process_event_ebd( |
| OMX_BUFFERHEADERTYPE *p_buffer_hdr, |
| unsigned int index) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| if (index < m_port_ip.def.nBufferCountActual) |
| { |
| if (m_arbitrary_bytes_mode && m_buffer_array_ip[index].split_count) |
| { |
| m_buffer_array_ip[index].split_count--; |
| } |
| else |
| { |
| m_port_ip.num_pending_buffers--; |
| |
| OMX_SWVDEC_LOG_CALLBACK( |
| "EmptyBufferDone(): %p, buffer %p", |
| p_buffer_hdr, |
| m_buffer_array_ip[index].buffer_swvdec.p_buffer); |
| |
| m_callback.EmptyBufferDone(&m_cmp, m_app_data, p_buffer_hdr); |
| } |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("buffer index '%d' invalid", index); |
| |
| retval = OMX_ErrorBadParameter; |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Process FBD event. |
| * |
| * @param[in] p_buffer_hdr: Pointer to buffer header. |
| * @param[in] index: Index of buffer in output buffer info array. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::async_process_event_fbd( |
| OMX_BUFFERHEADERTYPE *p_buffer_hdr, |
| unsigned int index) |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| static long long timestamp_prev = 0; |
| |
| if (index < m_port_op.def.nBufferCountActual) |
| { |
| OMX_U8 *p_buffer; |
| |
| p_buffer = m_buffer_array_op[index].buffer_swvdec.p_buffer; |
| |
| m_port_op.num_pending_buffers--; |
| |
| if (m_port_op.flush_inprogress) |
| { |
| p_buffer_hdr->nFilledLen = 0; |
| p_buffer_hdr->nTimeStamp = 0; |
| p_buffer_hdr->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT; |
| } |
| |
| if (p_buffer_hdr->nFilledLen) |
| { |
| if (m_sync_frame_decoding_mode) |
| { |
| OMX_SWVDEC_LOG_LOW("sync frame decoding mode; " |
| "setting timestamp to zero"); |
| |
| p_buffer_hdr->nTimeStamp = 0; |
| } |
| else |
| { |
| if (m_queue_timestamp.empty()) |
| { |
| OMX_SWVDEC_LOG_ERROR("timestamp queue empty; " |
| "re-using previous timestamp %lld", |
| timestamp_prev); |
| |
| p_buffer_hdr->nTimeStamp = timestamp_prev; |
| } |
| else |
| { |
| p_buffer_hdr->nTimeStamp = m_queue_timestamp.top(); |
| |
| m_queue_timestamp.pop(); |
| |
| timestamp_prev = p_buffer_hdr->nTimeStamp; |
| } |
| } |
| |
| ion_flush_op(index); |
| |
| if (m_meta_buffer_mode) |
| { |
| pthread_mutex_lock(&m_meta_buffer_array_mutex); |
| } |
| |
| m_diag.dump_op(p_buffer, |
| m_frame_dimensions.width, |
| m_frame_dimensions.height, |
| m_frame_attributes.stride, |
| m_frame_attributes.scanlines); |
| |
| if (m_meta_buffer_mode) |
| { |
| pthread_mutex_unlock(&m_meta_buffer_array_mutex); |
| } |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_LOW("filled length zero; " |
| "setting timestamp to zero"); |
| |
| p_buffer_hdr->nTimeStamp = 0; |
| } |
| |
| if (p_buffer_hdr->nFlags & OMX_BUFFERFLAG_EOS) |
| { |
| async_post_event(OMX_SWVDEC_EVENT_EOS, 0, 0); |
| |
| OMX_SWVDEC_LOG_LOW("flushing %zu elements in timestamp queue", |
| m_queue_timestamp.size()); |
| |
| while (m_queue_timestamp.empty() == false) |
| { |
| m_queue_timestamp.pop(); |
| } |
| } |
| |
| if (m_meta_buffer_mode && |
| ((p_buffer_hdr->nFlags & OMX_BUFFERFLAG_READONLY)) == 0) |
| { |
| meta_buffer_ref_remove(index); |
| } |
| |
| OMX_SWVDEC_LOG_CALLBACK( |
| "FillBufferDone(): %p, buffer %p, " |
| "flags 0x%08x, filled length %d, timestamp %lld", |
| p_buffer_hdr, |
| p_buffer, |
| p_buffer_hdr->nFlags, |
| p_buffer_hdr->nFilledLen, |
| p_buffer_hdr->nTimeStamp); |
| |
| m_callback.FillBufferDone(&m_cmp, m_app_data, p_buffer_hdr); |
| } |
| else |
| { |
| OMX_SWVDEC_LOG_ERROR("buffer index '%d' invalid", index); |
| |
| retval = OMX_ErrorBadParameter; |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Process EOS event. |
| * |
| * @retval OMX_ErrorNone |
| */ |
| OMX_ERRORTYPE omx_swvdec::async_process_event_eos() |
| { |
| OMX_SWVDEC_LOG_CALLBACK("EventHandler(): " |
| "OMX_EventBufferFlag, port index %d, EOS", |
| OMX_CORE_PORT_INDEX_OP); |
| |
| m_callback.EventHandler(&m_cmp, |
| m_app_data, |
| OMX_EventBufferFlag, |
| OMX_CORE_PORT_INDEX_OP, |
| OMX_BUFFERFLAG_EOS, |
| NULL); |
| |
| return OMX_ErrorNone; |
| } |
| |
| /** |
| * @brief Process input port flush event. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::async_process_event_flush_port_ip() |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| OMX_SWVDEC_EVENT_INFO event_info; |
| |
| OMX_BUFFERHEADERTYPE *p_buffer_hdr; |
| |
| unsigned int index; |
| |
| while (m_queue_port_ip.pop(&event_info)) |
| { |
| switch (event_info.event_id) |
| { |
| |
| case OMX_SWVDEC_EVENT_ETB: |
| { |
| p_buffer_hdr = (OMX_BUFFERHEADERTYPE *) event_info.event_param1; |
| |
| index = event_info.event_param2; |
| |
| // compensate decrement in async_process_event_ebd() |
| m_port_ip.num_pending_buffers++; |
| |
| retval = async_process_event_ebd(p_buffer_hdr, index); |
| break; |
| } |
| |
| case OMX_SWVDEC_EVENT_EBD: |
| { |
| p_buffer_hdr = (OMX_BUFFERHEADERTYPE *) event_info.event_param1; |
| |
| index = event_info.event_param2; |
| |
| retval = async_process_event_ebd(p_buffer_hdr, index); |
| break; |
| } |
| |
| default: |
| { |
| assert(0); |
| break; |
| } |
| |
| } |
| } |
| |
| assert(m_port_ip.num_pending_buffers == 0); |
| |
| if ((retval == OMX_ErrorNone) && |
| (m_status_flags & (1 << PENDING_PORT_FLUSH_IP))) |
| { |
| m_status_flags &= ~(1 << PENDING_PORT_FLUSH_IP); |
| |
| async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, |
| OMX_CommandFlush, |
| OMX_CORE_PORT_INDEX_IP); |
| } |
| |
| m_port_ip.flush_inprogress = OMX_FALSE; |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Process output port flush event. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::async_process_event_flush_port_op() |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| OMX_SWVDEC_EVENT_INFO event_info; |
| |
| OMX_BUFFERHEADERTYPE *p_buffer_hdr; |
| |
| unsigned int index; |
| |
| while (m_queue_port_op.pop(&event_info)) |
| { |
| switch (event_info.event_id) |
| { |
| |
| case OMX_SWVDEC_EVENT_FTB: |
| { |
| p_buffer_hdr = (OMX_BUFFERHEADERTYPE *) event_info.event_param1; |
| |
| index = event_info.event_param2; |
| |
| // compensate decrement in async_process_event_fbd() |
| m_port_op.num_pending_buffers++; |
| |
| retval = async_process_event_fbd(p_buffer_hdr, index); |
| break; |
| } |
| |
| case OMX_SWVDEC_EVENT_FBD: |
| { |
| p_buffer_hdr = (OMX_BUFFERHEADERTYPE *) event_info.event_param1; |
| |
| index = event_info.event_param2; |
| |
| retval = async_process_event_fbd(p_buffer_hdr, index); |
| break; |
| } |
| |
| default: |
| { |
| assert(0); |
| break; |
| } |
| |
| } |
| } |
| |
| assert(m_port_op.num_pending_buffers == 0); |
| |
| if ((retval == OMX_ErrorNone) && |
| (m_status_flags & (1 << PENDING_PORT_FLUSH_OP))) |
| { |
| m_status_flags &= ~(1 << PENDING_PORT_FLUSH_OP); |
| |
| async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, |
| OMX_CommandFlush, |
| OMX_CORE_PORT_INDEX_OP); |
| } |
| |
| if ((retval == OMX_ErrorNone) && |
| (m_status_flags & (1 << PENDING_STATE_EXECUTING_TO_IDLE))) |
| { |
| m_status_flags &= ~(1 << PENDING_STATE_EXECUTING_TO_IDLE); |
| |
| async_post_event(OMX_SWVDEC_EVENT_CMD_ACK, |
| OMX_CommandStateSet, |
| OMX_StateIdle); |
| } |
| |
| if (m_port_reconfig_inprogress == false) |
| { |
| OMX_SWVDEC_LOG_LOW("flushing %zu elements in timestamp queue", |
| m_queue_timestamp.size()); |
| |
| while (m_queue_timestamp.empty() == false) |
| { |
| m_queue_timestamp.pop(); |
| } |
| } |
| |
| m_port_op.flush_inprogress = OMX_FALSE; |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Process port reconfiguration event. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::async_process_event_port_reconfig() |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| if (m_port_reconfig_inprogress) |
| { |
| OMX_SWVDEC_LOG_ERROR("port reconfiguration already in progress"); |
| |
| retval = OMX_ErrorIncorrectStateOperation; |
| } |
| else |
| { |
| m_port_reconfig_inprogress = true; |
| |
| OMX_SWVDEC_LOG_CALLBACK("EventHandler(): " |
| "OMX_EventPortSettingsChanged, port index %d", |
| OMX_CORE_PORT_INDEX_OP); |
| |
| m_callback.EventHandler(&m_cmp, |
| m_app_data, |
| OMX_EventPortSettingsChanged, |
| OMX_CORE_PORT_INDEX_OP, |
| OMX_IndexParamPortDefinition, |
| NULL); |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Process dimensions updated event. |
| * |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::async_process_event_dimensions_updated() |
| { |
| OMX_ERRORTYPE retval = OMX_ErrorNone; |
| |
| if (m_dimensions_update_inprogress) |
| { |
| OMX_SWVDEC_LOG_ERROR("dimensions update already in progress"); |
| |
| retval = OMX_ErrorIncorrectStateOperation; |
| } |
| else |
| { |
| m_dimensions_update_inprogress = true; |
| |
| OMX_SWVDEC_LOG_CALLBACK("EventHandler(): " |
| "OMX_EventPortSettingsChanged, port index %d, " |
| "OMX_IndexConfigCommonOutputCrop", |
| OMX_CORE_PORT_INDEX_OP); |
| |
| m_callback.EventHandler(&m_cmp, |
| m_app_data, |
| OMX_EventPortSettingsChanged, |
| OMX_CORE_PORT_INDEX_OP, |
| OMX_IndexConfigCommonOutputCrop, |
| NULL); |
| } |
| |
| return retval; |
| } |
| |
| /** |
| * @brief Map the memory and run the ioctl SYNC operations |
| *.on ION fd with DMA_BUF_IOCTL_SYNC |
| *.@param[in] fd: ION header. |
| * @param[in] len:Lenth of the memory. |
| * @retval mapped memory pointer |
| */ |
| unsigned char *omx_swvdec::ion_map(int fd, int len) |
| { |
| unsigned char *bufaddr = (unsigned char*)mmap(NULL, len, PROT_READ|PROT_WRITE, |
| MAP_SHARED, fd, 0); |
| if (bufaddr != MAP_FAILED) { |
| #ifdef USE_ION |
| struct dma_buf_sync buf_sync; |
| buf_sync.flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_RW; |
| int rc = ioctl(fd, DMA_BUF_IOCTL_SYNC, &buf_sync); |
| if (rc) { |
| OMX_SWVDEC_LOG_ERROR("Failed DMA_BUF_IOCTL_SYNC"); |
| } |
| #endif |
| } |
| return bufaddr; |
| } |
| |
| /** |
| * @brief Unmap the memory |
| *.@param[in] fd: ION header. |
| .*.@param[in].bufaddr : buffer address |
| * @param[in] len:Lenth of the memory. |
| * @retval OMX_ERRORTYPE |
| */ |
| OMX_ERRORTYPE omx_swvdec::ion_unmap(int fd, void *bufaddr, int len) |
| { |
| #ifdef USE_ION |
| struct dma_buf_sync buf_sync; |
| buf_sync.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_RW; |
| int rc = ioctl(fd, DMA_BUF_IOCTL_SYNC, &buf_sync); |
| if (rc) { |
| OMX_SWVDEC_LOG_ERROR("Failed DMA_BUF_IOCTL_SYNC"); |
| } |
| #endif |
| if (-1 == munmap(bufaddr, len)) { |
| OMX_SWVDEC_LOG_ERROR("munmap failed."); |
| return OMX_ErrorInsufficientResources; |
| } |
| return OMX_ErrorNone; |
| } |
| |