]> git.sesse.net Git - vlc/blobdiff - modules/stream_out/transcode.c
Added and used VLC_CODEC_MP3 when applicable.
[vlc] / modules / stream_out / transcode.c
index 0f4bffd5a88fceeb9e227f538f0fbc1ce1838576..ce71eb8ef999ab6d87343b6d001c6ee3c4e78436 100644 (file)
@@ -38,6 +38,7 @@
 #include <vlc_aout.h>
 #include <vlc_vout.h>
 #include <vlc_codec.h>
+#include <vlc_meta.h>
 #include <vlc_block.h>
 #include <vlc_filter.h>
 #include <vlc_osd.h>
@@ -166,73 +167,73 @@ vlc_module_begin ()
     set_category( CAT_SOUT )
     set_subcategory( SUBCAT_SOUT_STREAM )
     set_section( N_("Video"), NULL )
-    add_string( SOUT_CFG_PREFIX "venc", NULL, NULL, VENC_TEXT,
-                VENC_LONGTEXT, false );
+    add_module( SOUT_CFG_PREFIX "venc", "encoder", NULL, NULL, VENC_TEXT,
+                VENC_LONGTEXT, false )
     add_string( SOUT_CFG_PREFIX "vcodec", NULL, NULL, VCODEC_TEXT,
-                VCODEC_LONGTEXT, false );
+                VCODEC_LONGTEXT, false )
     add_integer( SOUT_CFG_PREFIX "vb", 800 * 1000, NULL, VB_TEXT,
-                 VB_LONGTEXT, false );
+                 VB_LONGTEXT, false )
     add_float( SOUT_CFG_PREFIX "scale", 1, NULL, SCALE_TEXT,
-               SCALE_LONGTEXT, false );
+               SCALE_LONGTEXT, false )
     add_float( SOUT_CFG_PREFIX "fps", 0, NULL, FPS_TEXT,
-               FPS_LONGTEXT, false );
+               FPS_LONGTEXT, false )
     add_bool( SOUT_CFG_PREFIX "hurry-up", true, NULL, HURRYUP_TEXT,
-               HURRYUP_LONGTEXT, false );
+               HURRYUP_LONGTEXT, false )
     add_bool( SOUT_CFG_PREFIX "deinterlace", 0, NULL, DEINTERLACE_TEXT,
-              DEINTERLACE_LONGTEXT, false );
+              DEINTERLACE_LONGTEXT, false )
     add_string( SOUT_CFG_PREFIX "deinterlace-module", "deinterlace", NULL,
                 DEINTERLACE_MODULE_TEXT, DEINTERLACE_MODULE_LONGTEXT,
-                false );
-        change_string_list( ppsz_deinterlace_type, 0, 0 );
+                false )
+        change_string_list( ppsz_deinterlace_type, 0, 0 )
     add_integer( SOUT_CFG_PREFIX "width", 0, NULL, WIDTH_TEXT,
-                 WIDTH_LONGTEXT, true );
+                 WIDTH_LONGTEXT, true )
     add_integer( SOUT_CFG_PREFIX "height", 0, NULL, HEIGHT_TEXT,
-                 HEIGHT_LONGTEXT, true );
+                 HEIGHT_LONGTEXT, true )
     add_integer( SOUT_CFG_PREFIX "maxwidth", 0, NULL, MAXWIDTH_TEXT,
-                 MAXWIDTH_LONGTEXT, true );
+                 MAXWIDTH_LONGTEXT, true )
     add_integer( SOUT_CFG_PREFIX "maxheight", 0, NULL, MAXHEIGHT_TEXT,
-                 MAXHEIGHT_LONGTEXT, true );
+                 MAXHEIGHT_LONGTEXT, true )
     add_module_list( SOUT_CFG_PREFIX "vfilter", "video filter2",
                      NULL, NULL,
-                     VFILTER_TEXT, VFILTER_LONGTEXT, false );
+                     VFILTER_TEXT, VFILTER_LONGTEXT, false )
 
     set_section( N_("Audio"), NULL )
-    add_string( SOUT_CFG_PREFIX "aenc", NULL, NULL, AENC_TEXT,
-                AENC_LONGTEXT, false );
+    add_module( SOUT_CFG_PREFIX "aenc", "encoder", NULL, NULL, AENC_TEXT,
+                AENC_LONGTEXT, false )
     add_string( SOUT_CFG_PREFIX "acodec", NULL, NULL, ACODEC_TEXT,
-                ACODEC_LONGTEXT, false );
+                ACODEC_LONGTEXT, false )
     add_integer( SOUT_CFG_PREFIX "ab", 0, NULL, AB_TEXT,
-                 AB_LONGTEXT, false );
+                 AB_LONGTEXT, false )
     add_integer( SOUT_CFG_PREFIX "channels", 0, NULL, ACHANS_TEXT,
-                 ACHANS_LONGTEXT, false );
+                 ACHANS_LONGTEXT, false )
     add_integer( SOUT_CFG_PREFIX "samplerate", 0, NULL, ARATE_TEXT,
-                 ARATE_LONGTEXT, true );
+                 ARATE_LONGTEXT, true )
     add_bool( SOUT_CFG_PREFIX "audio-sync", 0, NULL, ASYNC_TEXT,
-              ASYNC_LONGTEXT, false );
+              ASYNC_LONGTEXT, false )
     add_module_list( SOUT_CFG_PREFIX "afilter",  "audio filter2",
                      NULL, NULL,
-                     AFILTER_TEXT, AFILTER_LONGTEXT, false );
+                     AFILTER_TEXT, AFILTER_LONGTEXT, false )
 
     set_section( N_("Overlays/Subtitles"), NULL )
-    add_string( SOUT_CFG_PREFIX "senc", NULL, NULL, SENC_TEXT,
-                SENC_LONGTEXT, false );
+    add_module( SOUT_CFG_PREFIX "senc", "encoder", NULL, NULL, SENC_TEXT,
+                SENC_LONGTEXT, false )
     add_string( SOUT_CFG_PREFIX "scodec", NULL, NULL, SCODEC_TEXT,
-                SCODEC_LONGTEXT, false );
+                SCODEC_LONGTEXT, false )
     add_bool( SOUT_CFG_PREFIX "soverlay", 0, NULL, SCODEC_TEXT,
-               SCODEC_LONGTEXT, false );
+               SCODEC_LONGTEXT, false )
     add_module_list( SOUT_CFG_PREFIX "sfilter", "video filter",
                      NULL, NULL,
-                     SFILTER_TEXT, SFILTER_LONGTEXT, false );
+                     SFILTER_TEXT, SFILTER_LONGTEXT, false )
 
     set_section( N_("On Screen Display"), NULL )
     add_bool( SOUT_CFG_PREFIX "osd", 0, NULL, OSD_TEXT,
-              OSD_LONGTEXT, false );
+              OSD_LONGTEXT, false )
 
     set_section( N_("Miscellaneous"), NULL )
     add_integer( SOUT_CFG_PREFIX "threads", 0, NULL, THREADS_TEXT,
-                 THREADS_LONGTEXT, true );
+                 THREADS_LONGTEXT, true )
     add_bool( SOUT_CFG_PREFIX "high-priority", 0, NULL, HP_TEXT, HP_LONGTEXT,
-              true );
+              true )
 
 vlc_module_end ()
 
@@ -432,8 +433,8 @@ static int Open( vlc_object_t *p_this )
 
     if( p_sys->i_acodec )
     {
-        if( p_sys->i_acodec == VLC_FOURCC('m','p','3',0) &&
-            p_sys->i_channels > 2 )
+        if( ( p_sys->i_acodec == VLC_CODEC_MP3 ||
+              p_sys->i_acodec == VLC_CODEC_MPGA ) && p_sys->i_channels > 2 )
         {
             msg_Warn( p_stream, "%d channels invalid for mp3, forcing to 2",
                       p_sys->i_channels );
@@ -597,7 +598,7 @@ static int Open( vlc_object_t *p_this )
                                    &p_sys->p_osd_cfg, strdup( "dvbsub") );
         free( psz_next );
 
-        p_sys->i_osdcodec = VLC_FOURCC('Y','U','V','P' );
+        p_sys->i_osdcodec = VLC_CODEC_YUVP;
 
         msg_Dbg( p_stream, "codec osd=%4.4s", (char *)&p_sys->i_osdcodec );
 
@@ -667,7 +668,7 @@ static void Close( vlc_object_t * p_this )
 
 struct sout_stream_id_t
 {
-    vlc_fourcc_t  b_transcode;
+    bool            b_transcode;
 
     /* id of the out stream */
     void *id;
@@ -692,10 +693,9 @@ static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
     sout_stream_sys_t *p_sys = p_stream->p_sys;
     sout_stream_id_t *id;
 
-    id = malloc( sizeof( sout_stream_id_t ) );
+    id = calloc( 1, sizeof( sout_stream_id_t ) );
     if( !id )
         goto error;
-    memset( id, 0, sizeof(sout_stream_id_t) );
 
     id->id = NULL;
     id->p_decoder = NULL;
@@ -711,7 +711,7 @@ static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
     id->p_decoder->b_pace_control = true;
 
     /* Create encoder object */
-    id->p_encoder = vlc_object_create( p_stream, VLC_OBJECT_ENCODER );
+    id->p_encoder = sout_EncoderCreate( p_stream );
     if( !id->p_encoder )
         goto error;
     vlc_object_attach( id->p_encoder, p_stream );
@@ -950,12 +950,11 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
     sout_stream_sys_t *p_sys = p_stream->p_sys;
     block_t *p_out = NULL;
 
-    if( !id->b_transcode && id->id )
-    {
-        return sout_StreamIdSend( p_sys->p_out, id->id, p_buffer );
-    }
-    else if( !id->b_transcode )
+    if( !id->b_transcode )
     {
+        if( id->id )
+            return sout_StreamIdSend( p_sys->p_out, id->id, p_buffer );
+
         block_Release( p_buffer );
         return VLC_EGENERIC;
     }
@@ -1057,12 +1056,107 @@ static int transcode_audio_filter_allocation_init( filter_t *p_filter,
     return VLC_SUCCESS;
 }
 
+static bool transcode_audio_filter_needed( const es_format_t *p_fmt1, const es_format_t *p_fmt2 )
+{
+    if( p_fmt1->i_codec != p_fmt2->i_codec ||
+        p_fmt1->audio.i_channels != p_fmt2->audio.i_channels ||
+        p_fmt1->audio.i_rate != p_fmt2->audio.i_rate )
+        return true;
+    return false;
+}
+static int transcode_audio_filter_chain_build( sout_stream_t *p_stream, filter_chain_t *p_chain,
+                                               const es_format_t *p_dst, const es_format_t *p_src )
+{
+    if( !transcode_audio_filter_needed( p_dst, p_src ) )
+        return VLC_SUCCESS;
+
+    es_format_t current = *p_src;
+
+    msg_Dbg( p_stream, "Looking for filter "
+             "(%4.4s->%4.4s, channels %d->%d, rate %d->%d)",
+         (const char *)&p_src->i_codec,
+         (const char *)&p_dst->i_codec,
+         p_src->audio.i_channels,
+         p_dst->audio.i_channels,
+         p_src->audio.i_rate,
+         p_dst->audio.i_rate );
+
+    /* If any filter is needed, convert to fl32 */
+    if( current.i_codec != VLC_CODEC_FL32 )
+    {
+        /* First step, convert to fl32 */
+        current.i_codec =
+        current.audio.i_format = VLC_CODEC_FL32;
+
+        if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, &current ) )
+        {
+            msg_Err( p_stream, "Failed to find conversion filter to fl32" );
+            return VLC_EGENERIC;
+        }
+        current = *filter_chain_GetFmtOut( p_chain );
+    }
+
+    /* Fix sample rate */
+    if( current.audio.i_rate != p_dst->audio.i_rate )
+    {
+        current.audio.i_rate = p_dst->audio.i_rate;
+        if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, &current ) )
+        {
+            msg_Err( p_stream, "Failed to find conversion filter for resampling" );
+            return VLC_EGENERIC;
+        }
+        current = *filter_chain_GetFmtOut( p_chain );
+    }
+
+    /* Fix channels */
+    if( current.audio.i_channels != p_dst->audio.i_channels )
+    {
+        current.audio.i_channels = p_dst->audio.i_channels;
+        current.audio.i_physical_channels = p_dst->audio.i_physical_channels;
+        current.audio.i_original_channels = p_dst->audio.i_original_channels;
+
+        if( ( !current.audio.i_physical_channels || !current.audio.i_original_channels ) &&
+            current.audio.i_channels < 6 )
+            current.audio.i_physical_channels =
+            current.audio.i_original_channels = pi_channels_maps[current.audio.i_channels];
+
+        if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, &current ) )
+        {
+            msg_Err( p_stream, "Failed to find conversion filter for channel mixing" );
+            return VLC_EGENERIC;
+        }
+        current = *filter_chain_GetFmtOut( p_chain );
+    }
+
+    /* And last step, convert to the requested codec */
+    if( current.i_codec != p_dst->i_codec )
+    {
+        current.i_codec = p_dst->i_codec;
+        if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, &current ) )
+        {
+            msg_Err( p_stream, "Failed to find conversion filter to %4.4s",
+                     (const char*)&p_dst->i_codec);
+            return VLC_EGENERIC;
+        }
+        current = *filter_chain_GetFmtOut( p_chain );
+    }
+
+    if( transcode_audio_filter_needed( p_dst, &current ) )
+    {
+        /* Weird case, a filter has side effects, doomed */
+        msg_Err( p_stream, "Failed to create a valid audio filter chain" );
+        return VLC_EGENERIC;
+    }
+
+    msg_Dbg( p_stream, "Got complete audio filter chain" );
+    return VLC_SUCCESS;
+}
+
 static int transcode_audio_new( sout_stream_t *p_stream,
                                 sout_stream_id_t *id )
 {
     sout_stream_sys_t *p_sys = p_stream->p_sys;
     es_format_t fmt_last;
-    int i;
 
     /*
      * Open decoder
@@ -1078,7 +1172,7 @@ static int transcode_audio_new( sout_stream_t *p_stream,
     /* id->p_decoder->p_cfg = p_sys->p_audio_cfg; */
 
     id->p_decoder->p_module =
-        module_need( id->p_decoder, "decoder", "$codec", 0 );
+        module_need( id->p_decoder, "decoder", "$codec", false );
     if( !id->p_decoder->p_module )
     {
         msg_Err( p_stream, "cannot find audio decoder" );
@@ -1088,7 +1182,7 @@ static int transcode_audio_new( sout_stream_t *p_stream,
         aout_BitsPerSample( id->p_decoder->fmt_out.i_codec );
     fmt_last = id->p_decoder->fmt_out;
     /* Fix AAC SBR changing number of channels and sampling rate */
-    if( !(id->p_decoder->fmt_in.i_codec == VLC_FOURCC('m','p','4','a') &&
+    if( !(id->p_decoder->fmt_in.i_codec == VLC_CODEC_MP4A &&
         fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate &&
         fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels) )
         fmt_last.audio.i_rate = id->p_decoder->fmt_in.audio.i_rate;
@@ -1128,141 +1222,43 @@ static int transcode_audio_new( sout_stream_t *p_stream,
     id->p_encoder->fmt_in.audio.i_bitspersample =
         aout_BitsPerSample( id->p_encoder->fmt_in.i_codec );
 
-    /* Init filter chain */
-    id->p_f_chain = filter_chain_New( p_stream, "audio filter2", true,
-                    transcode_audio_filter_allocation_init, NULL, NULL );
-    filter_chain_Reset( id->p_f_chain, &fmt_last, &id->p_encoder->fmt_in );
-
-    /* Load conversion filters */
-    if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels ||
-        fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate )
-    {
-        /* We'll have to go through fl32 first */
-        fmt_last.i_codec = fmt_last.audio.i_format = VLC_FOURCC('f','l','3','2');
-        fmt_last.audio.i_bitspersample = aout_BitsPerSample( fmt_last.i_codec );
-        filter_chain_AppendFilter( id->p_f_chain, NULL, NULL, NULL, &fmt_last );
-        fmt_last = *filter_chain_GetFmtOut( id->p_f_chain );
-    }
-
-    for( i = 0; i < 4; i++ )
-    {
-        if( (fmt_last.audio.i_channels !=
-            id->p_encoder->fmt_in.audio.i_channels) ||
-            (fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate) ||
-            (fmt_last.i_codec != id->p_encoder->fmt_in.i_codec) )
-        {
-            msg_Dbg( p_stream, "Looking for filter "
-                     "(%4.4s->%4.4s, channels %d->%d, rate %d->%d)",
-                 (char *)&fmt_last.i_codec,
-                 (char *)&id->p_encoder->fmt_in.i_codec,
-                 fmt_last.audio.i_channels,
-                 id->p_encoder->fmt_in.audio.i_channels,
-                 fmt_last.audio.i_rate,
-                 id->p_encoder->fmt_in.audio.i_rate );
-            filter_chain_AppendFilter( id->p_f_chain, NULL, NULL,
-                                       &fmt_last, &id->p_encoder->fmt_in );
-            fmt_last = *filter_chain_GetFmtOut( id->p_f_chain );
-        }
-        else break;
-    }
-
-    /* Final checks to see if conversions were successful */
-    if( fmt_last.i_codec != id->p_encoder->fmt_in.i_codec )
-    {
-        msg_Err( p_stream, "no audio filter found "
-                           "(%4.4s->%4.4s, channels %d->%d, rate %d->%d)",
-                 (char *)&fmt_last.i_codec,
-                 (char *)&id->p_encoder->fmt_in.i_codec,
-                 fmt_last.audio.i_channels,
-                 id->p_encoder->fmt_in.audio.i_channels,
-                 fmt_last.audio.i_rate,
-                 id->p_encoder->fmt_in.audio.i_rate );
-        transcode_audio_close( id );
-        return VLC_EGENERIC;
-    }
-
-    /* Load user specified audio filters now */
+    /* Load user specified audio filters */
     if( p_sys->psz_af2 )
     {
-        id->p_uf_chain = filter_chain_New( p_stream, "audio filter2", false,
-                       transcode_audio_filter_allocation_init, NULL, NULL );
-        filter_chain_Reset( id->p_uf_chain, &fmt_last, &id->p_encoder->fmt_in );
-        filter_chain_AppendFromString( id->p_uf_chain, p_sys->psz_af2 );
-        fmt_last = *filter_chain_GetFmtOut( id->p_uf_chain );
-    }
-
-    if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels )
-    {
-#if 1
-        module_unneed( id->p_encoder, id->p_encoder->p_module );
-        id->p_encoder->p_module = NULL;
-
-        /* This might work, but only if the encoder is restarted */
-        id->p_encoder->fmt_in.audio.i_channels = fmt_last.audio.i_channels;
-        id->p_encoder->fmt_out.audio.i_channels = fmt_last.audio.i_channels;
-
-        id->p_encoder->fmt_in.audio.i_physical_channels =
-            id->p_encoder->fmt_in.audio.i_original_channels =
-                fmt_last.audio.i_physical_channels;
-        id->p_encoder->fmt_out.audio.i_physical_channels =
-            id->p_encoder->fmt_out.audio.i_original_channels =
-                fmt_last.audio.i_physical_channels;
-
-        msg_Dbg( p_stream, "number of audio channels for mixing changed, "
-                 "trying to reopen the encoder for mixing %i to %i channels",
-                 fmt_last.audio.i_channels,
-                 id->p_encoder->fmt_in.audio.i_channels );
-
-        /* reload encoder */
-        id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
-        id->p_encoder->p_module =
-            module_need( id->p_encoder, "encoder", p_sys->psz_aenc, true );
-        if( !id->p_encoder->p_module ||
-            fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels  ||
-            fmt_last.i_codec != id->p_encoder->fmt_in.i_codec )
+        es_format_t fmt_fl32 = fmt_last;
+        fmt_fl32.i_codec =
+        fmt_fl32.audio.i_format = VLC_CODEC_FL32;
+        if( transcode_audio_filter_chain_build( p_stream, id->p_uf_chain,
+                                                &fmt_fl32, &fmt_last ) )
         {
-            if( id->p_encoder->p_module )
-            {
-                module_unneed( id->p_encoder, id->p_encoder->p_module );
-                id->p_encoder->p_module = NULL;
-            }
-            msg_Err( p_stream, "cannot find audio encoder (module:%s fourcc:%4.4s)",
-                     p_sys->psz_aenc ? p_sys->psz_aenc : "any",
-                     (char *)&p_sys->i_acodec );
             transcode_audio_close( id );
             return VLC_EGENERIC;
         }
-        id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
-        id->p_encoder->fmt_in.audio.i_bitspersample =
-            aout_BitsPerSample( id->p_encoder->fmt_in.i_codec );
-#else
-        msg_Err( p_stream, "no audio filter found for mixing from"
-                 " %i to %i channels", fmt_last.audio.i_channels,
-                 id->p_encoder->fmt_in.audio.i_channels );
+        fmt_last = fmt_fl32;
 
-        transcode_audio_close( id );
-        return VLC_EGENERIC;
-#endif
+        id->p_uf_chain = filter_chain_New( p_stream, "audio filter2", false,
+                                           transcode_audio_filter_allocation_init, NULL, NULL );
+        filter_chain_Reset( id->p_uf_chain, &fmt_last, &fmt_fl32 );
+        if( filter_chain_AppendFromString( id->p_uf_chain, p_sys->psz_af2 ) > 0 )
+            fmt_last = *filter_chain_GetFmtOut( id->p_uf_chain );
     }
 
-    if( fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate )
+    /* Load conversion filters */
+    id->p_f_chain = filter_chain_New( p_stream, "audio filter2", true,
+                    transcode_audio_filter_allocation_init, NULL, NULL );
+    filter_chain_Reset( id->p_f_chain, &fmt_last, &id->p_encoder->fmt_in );
+
+    if( transcode_audio_filter_chain_build( p_stream, id->p_f_chain,
+                                            &id->p_encoder->fmt_in, &fmt_last ) )
     {
-        msg_Err( p_stream, "no audio filter found for resampling from"
-                 " %iHz to %iHz", fmt_last.audio.i_rate,
-                 id->p_encoder->fmt_in.audio.i_rate );
-#if 0
-        /* FIXME : this might work, but only if the encoder is restarted */
-        id->p_encoder->fmt_in.audio.i_rate = fmt_last.audio.i_rate;
-        id->p_encoder->fmt_out.audio.i_rate = fmt_last.audio.i_rate;
-#else
         transcode_audio_close( id );
         return VLC_EGENERIC;
-#endif
     }
+    fmt_last = id->p_encoder->fmt_in;
 
-    /* FIXME: Hack for mp3 transcoding support */
-    if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC( 'm','p','3',' ' ) )
-        id->p_encoder->fmt_out.i_codec = VLC_FOURCC( 'm','p','g','a' );
+    /* */
+    id->p_encoder->fmt_out.i_codec =
+        vlc_fourcc_GetCodec( AUDIO_ES, id->p_encoder->fmt_out.i_codec );
 
     return VLC_SUCCESS;
 }
@@ -1276,16 +1272,20 @@ static void transcode_audio_close( sout_stream_id_t *id )
         module_unneed( id->p_decoder, id->p_decoder->p_module );
     id->p_decoder->p_module = NULL;
 
+    if( id->p_decoder->p_description )
+        vlc_meta_Delete( id->p_decoder->p_description );
+    id->p_decoder->p_description = NULL;
+
     /* Close encoder */
     if( id->p_encoder->p_module )
         module_unneed( id->p_encoder, id->p_encoder->p_module );
     id->p_encoder->p_module = NULL;
 
     /* Close filters */
-    if( id->p_f_chain )
-        filter_chain_Delete( id->p_f_chain );
     if( id->p_uf_chain )
         filter_chain_Delete( id->p_uf_chain );
+    if( id->p_f_chain )
+        filter_chain_Delete( id->p_f_chain );
 }
 
 static int transcode_audio_process( sout_stream_t *p_stream,
@@ -1326,9 +1326,13 @@ static int transcode_audio_process( sout_stream_t *p_stream,
         p_audio_block->i_samples = p_audio_buf->i_nb_samples;
 
         /* Run filter chain */
-        p_audio_block = filter_chain_AudioFilter( id->p_f_chain, p_audio_block );
         if( id->p_uf_chain )
+        {
             p_audio_block = filter_chain_AudioFilter( id->p_uf_chain, p_audio_block );
+            assert( p_audio_block );
+        }
+
+        p_audio_block = filter_chain_AudioFilter( id->p_f_chain, p_audio_block );
         assert( p_audio_block );
 
         p_audio_buf->p_buffer = p_audio_block->p_buffer;
@@ -1464,7 +1468,7 @@ static int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_t *id )
     /* id->p_decoder->p_cfg = p_sys->p_video_cfg; */
 
     id->p_decoder->p_module =
-        module_need( id->p_decoder, "decoder", "$codec", 0 );
+        module_need( id->p_decoder, "decoder", "$codec", false );
 
     if( !id->p_decoder->p_module )
     {
@@ -1535,8 +1539,7 @@ static int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_t *id )
         p_sys->i_last_pic = 0;
         p_sys->p_buffers = NULL;
         p_sys->b_die = p_sys->b_error = 0;
-        if( vlc_thread_create( p_sys, "encoder", EncoderThread, i_priority,
-                               false ) )
+        if( vlc_thread_create( p_sys, "encoder", EncoderThread, i_priority ) )
         {
             msg_Err( p_stream, "cannot spawn encoder thread" );
             module_unneed( id->p_decoder, id->p_decoder->p_module );
@@ -1732,12 +1735,9 @@ static int transcode_video_encoder_open( sout_stream_t *p_stream,
 
     id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
 
-    /* Hack for mp2v/mp1v transcoding support */
-    if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','1','v') ||
-        id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','2','v') )
-    {
-        id->p_encoder->fmt_out.i_codec = VLC_FOURCC('m','p','g','v');
-    }
+    /*  */
+    id->p_encoder->fmt_out.i_codec =
+        vlc_fourcc_GetCodec( VIDEO_ES, id->p_encoder->fmt_out.i_codec );
 
     id->id = sout_StreamIdAdd( p_stream->p_sys->p_out,
                                &id->p_encoder->fmt_out );
@@ -1771,6 +1771,8 @@ static void transcode_video_close( sout_stream_t *p_stream,
     /* Close decoder */
     if( id->p_decoder->p_module )
         module_unneed( id->p_decoder, id->p_decoder->p_module );
+    if( id->p_decoder->p_description )
+        vlc_meta_Delete( id->p_decoder->p_description );
 
     if( id->p_decoder->p_owner )
     {
@@ -2130,7 +2132,7 @@ static picture_t *video_new_buffer( vlc_object_t *p_this, picture_t **pp_ring,
     /* Find an empty space in the picture ring buffer */
     for( i = 0; i < PICTURE_RING_SIZE; i++ )
     {
-        if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
+        if( pp_ring[i] != NULL && pp_ring[i]->i_status == DESTROYED_PICTURE )
         {
             pp_ring[i]->i_status = RESERVED_PICTURE;
             return pp_ring[i];
@@ -2138,7 +2140,7 @@ static picture_t *video_new_buffer( vlc_object_t *p_this, picture_t **pp_ring,
     }
     for( i = 0; i < PICTURE_RING_SIZE; i++ )
     {
-        if( pp_ring[i] == 0 ) break;
+        if( pp_ring[i] == NULL ) break;
     }
 
     if( i == PICTURE_RING_SIZE && p_sys->i_threads >= 1 )
@@ -2155,7 +2157,7 @@ static picture_t *video_new_buffer( vlc_object_t *p_this, picture_t **pp_ring,
         /* Find an empty space in the picture ring buffer */
         for( i = 0; i < PICTURE_RING_SIZE; i++ )
         {
-            if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
+            if( pp_ring[i] != NULL && pp_ring[i]->i_status == DESTROYED_PICTURE )
             {
                 pp_ring[i]->i_status = RESERVED_PICTURE;
                 return pp_ring[i];
@@ -2163,7 +2165,7 @@ static picture_t *video_new_buffer( vlc_object_t *p_this, picture_t **pp_ring,
         }
         for( i = 0; i < PICTURE_RING_SIZE; i++ )
         {
-            if( pp_ring[i] == 0 ) break;
+            if( pp_ring[i] == NULL ) break;
         }
     }
 
@@ -2180,12 +2182,12 @@ static picture_t *video_new_buffer( vlc_object_t *p_this, picture_t **pp_ring,
         i = 0;
     }
 
+    p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
     p_pic = picture_New( p_dec->fmt_out.video.i_chroma,
                          p_dec->fmt_out.video.i_width,
                          p_dec->fmt_out.video.i_height,
                          p_dec->fmt_out.video.i_aspect );
     if( !p_pic ) return NULL;
-    p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
     p_pic->p_sys = calloc( 1, sizeof(picture_sys_t) );
     if( !p_pic->p_sys )
     {
@@ -2274,7 +2276,7 @@ static int transcode_spu_new( sout_stream_t *p_stream, sout_stream_id_t *id )
     /* id->p_decoder->p_cfg = p_sys->p_spu_cfg; */
 
     id->p_decoder->p_module =
-        module_need( id->p_decoder, "decoder", "$codec", 0 );
+        module_need( id->p_decoder, "decoder", "$codec", false );
 
     if( !id->p_decoder->p_module )
     {
@@ -2316,6 +2318,8 @@ static void transcode_spu_close( sout_stream_id_t *id)
     /* Close decoder */
     if( id->p_decoder->p_module )
         module_unneed( id->p_decoder, id->p_decoder->p_module );
+    if( id->p_decoder->p_description )
+        vlc_meta_Delete( id->p_decoder->p_description );
 
     /* Close encoder */
     if( id->p_encoder->p_module )
@@ -2395,7 +2399,7 @@ static int transcode_osd_new( sout_stream_t *p_stream, sout_stream_id_t *id )
 
         /* Open encoder */
         es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
-                        VLC_FOURCC('Y','U','V','A') );
+                        VLC_CODEC_YUVA );
         id->p_encoder->fmt_in.psz_language = strdup( "osd" );
 
         id->p_encoder->p_cfg = p_sys->p_osd_cfg;