]> git.sesse.net Git - vlc/blobdiff - modules/codec/avcodec/avcodec.c
Mark ffmpeg-fast and ffmpeg-hw as normal preferences.
[vlc] / modules / codec / avcodec / avcodec.c
index 32ac2237247e5e8aac1cedbd128168a245031afb..f2c416fc64e816d0a8d4faa82e1e51beb8139c69 100644 (file)
@@ -32,6 +32,8 @@
 #include <vlc_common.h>
 #include <vlc_plugin.h>
 #include <vlc_codec.h>
 #include <vlc_common.h>
 #include <vlc_plugin.h>
 #include <vlc_codec.h>
+#include <vlc_avcodec.h>
+#include <vlc_cpu.h>
 
 /* ffmpeg header */
 #define HAVE_MMX 1
 
 /* ffmpeg header */
 #define HAVE_MMX 1
 #   include <avcodec.h>
 #endif
 
 #   include <avcodec.h>
 #endif
 
-#if LIBAVCODEC_BUILD < 5000
-#   error You must have a libavcodec >= 5000 (get svn)
-#endif
-
 #include "avcodec.h"
 #include "avcodec.h"
-#include "fourcc.h"
 #include "avutil.h"
 #include "avutil.h"
+#include "chroma.h"
+
+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT( 52, 25, 0 )
+#   error You must update libavcodec to a version >= 52.25.0
+#endif
 
 /*****************************************************************************
  * decoder_sys_t: decoder descriptor
 
 /*****************************************************************************
  * decoder_sys_t: decoder descriptor
@@ -76,131 +78,150 @@ static const char *const enc_hq_list_text[] = {
     N_("rd"), N_("bits"), N_("simple") };
 #endif
 
     N_("rd"), N_("bits"), N_("simple") };
 #endif
 
+#ifdef MERGE_FFMPEG
+# include "../../demux/avformat/avformat.h"
+# include "../../access/avio.h"
+#endif
+
 /*****************************************************************************
  * Module descriptor
  *****************************************************************************/
 /*****************************************************************************
  * Module descriptor
  *****************************************************************************/
-#define MODULE_DESCRIPTION N_( "Various audio and video decoders/encoders" \
+#define MODULE_DESCRIPTION N_( "Various audio and video decoders/encoders " \
         "delivered by the FFmpeg library. This includes (MS)MPEG4, DivX, SV1,"\
         "H261, H263, H264, WMV, WMA, AAC, AMR, DV, MJPEG and other codecs")
 
         "delivered by the FFmpeg library. This includes (MS)MPEG4, DivX, SV1,"\
         "H261, H263, H264, WMV, WMA, AAC, AMR, DV, MJPEG and other codecs")
 
-vlc_module_begin();
-    set_shortname( "FFmpeg");
-    add_shortcut( "ffmpeg" );
-    set_category( CAT_INPUT );
-    set_subcategory( SUBCAT_INPUT_SCODEC );
+vlc_module_begin ()
+    set_shortname( "FFmpeg")
+    add_shortcut( "ffmpeg" )
+    set_category( CAT_INPUT )
+    set_subcategory( SUBCAT_INPUT_VCODEC )
     /* decoder main module */
 #if defined(MODULE_NAME_is_ffmpegaltivec) \
      || (defined(CAN_COMPILE_ALTIVEC) && !defined(NO_ALTIVEC_IN_FFMPEG))
     /* decoder main module */
 #if defined(MODULE_NAME_is_ffmpegaltivec) \
      || (defined(CAN_COMPILE_ALTIVEC) && !defined(NO_ALTIVEC_IN_FFMPEG))
-    set_description( N_("AltiVec FFmpeg audio/video decoder ((MS)MPEG4,SVQ1,H263,WMV,WMA)") );
-    /*add_requirement( ALTIVEC );*/
-    set_capability( "decoder", 71 );
+    set_description( N_("AltiVec FFmpeg audio/video decoder ((MS)MPEG4,SVQ1,H263,WMV,WMA)") )
+    /*add_requirement( ALTIVEC )*/
+    set_capability( "decoder", 71 )
 #else
 #else
-    set_description( N_("FFmpeg audio/video decoder") );
-    set_help( MODULE_DESCRIPTION );
-    set_capability( "decoder", 70 );
+    set_description( N_("FFmpeg audio/video decoder") )
+    set_help( MODULE_DESCRIPTION )
+    set_capability( "decoder", 70 )
 #endif
 #endif
