Commit 20df8f9c authored by Thomas Guillem's avatar Thomas Guillem

omx: add OMXCodec_GetQuirks

This function returns of list of hacks that are needed for codec
initialization, and also include IgnoreOmxDecoderPadding hack.

Remove OMX.MTK.VIDEO.DECODER.MPEG4 from blacklist since it only need a valid
CSD.
parent 9258870f
......@@ -100,6 +100,7 @@ struct decoder_sys_t
bool error_state;
bool b_new_block;
int64_t i_preroll_end;
int i_quirks;
/* Specific Audio/Video callbacks */
dec_on_new_block_cb pf_on_new_block;
......@@ -585,24 +586,17 @@ static int OpenDecoder(vlc_object_t *p_this, pf_MediaCodecApi_init pf_init)
if (!p_sys->psz_name)
goto bailout;
/* Check if we need late opening */
switch (p_dec->fmt_in.i_codec)
p_sys->i_quirks = OMXCodec_GetQuirks( VIDEO_ES,
p_dec->fmt_in.i_codec,
p_sys->psz_name,
strlen(p_sys->psz_name) );
if ((p_sys->i_quirks & OMXCODEC_VIDEO_QUIRKS_NEED_SIZE)
&& (!p_sys->u.video.i_width || !p_sys->u.video.i_height))
{
case VLC_CODEC_H264:
if (!p_sys->u.video.i_width || !p_sys->u.video.i_height)
{
msg_Warn(p_dec, "waiting for sps/pps for codec %4.4s",
(const char *)&p_dec->fmt_in.i_codec);
return VLC_SUCCESS;
}
case VLC_CODEC_VC1:
if (!p_dec->fmt_in.i_extra)
{
msg_Warn(p_dec, "waiting for extra data for codec %4.4s",
(const char *)&p_dec->fmt_in.i_codec);
return VLC_SUCCESS;
}
break;
msg_Warn(p_dec, "waiting for a valid video size for codec %4.4s",
(const char *)&p_dec->fmt_in.i_codec);
return VLC_SUCCESS;
}
}
else
......@@ -616,30 +610,24 @@ static int OpenDecoder(vlc_object_t *p_this, pf_MediaCodecApi_init pf_init)
if (!p_sys->psz_name)
goto bailout;
/* Marvel ACodec assert if channel count is 0 */
if (!strncmp(p_sys->psz_name, "OMX.Marvell",
__MIN(strlen(p_sys->psz_name), strlen("OMX.Marvell"))))
p_sys->u.audio.b_need_channels = true;
/* Check if we need late opening */
switch (p_dec->fmt_in.i_codec)
{
case VLC_CODEC_VORBIS:
case VLC_CODEC_MP4A:
if (!p_dec->fmt_in.i_extra)
{
msg_Warn(p_dec, "waiting for extra data for codec %4.4s",
(const char *)&p_dec->fmt_in.i_codec);
return VLC_SUCCESS;
}
break;
}
if (!p_sys->u.audio.i_channels && p_sys->u.audio.b_need_channels)
p_sys->i_quirks = OMXCodec_GetQuirks( AUDIO_ES,
p_dec->fmt_in.i_codec,
p_sys->psz_name,
strlen(p_sys->psz_name) );
if ((p_sys->i_quirks & OMXCODEC_AUDIO_QUIRKS_NEED_CHANNELS)
&& !p_sys->u.audio.i_channels)
{
msg_Warn(p_dec, "waiting for valid channel count");
return VLC_SUCCESS;
}
}
if ((p_sys->i_quirks & OMXCODEC_QUIRKS_NEED_CSD)
&& !p_dec->fmt_in.i_extra)
{
msg_Warn(p_dec, "waiting for extra data for codec %4.4s",
(const char *)&p_dec->fmt_in.i_codec);
return VLC_SUCCESS;
}
if (StartMediaCodec(p_dec) == VLC_SUCCESS)
return VLC_SUCCESS;
......@@ -899,7 +887,8 @@ static int Video_ProcessOutput(decoder_t *p_dec, mc_api_out *p_out,
p_sys->u.video.i_stride, &p_sys->u.video.ascd);
if (p_sys->u.video.i_pixel_format == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar)
p_sys->u.video.i_slice_height -= p_out->u.conf.video.crop_top/2;
if (IgnoreOmxDecoderPadding(p_sys->psz_name)) {
if ((p_sys->i_quirks & OMXCODEC_VIDEO_QUIRKS_IGNORE_PADDING))
{
p_sys->u.video.i_slice_height = 0;
p_sys->u.video.i_stride = p_dec->fmt_out.video.i_width;
}
......@@ -1304,17 +1293,19 @@ static int Video_OnNewBlock(decoder_t *p_dec, block_t *p_block, int *p_flags)
}
}
/* try delayed opening if there is a new extra data */
if (!p_sys->api->b_started)
{
switch (p_dec->fmt_in.i_codec)
{
case VLC_CODEC_VC1:
if (p_dec->fmt_in.i_extra)
*p_flags |= NEWBLOCK_FLAG_RESTART;
default:
break;
}
*p_flags |= NEWBLOCK_FLAG_RESTART;
/* Don't start if we don't have any csd */
if ((p_sys->i_quirks & OMXCODEC_QUIRKS_NEED_CSD)
&& !p_dec->fmt_in.i_extra && !p_sys->pp_csd)
*p_flags &= ~NEWBLOCK_FLAG_RESTART;
/* Don't start if we don't have a valid video size */
if ((p_sys->i_quirks & OMXCODEC_VIDEO_QUIRKS_NEED_SIZE)
&& (!p_sys->u.video.i_width || !p_sys->u.video.i_height))
*p_flags &= ~NEWBLOCK_FLAG_RESTART;
}
timestamp_FifoPut(p_sys->u.video.timestamp_fifo,
......@@ -1359,22 +1350,18 @@ static int Audio_OnNewBlock(decoder_t *p_dec, block_t *p_block, int *p_flags)
/* try delayed opening if there is a new extra data */
if (!p_sys->api->b_started)
{
switch (p_dec->fmt_in.i_codec)
{
case VLC_CODEC_VORBIS:
case VLC_CODEC_MP4A:
if (p_dec->fmt_in.i_extra)
*p_flags |= NEWBLOCK_FLAG_RESTART;
default:
break;
}
if (!p_dec->p_sys->u.audio.i_channels && p_dec->fmt_in.audio.i_channels)
{
p_dec->p_sys->u.audio.i_channels = p_dec->fmt_in.audio.i_channels;
*p_flags |= NEWBLOCK_FLAG_RESTART;
}
p_dec->p_sys->u.audio.i_channels = p_dec->fmt_in.audio.i_channels;
*p_flags |= NEWBLOCK_FLAG_RESTART;
/* Don't start if we don't have any csd */
if ((p_sys->i_quirks & OMXCODEC_QUIRKS_NEED_CSD)
&& !p_dec->fmt_in.i_extra)
*p_flags &= ~NEWBLOCK_FLAG_RESTART;
if (!p_dec->p_sys->u.audio.i_channels && p_sys->u.audio.b_need_channels)
/* Don't start if we don't have a valid channels count */
if ((p_sys->i_quirks & OMXCODEC_AUDIO_QUIRKS_NEED_CHANNELS)
&& !p_dec->p_sys->u.audio.i_channels)
*p_flags &= ~NEWBLOCK_FLAG_RESTART;
}
return 1;
......
......@@ -635,7 +635,7 @@ static OMX_ERRORTYPE GetPortDefinition(decoder_t *p_dec, OmxPort *p_port,
strlen("OMX.qcom.video.decoder")))
def->format.video.eColorFormat = OMX_QCOM_COLOR_FormatYVU420SemiPlanar;
if (IgnoreOmxDecoderPadding(p_sys->psz_component)) {
if ((p_sys->i_quirks & OMXCODEC_VIDEO_QUIRKS_IGNORE_PADDING)) {
def->format.video.nSliceHeight = 0;
def->format.video.nStride = p_fmt->video.i_width;
}
......@@ -821,6 +821,7 @@ static OMX_ERRORTYPE InitialiseComponent(decoder_t *p_dec,
OMX_HANDLETYPE omx_handle;
OMX_ERRORTYPE omx_error;
unsigned int i;
int i_quirks;
OMX_U8 psz_role[OMX_MAX_STRINGNAME_SIZE];
OMX_PARAM_COMPONENTROLETYPE role;
OMX_PARAM_PORTDEFINITIONTYPE definition;
......@@ -835,6 +836,10 @@ static OMX_ERRORTYPE InitialiseComponent(decoder_t *p_dec,
return omx_error;
}
strncpy(p_sys->psz_component, psz_component, OMX_MAX_STRINGNAME_SIZE-1);
i_quirks = OMXCodec_GetQuirks(p_dec->fmt_in.i_cat,
p_sys->b_enc ? p_dec->fmt_out.i_codec : p_dec->fmt_in.i_codec,
p_sys->psz_component,
strlen(p_sys->psz_component));
omx_error = OMX_ComponentRoleEnum(omx_handle, psz_role, 0);
if(omx_error == OMX_ErrorNone)
......@@ -976,6 +981,7 @@ static OMX_ERRORTYPE InitialiseComponent(decoder_t *p_dec,
}
}
p_sys->i_quirks = i_quirks;
*p_handle = omx_handle;
return OMX_ErrorNone;
......
......@@ -119,6 +119,7 @@ struct decoder_sys_t
char psz_component[OMX_MAX_STRINGNAME_SIZE];
char ppsz_components[MAX_COMPONENTS_LIST_SIZE][OMX_MAX_STRINGNAME_SIZE];
unsigned int components;
int i_quirks;
OmxEventQueue event_queue;
......
......@@ -209,8 +209,6 @@ void CopyOmxPicture( int i_color_format, picture_t *p_pic,
void CopyVlcPicture( decoder_t *, OMX_BUFFERHEADERTYPE *, picture_t * );
int IgnoreOmxDecoderPadding(const char *psz_name);
/*****************************************************************************
* Logging utility functions
*****************************************************************************/
......@@ -226,6 +224,16 @@ void PrintOmx(decoder_t *p_dec, OMX_HANDLETYPE omx_handle, OMX_U32 i_port);
*****************************************************************************/
bool OMXCodec_IsBlacklisted( const char *p_name, unsigned int i_name_len );
enum {
OMXCODEC_NO_QUIRKS = 0,
OMXCODEC_QUIRKS_NEED_CSD = 0x1,
OMXCODEC_VIDEO_QUIRKS_NEED_SIZE = 0x2,
OMXCODEC_VIDEO_QUIRKS_IGNORE_PADDING = 0x4,
OMXCODEC_AUDIO_QUIRKS_NEED_CHANNELS = 0x8,
};
int OMXCodec_GetQuirks( int i_cat, vlc_fourcc_t i_codec,
const char *p_name, unsigned int i_name_len );
/*****************************************************************************
* fourcc -> omx id mapping
*****************************************************************************/
......
......@@ -278,35 +278,6 @@ void CopyVlcPicture( decoder_t *p_dec, OMX_BUFFERHEADERTYPE *p_header,
}
}
int IgnoreOmxDecoderPadding(const char *name)
{
// The list of decoders that signal padding properly is not necessary,
// since that is the default, but keep it here for reference. (This is
// only relevant for manufacturers that are known to have decoders with
// this kind of bug.)
/*
static const char *padding_decoders[] = {
"OMX.SEC.AVC.Decoder",
"OMX.SEC.wmv7.dec",
"OMX.SEC.wmv8.dec",
NULL
};
*/
static const char *nopadding_decoders[] = {
"OMX.SEC.avc.dec",
"OMX.SEC.avcdec",
"OMX.SEC.MPEG4.Decoder",
"OMX.SEC.mpeg4.dec",
"OMX.SEC.vc1.dec",
NULL
};
for (const char **ptr = nopadding_decoders; *ptr; ptr++) {
if (!strcmp(*ptr, name))
return 1;
}
return 0;
}
/*****************************************************************************
* Utility functions
*****************************************************************************/
......@@ -335,8 +306,6 @@ bool OMXCodec_IsBlacklisted( const char *p_name, unsigned int i_name_len )
* it) and for WMV3 it outputs plain black buffers. Thus ignore
* it until we can make it work properly. */
"OMX.Nvidia.vc1.decode",
/* crashes mediaserver */
"OMX.MTK.VIDEO.DECODER.MPEG4",
/* black screen */
"OMX.MTK.VIDEO.DECODER.VC1",
/* Not working or crashing (Samsung) */
......@@ -377,6 +346,90 @@ bool OMXCodec_IsBlacklisted( const char *p_name, unsigned int i_name_len )
return false;
}
struct str2quirks {
const char *psz_name;
int i_quirks;
};
int OMXCodec_GetQuirks( int i_cat, vlc_fourcc_t i_codec,
const char *p_name, unsigned int i_name_len )
{
static const struct str2quirks quirks_prefix[] = {
{ "OMX.MTK.VIDEO.DECODER.MPEG4", OMXCODEC_QUIRKS_NEED_CSD },
{ "OMX.Marvell", OMXCODEC_AUDIO_QUIRKS_NEED_CHANNELS },
/* The list of decoders that signal padding properly is not necessary,
* since that is the default, but keep it here for reference. (This is
* only relevant for manufacturers that are known to have decoders with
* this kind of bug.)
* static const char *padding_decoders[] = {
* "OMX.SEC.AVC.Decoder",
* "OMX.SEC.wmv7.dec",
* "OMX.SEC.wmv8.dec",
* NULL
* };
*/
{ "OMX.SEC.avc.dec", OMXCODEC_VIDEO_QUIRKS_IGNORE_PADDING },
{ "OMX.SEC.avcdec", OMXCODEC_VIDEO_QUIRKS_IGNORE_PADDING },
{ "OMX.SEC.MPEG4.Decoder", OMXCODEC_VIDEO_QUIRKS_IGNORE_PADDING },
{ "OMX.SEC.mpeg4.dec", OMXCODEC_VIDEO_QUIRKS_IGNORE_PADDING },
{ "OMX.SEC.vc1.dec", OMXCODEC_VIDEO_QUIRKS_IGNORE_PADDING },
{ NULL, 0 }
};
static struct str2quirks quirks_suffix[] = {
{ NULL, 0 }
};
int i_quirks = OMXCODEC_NO_QUIRKS;
if( i_cat == VIDEO_ES )
{
i_quirks |= OMXCODEC_VIDEO_QUIRKS_NEED_SIZE;
switch( i_codec )
{
case VLC_CODEC_H264:
case VLC_CODEC_VC1:
i_quirks |= OMXCODEC_QUIRKS_NEED_CSD;
break;
}
} else if( i_cat == AUDIO_ES )
{
switch( i_codec )
{
case VLC_CODEC_VORBIS:
case VLC_CODEC_MP4A:
i_quirks |= OMXCODEC_QUIRKS_NEED_CSD;
break;
}
}
/* p_name is not '\0' terminated */
for( const struct str2quirks *p_q_prefix = quirks_prefix; p_q_prefix->psz_name;
p_q_prefix++ )
{
const char *psz_prefix = p_q_prefix->psz_name;
if( !strncmp( p_name, psz_prefix,
__MIN( strlen(psz_prefix), i_name_len ) ) )
i_quirks |= p_q_prefix->i_quirks;
}
for( const struct str2quirks *p_q_suffix = quirks_suffix; p_q_suffix->psz_name;
p_q_suffix++ )
{
const char *psz_suffix = p_q_suffix->psz_name;
size_t i_suffix_len = strlen( psz_suffix );
if( i_name_len > i_suffix_len
&& !strncmp( p_name + i_name_len - i_suffix_len, psz_suffix,
i_suffix_len ) )
i_quirks |= p_q_suffix->i_quirks;
}
return i_quirks;
}
/*****************************************************************************
* Logging utility functions
*****************************************************************************/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment