omx: add OMXCodec_GetQuirks
authorThomas Guillem <thomas@gllm.fr>
Fri, 28 Aug 2015 10:19:32 +0000 (12:19 +0200)
committerThomas Guillem <thomas@gllm.fr>
Thu, 3 Sep 2015 12:27:29 +0000 (14:27 +0200)
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.

modules/codec/omxil/mediacodec.c
modules/codec/omxil/omxil.c
modules/codec/omxil/omxil.h
modules/codec/omxil/omxil_utils.h
modules/codec/omxil/utils.c

index 605531e..6b9a16a 100644 (file)
@@ -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;
index 30ee789..a7aa66b 100644 (file)
@@ -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;
 
index ba97418..ccfd5df 100644 (file)
@@ -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;
 
index 04a56bd..5273b8e 100644 (file)
@@ -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
  *****************************************************************************/
index 8cd00d4..5de3398 100644 (file)
@@ -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
  *****************************************************************************/