-    set_section( N_("Decoding") , NULL );
-    set_callbacks( OpenDecoder, CloseDecoder );
-
-
-    add_bool( "ffmpeg-dr", 1, NULL, DR_TEXT, DR_TEXT, true );
-    add_integer ( "ffmpeg-error-resilience", 1, NULL, ERROR_TEXT,
-        ERROR_LONGTEXT, true );
-    add_integer ( "ffmpeg-workaround-bugs", 1, NULL, BUGS_TEXT, BUGS_LONGTEXT,
-        false );
-    add_bool( "ffmpeg-hurry-up", 1, NULL, HURRYUP_TEXT, HURRYUP_LONGTEXT,
-        false );
-    add_integer( "ffmpeg-skip-frame", 0, NULL, SKIP_FRAME_TEXT,
-        SKIP_FRAME_LONGTEXT, true );
-        change_integer_range( -1, 4 );
-    add_integer( "ffmpeg-skip-idct", 0, NULL, SKIP_IDCT_TEXT,
-        SKIP_IDCT_LONGTEXT, true );
-        change_integer_range( -1, 4 );
-    add_integer ( "ffmpeg-vismv", 0, NULL, VISMV_TEXT, VISMV_LONGTEXT,
-        true );
-    add_integer ( "ffmpeg-lowres", 0, NULL, LOWRES_TEXT, LOWRES_LONGTEXT,
-        true );
-        change_integer_range( 0, 2 );
-    add_integer ( "ffmpeg-skiploopfilter", 0, NULL, SKIPLOOPF_TEXT,
-                  SKIPLOOPF_LONGTEXT, true );
-        change_integer_list( nloopf_list, nloopf_list_text, NULL );
-
-    add_integer( "ffmpeg-debug", 0, NULL, DEBUG_TEXT, DEBUG_LONGTEXT,
-                 true );
+    set_section( N_("Decoding") , NULL )
+    set_callbacks( OpenDecoder, CloseDecoder )
+
+
+    add_bool( "ffmpeg-dr", true, DR_TEXT, DR_TEXT, true )
+    add_integer ( "ffmpeg-error-resilience", 1, ERROR_TEXT,
+        ERROR_LONGTEXT, true )
+    add_integer ( "ffmpeg-workaround-bugs", 1, BUGS_TEXT, BUGS_LONGTEXT,
+        false )
+    add_bool( "ffmpeg-hurry-up", true, HURRYUP_TEXT, HURRYUP_LONGTEXT,
+        false )
+    add_integer( "ffmpeg-skip-frame", 0, SKIP_FRAME_TEXT,
+        SKIP_FRAME_LONGTEXT, true )
+        change_integer_range( -1, 4 )
+    add_integer( "ffmpeg-skip-idct", 0, SKIP_IDCT_TEXT,
+        SKIP_IDCT_LONGTEXT, true )
+        change_integer_range( -1, 4 )
+    add_integer ( "ffmpeg-vismv", 0, VISMV_TEXT, VISMV_LONGTEXT,
+        true )
+    add_integer ( "ffmpeg-lowres", 0, LOWRES_TEXT, LOWRES_LONGTEXT,
+        true )
+        change_integer_range( 0, 2 )
+    add_bool( "ffmpeg-fast", false, FAST_TEXT, FAST_LONGTEXT, false )
+    add_integer ( "ffmpeg-skiploopfilter", 0, SKIPLOOPF_TEXT,
+                  SKIPLOOPF_LONGTEXT, true )
+        change_safe ()
+        change_integer_list( nloopf_list, nloopf_list_text )
+
+    add_integer( "ffmpeg-debug", 0, DEBUG_TEXT, DEBUG_LONGTEXT,
+                 true )
+#if defined(HAVE_AVCODEC_VAAPI) || defined(HAVE_AVCODEC_DXVA2)
+    add_bool( "ffmpeg-hw", false, HW_TEXT, HW_LONGTEXT, false )
+#endif
+#if defined(FF_THREAD_FRAME)
+    add_integer( "ffmpeg-threads", 0, THREADS_TEXT, THREADS_LONGTEXT, true );
+#endif
+
 
 #ifdef ENABLE_SOUT
     /* encoder submodule */
 
 #ifdef ENABLE_SOUT
     /* encoder submodule */
-    add_submodule();
-    set_section( N_("Encoding") , NULL );
-    set_description( N_("FFmpeg audio/video encoder") );
-    set_capability( "encoder", 100 );
-    set_callbacks( OpenEncoder, CloseEncoder );
-
-    add_string( ENC_CFG_PREFIX "hq", "simple", NULL, ENC_HQ_TEXT,
-                ENC_HQ_LONGTEXT, false );
-        change_string_list( enc_hq_list, enc_hq_list_text, 0 );
-    add_integer( ENC_CFG_PREFIX "keyint", 0, NULL, ENC_KEYINT_TEXT,
-                 ENC_KEYINT_LONGTEXT, false );
-    add_integer( ENC_CFG_PREFIX "bframes", 0, NULL, ENC_BFRAMES_TEXT,
-                 ENC_BFRAMES_LONGTEXT, false );
-    add_bool( ENC_CFG_PREFIX "hurry-up", 0, NULL, ENC_HURRYUP_TEXT,
-              ENC_HURRYUP_LONGTEXT, false );
-    add_bool( ENC_CFG_PREFIX "interlace", 0, NULL, ENC_INTERLACE_TEXT,
-              ENC_INTERLACE_LONGTEXT, true );
-    add_bool( ENC_CFG_PREFIX "interlace-me", 1, NULL, ENC_INTERLACE_ME_TEXT,
-              ENC_INTERLACE_ME_LONGTEXT, true );
-    add_integer( ENC_CFG_PREFIX "vt", 0, NULL, ENC_VT_TEXT,
-                 ENC_VT_LONGTEXT, true );
-    add_bool( ENC_CFG_PREFIX "pre-me", 0, NULL, ENC_PRE_ME_TEXT,
-              ENC_PRE_ME_LONGTEXT, true );
-    add_integer( ENC_CFG_PREFIX "rc-buffer-size", 224*1024*8, NULL,
-                 ENC_RC_BUF_TEXT, ENC_RC_BUF_LONGTEXT, true );
-    add_float( ENC_CFG_PREFIX "rc-buffer-aggressivity", 1.0, NULL,
-               ENC_RC_BUF_AGGR_TEXT, ENC_RC_BUF_AGGR_LONGTEXT, true );
-    add_float( ENC_CFG_PREFIX "i-quant-factor", 0, NULL,
-               ENC_IQUANT_FACTOR_TEXT, ENC_IQUANT_FACTOR_LONGTEXT, true );
-    add_integer( ENC_CFG_PREFIX "noise-reduction", 0, NULL,
-                 ENC_NOISE_RED_TEXT, ENC_NOISE_RED_LONGTEXT, true );
-    add_bool( ENC_CFG_PREFIX "mpeg4-matrix", 0, NULL,
-              ENC_MPEG4_MATRIX_TEXT, ENC_MPEG4_MATRIX_LONGTEXT, true );
-    add_integer( ENC_CFG_PREFIX "qmin", 0, NULL,
-                 ENC_QMIN_TEXT, ENC_QMIN_LONGTEXT, true );
-    add_integer( ENC_CFG_PREFIX "qmax", 0, NULL,
-                 ENC_QMAX_TEXT, ENC_QMAX_LONGTEXT, true );
-    add_bool( ENC_CFG_PREFIX "trellis", 0, NULL,
-              ENC_TRELLIS_TEXT, ENC_TRELLIS_LONGTEXT, true );
-    add_float( ENC_CFG_PREFIX "qscale", 0, NULL,
-               ENC_QSCALE_TEXT, ENC_QSCALE_LONGTEXT, true );
-    add_integer( ENC_CFG_PREFIX "strict", 0, NULL,
-                 ENC_STRICT_TEXT, ENC_STRICT_LONGTEXT, true );
-    add_float( ENC_CFG_PREFIX "lumi-masking", 0.0, NULL,
-               ENC_LUMI_MASKING_TEXT, ENC_LUMI_MASKING_LONGTEXT, true );
-    add_float( ENC_CFG_PREFIX "dark-masking", 0.0, NULL,
-               ENC_DARK_MASKING_TEXT, ENC_DARK_MASKING_LONGTEXT, true );
-    add_float( ENC_CFG_PREFIX "p-masking", 0.0, NULL,
-               ENC_P_MASKING_TEXT, ENC_P_MASKING_LONGTEXT, true );
-    add_float( ENC_CFG_PREFIX "border-masking", 0.0, NULL,
-               ENC_BORDER_MASKING_TEXT, ENC_BORDER_MASKING_LONGTEXT, true );
-    add_integer( ENC_CFG_PREFIX "luma-elim-threshold", 0, NULL,
-                 ENC_LUMA_ELIM_TEXT, ENC_LUMA_ELIM_LONGTEXT, true );
-    add_integer( ENC_CFG_PREFIX "chroma-elim-threshold", 0, NULL,
-                 ENC_CHROMA_ELIM_TEXT, ENC_CHROMA_ELIM_LONGTEXT, true );
-
-#if LIBAVCODEC_VERSION_INT >= ((51<<16)+(40<<8)+4)
+    add_submodule ()
+    add_shortcut( "ffmpeg" )
+    set_section( N_("Encoding") , NULL )
+    set_description( N_("FFmpeg audio/video encoder") )
+    set_capability( "encoder", 100 )
+    set_callbacks( OpenEncoder, CloseEncoder )
+
+    add_string( ENC_CFG_PREFIX "hq", "simple", ENC_HQ_TEXT,
+                ENC_HQ_LONGTEXT, false )
+        change_string_list( enc_hq_list, enc_hq_list_text, 0 )
+    add_integer( ENC_CFG_PREFIX "keyint", 0, ENC_KEYINT_TEXT,
+                 ENC_KEYINT_LONGTEXT, false )
+    add_integer( ENC_CFG_PREFIX "bframes", 0, ENC_BFRAMES_TEXT,
+                 ENC_BFRAMES_LONGTEXT, false )
+    add_bool( ENC_CFG_PREFIX "hurry-up", false, ENC_HURRYUP_TEXT,
+              ENC_HURRYUP_LONGTEXT, false )
+    add_bool( ENC_CFG_PREFIX "interlace", false, ENC_INTERLACE_TEXT,
+              ENC_INTERLACE_LONGTEXT, true )
+    add_bool( ENC_CFG_PREFIX "interlace-me", true, ENC_INTERLACE_ME_TEXT,
+              ENC_INTERLACE_ME_LONGTEXT, true )
+    add_integer( ENC_CFG_PREFIX "vt", 0, ENC_VT_TEXT,
+                 ENC_VT_LONGTEXT, true )
+    add_bool( ENC_CFG_PREFIX "pre-me", false, ENC_PRE_ME_TEXT,
+              ENC_PRE_ME_LONGTEXT, true )
+    add_integer( ENC_CFG_PREFIX "rc-buffer-size", 224*1024*8,
+                 ENC_RC_BUF_TEXT, ENC_RC_BUF_LONGTEXT, true )
+    add_float( ENC_CFG_PREFIX "rc-buffer-aggressivity", 1.0,
+               ENC_RC_BUF_AGGR_TEXT, ENC_RC_BUF_AGGR_LONGTEXT, true )
+    add_float( ENC_CFG_PREFIX "i-quant-factor", 0,
+               ENC_IQUANT_FACTOR_TEXT, ENC_IQUANT_FACTOR_LONGTEXT, true )
+    add_integer( ENC_CFG_PREFIX "noise-reduction", 0,
+                 ENC_NOISE_RED_TEXT, ENC_NOISE_RED_LONGTEXT, true )
+    add_bool( ENC_CFG_PREFIX "mpeg4-matrix", false,
+              ENC_MPEG4_MATRIX_TEXT, ENC_MPEG4_MATRIX_LONGTEXT, true )
+    add_integer( ENC_CFG_PREFIX "qmin", 0,
+                 ENC_QMIN_TEXT, ENC_QMIN_LONGTEXT, true )
+    add_integer( ENC_CFG_PREFIX "qmax", 0,
+                 ENC_QMAX_TEXT, ENC_QMAX_LONGTEXT, true )
+    add_bool( ENC_CFG_PREFIX "trellis", false,
+              ENC_TRELLIS_TEXT, ENC_TRELLIS_LONGTEXT, true )
+    add_float( ENC_CFG_PREFIX "qscale", 0,
+               ENC_QSCALE_TEXT, ENC_QSCALE_LONGTEXT, true )
+    add_integer( ENC_CFG_PREFIX "strict", 0,
+                 ENC_STRICT_TEXT, ENC_STRICT_LONGTEXT, true )
+    add_float( ENC_CFG_PREFIX "lumi-masking", 0.0,
+               ENC_LUMI_MASKING_TEXT, ENC_LUMI_MASKING_LONGTEXT, true )
+    add_float( ENC_CFG_PREFIX "dark-masking", 0.0,
+               ENC_DARK_MASKING_TEXT, ENC_DARK_MASKING_LONGTEXT, true )
+    add_float( ENC_CFG_PREFIX "p-masking", 0.0,
+               ENC_P_MASKING_TEXT, ENC_P_MASKING_LONGTEXT, true )
+    add_float( ENC_CFG_PREFIX "border-masking", 0.0,
+               ENC_BORDER_MASKING_TEXT, ENC_BORDER_MASKING_LONGTEXT, true )
+    add_integer( ENC_CFG_PREFIX "luma-elim-threshold", 0,
+                 ENC_LUMA_ELIM_TEXT, ENC_LUMA_ELIM_LONGTEXT, true )
+    add_integer( ENC_CFG_PREFIX "chroma-elim-threshold", 0,
+                 ENC_CHROMA_ELIM_TEXT, ENC_CHROMA_ELIM_LONGTEXT, true )
+
     /* Audio AAC encoder profile */
     /* Audio AAC encoder profile */
-    add_string( ENC_CFG_PREFIX "aac-profile", "main", NULL,
-                ENC_PROFILE_TEXT, ENC_PROFILE_LONGTEXT, true );
-#endif
+    add_string( ENC_CFG_PREFIX "aac-profile", "low",
+                ENC_PROFILE_TEXT, ENC_PROFILE_LONGTEXT, true )
 #endif /* ENABLE_SOUT */
 
     /* video filter submodule */
 #endif /* ENABLE_SOUT */
 
     /* video filter submodule */
-    add_submodule();
-    set_capability( "video filter2", 0 );
-    set_callbacks( OpenDeinterlace, CloseDeinterlace );
-    set_description( N_("FFmpeg deinterlace video filter") );
-    add_shortcut( "ffmpeg-deinterlace" );
-
-vlc_module_end();
+    add_submodule ()
+    set_capability( "video filter2", 0 )
+    set_callbacks( OpenDeinterlace, CloseDeinterlace )
+    set_description( N_("FFmpeg deinterlace video filter") )
+    add_shortcut( "ffmpeg-deinterlace" )
+
+#ifdef MERGE_FFMPEG
+    add_submodule ()
+#   include "../../demux/avformat/avformat.c"
+    add_submodule ()
+        AVIO_MODULE
+#endif
+vlc_module_end ()
 
 /*****************************************************************************
  * OpenDecoder: probe the decoder and return score
 
 /*****************************************************************************
  * OpenDecoder: probe the decoder and return score
@@ -221,14 +242,6 @@ static int OpenDecoder( vlc_object_t *p_this )
         return VLC_EGENERIC;
     }
 
         return VLC_EGENERIC;
     }
 
-    /* Bail out if buggy decoder */
-    if( i_codec_id == CODEC_ID_AAC )
-    {
-        msg_Dbg( p_dec, "refusing to use ffmpeg's (%s) decoder which is buggy",
-                 psz_namecodec );
-        return VLC_EGENERIC;
-    }
-
     /* Initialization must be done before avcodec_find_decoder() */
     InitLibavcodec(p_this);
 
     /* Initialization must be done before avcodec_find_decoder() */
     InitLibavcodec(p_this);
 
@@ -244,7 +257,7 @@ static int OpenDecoder( vlc_object_t *p_this )
     p_context = avcodec_alloc_context();
     if( !p_context )
         return VLC_ENOMEM;
     p_context = avcodec_alloc_context();
     if( !p_context )
         return VLC_ENOMEM;
-    p_context->debug = config_GetInt( p_dec, "ffmpeg-debug" );
+    p_context->debug = var_InheritInteger( p_dec, "ffmpeg-debug" );
     p_context->opaque = (void *)p_this;
 
     /* Set CPU capabilities */
     p_context->opaque = (void *)p_this;
 
     /* Set CPU capabilities */
@@ -270,6 +283,22 @@ static int OpenDecoder( vlc_object_t *p_this )
     {
         p_context->dsp_mask |= FF_MM_SSE2;
     }
     {
         p_context->dsp_mask |= FF_MM_SSE2;
     }
+#ifdef FF_MM_SSE3
+    if( !(i_cpu & CPU_CAPABILITY_SSE3) )
+        p_context->dsp_mask |= FF_MM_SSE3;
+#endif
+#ifdef FF_MM_SSSE3
+    if( !(i_cpu & CPU_CAPABILITY_SSSE3) )
+        p_context->dsp_mask |= FF_MM_SSSE3;
+#endif
+#ifdef FF_MM_SSE4
+    if( !(i_cpu & CPU_CAPABILITY_SSE4_1) )
+        p_context->dsp_mask |= FF_MM_SSE4;
+#endif
+#ifdef FF_MM_SSE42
+    if( !(i_cpu & CPU_CAPABILITY_SSE4_2) )
+        p_context->dsp_mask |= FF_MM_SSE42;
+#endif
 
     p_dec->b_need_packetized = true;
     switch( i_cat )
 
     p_dec->b_need_packetized = true;
     switch( i_cat )
