blob: 0acb4aaea4565ae4c159f5fd724669a36e8ba979 [file] [log] [blame]
/**
* @copyright
*
* Copyright (c) 2015-2018, 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);
strlcpy(m_role_name, "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE);
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))))
{
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;
}
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 = (unsigned char *) mmap(NULL,
m_port_op.def.nBufferSize,
PROT_READ | PROT_WRITE,
MAP_SHARED,
p_private_handle->fd,
0);
if (bufferaddr == MAP_FAILED)
{
OMX_SWVDEC_LOG_ERROR("mmap() failed for "
"fd %d of size %d",
p_private_handle->fd,
m_port_op.def.nBufferSize);
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 = m_port_op.def.nBufferSize;
p_buffer_payload->mmaped_size = m_port_op.def.nBufferSize;
p_buffer_swvdec->p_buffer = bufferaddr;
p_buffer_swvdec->size = m_port_op.def.nBufferSize;
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:
{
/**
* alignment factors:
*
* - stride: 128
* - scanlines_y: 32
* - scanlines_uv: 16
* - size: 4096
*/
m_frame_attributes.stride = ALIGN(width, 128);
m_frame_attributes.scanlines = ALIGN(height, 32);
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_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;
m_port_op.def.nBufferCountMin = p_port_def->nBufferCountMin;
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;