@@ -284,11 +313,23 @@ static int OpenDecoder( vlc_object_t *p_this )
         i_result =  InitAudioDec ( p_dec, p_context, p_codec,
                                        i_codec_id, psz_namecodec );
         break;
         i_result =  InitAudioDec ( p_dec, p_context, p_codec,
                                        i_codec_id, psz_namecodec );
         break;
+    case SPU_ES:
+        p_dec->pf_decode_sub = DecodeSubtitle;
+        i_result =  InitSubtitleDec( p_dec, p_context, p_codec,
+                                     i_codec_id, psz_namecodec );
+        break;
     default:
         i_result = VLC_EGENERIC;
     }
 
     default:
         i_result = VLC_EGENERIC;
     }
 
-    if( i_result == VLC_SUCCESS ) p_dec->p_sys->i_cat = i_cat;
+    if( i_result == VLC_SUCCESS )
+    {
+        p_dec->p_sys->i_cat = i_cat;
+        if( p_context->profile != FF_PROFILE_UNKNOWN)
+            p_dec->fmt_in.i_profile = p_context->profile;
+        if( p_context->level != FF_LEVEL_UNKNOWN)
+            p_dec->fmt_in.i_level = p_context->level;
+    }
 
     return i_result;
 }
 
     return i_result;
 }
@@ -309,19 +350,22 @@ static void CloseDecoder( vlc_object_t *p_this )
     case VIDEO_ES:
          EndVideoDec ( p_dec );
         break;
     case VIDEO_ES:
          EndVideoDec ( p_dec );
         break;
+    case SPU_ES:
+         EndSubtitleDec( p_dec );
+        break;
     }
 
     if( p_sys->p_context )
     {
     }
 
     if( p_sys->p_context )
     {
-        vlc_mutex_t *lock;
-
-        if( p_sys->p_context->extradata )
-            free( p_sys->p_context->extradata );
+        free( p_sys->p_context->extradata );
         p_sys->p_context->extradata = NULL;
 
         p_sys->p_context->extradata = NULL;
 
-        lock = var_AcquireMutex( "avcodec" );
-        avcodec_close( p_sys->p_context );
-        vlc_mutex_unlock( lock );
+        if( !p_sys->b_delayed_open )
+        {
+            vlc_avcodec_lock();
+            avcodec_close( p_sys->p_context );
+            vlc_avcodec_unlock();
+        }
         msg_Dbg( p_dec, "ffmpeg codec (%s) stopped", p_sys->psz_namecodec );
         av_free( p_sys->p_context );
     }
         msg_Dbg( p_dec, "ffmpeg codec (%s) stopped", p_sys->psz_namecodec );
         av_free( p_sys->p_context );
     }
@@ -331,8 +375,9 @@ static void CloseDecoder( vlc_object_t *p_this )
 
 void InitLibavcodec( vlc_object_t *p_object )
 {
 
 void InitLibavcodec( vlc_object_t *p_object )
 {
-    static int b_ffmpeginit = 0;
-    vlc_mutex_t *lock = var_AcquireMutex( "avcodec" );
+    static bool b_ffmpeginit = false;
+
+    vlc_avcodec_lock();
 
     /* *** init ffmpeg library (libavcodec) *** */
     if( !b_ffmpeginit )
 
     /* *** init ffmpeg library (libavcodec) *** */
     if( !b_ffmpeginit )
@@ -340,9 +385,9 @@ void InitLibavcodec( vlc_object_t *p_object )
         avcodec_init();
         avcodec_register_all();
         av_log_set_callback( LibavutilCallback );
         avcodec_init();
         avcodec_register_all();
         av_log_set_callback( LibavutilCallback );
-        b_ffmpeginit = 1;
+        b_ffmpeginit = true;
 
 
-        msg_Dbg( p_object, "libavcodec initialized (interface %d )",
+        msg_Dbg( p_object, "libavcodec initialized (interface 0x%x)",
                  LIBAVCODEC_VERSION_INT );
     }
     else
                  LIBAVCODEC_VERSION_INT );
     }
     else
@@ -350,5 +395,77 @@ void InitLibavcodec( vlc_object_t *p_object )
         msg_Dbg( p_object, "libavcodec already initialized" );
     }
 
         msg_Dbg( p_object, "libavcodec already initialized" );
     }
 
-    vlc_mutex_unlock( lock );
+    vlc_avcodec_unlock();
+}
+
+/*****************************************************************************
+ * ffmpeg_OpenCodec:
+ *****************************************************************************/
+int ffmpeg_OpenCodec( decoder_t *p_dec )
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+
+    if( p_sys->p_context->extradata_size <= 0 )
+    {
+        if( p_sys->i_codec_id == CODEC_ID_VC1 ||
+            p_sys->i_codec_id == CODEC_ID_VORBIS ||
+            p_sys->i_codec_id == CODEC_ID_THEORA ||
+            p_sys->i_codec_id == CODEC_ID_AAC )
+        {
+            msg_Warn( p_dec, "waiting for extra data for codec %s",
+                      p_sys->psz_namecodec );
+            return 1;
+        }
+    }
+    if( p_dec->fmt_in.i_cat == VIDEO_ES )
+    {
+        p_sys->p_context->width  = p_dec->fmt_in.video.i_width;
+        p_sys->p_context->height = p_dec->fmt_in.video.i_height;
+        p_sys->p_context->bits_per_coded_sample = p_dec->fmt_in.video.i_bits_per_pixel;
+    }
+    else if( p_dec->fmt_in.i_cat == AUDIO_ES )
+    {
+        p_sys->p_context->sample_rate = p_dec->fmt_in.audio.i_rate;
+        p_sys->p_context->channels = p_dec->fmt_in.audio.i_channels;
+
+        p_sys->p_context->block_align = p_dec->fmt_in.audio.i_blockalign;
+        p_sys->p_context->bit_rate = p_dec->fmt_in.i_bitrate;
+        p_sys->p_context->bits_per_coded_sample = p_dec->fmt_in.audio.i_bitspersample;
+    }
+    int ret;
+    vlc_avcodec_lock();
+    ret = avcodec_open( p_sys->p_context, p_sys->p_codec );
+    vlc_avcodec_unlock();
+    if( ret < 0 )
+        return VLC_EGENERIC;
+    msg_Dbg( p_dec, "ffmpeg codec (%s) started", p_sys->psz_namecodec );
+
+#ifdef HAVE_AVCODEC_MT
+    if( p_dec->fmt_in.i_cat == VIDEO_ES )
+    {
+        switch( p_sys->p_context->active_thread_type )
+        {
+            case FF_THREAD_FRAME:
+                msg_Dbg( p_dec, "using frame thread mode with %d threads",
+                         p_sys->p_context->thread_count );
+                break;
+            case FF_THREAD_SLICE:
+                msg_Dbg( p_dec, "using slice thread mode with %d threads",
+                         p_sys->p_context->thread_count );
+                break;
+            case 0:
+                if( p_sys->p_context->thread_count > 1 )
+                    msg_Warn( p_dec, "failed to enable threaded decoding" );
+                break;
+            default:
+                msg_Warn( p_dec, "using unknown thread mode with %d threads",
+                          p_sys->p_context->thread_count );
+                break;
+        }
+    }
+#endif
+
+    p_sys->b_delayed_open = false;
+
+    return VLC_SUCCESS;
 }
 }