]> git.sesse.net Git - vlc/blobdiff - modules/stream_out/transcode.c
Qt4 - Small correction to previous commit. Sorry.
[vlc] / modules / stream_out / transcode.c
index 2d6eddf22dee9f8d4006fa0d3ba4c182b509b053..131015e7c362a298759b04617e6749115da719d7 100644 (file)
 #include <math.h>
 
 #include <vlc/vlc.h>
-#include <vlc/input.h>
-#include <vlc/sout.h>
-#include <vlc/vout.h>
-#include <vlc/decoder.h>
+#include <vlc_input.h>
+#include <vlc_sout.h>
+#include <vlc_aout.h>
+#include <vlc_vout.h>
+#include <vlc_codec.h>
+#include <vlc_block.h>
 #include <vlc_filter.h>
 #include <vlc_osd.h>
 
 #define MASTER_SYNC_MAX_DRIFT 100000
 
+/* FIXME Ugly */
+#include "../../src/input/input_internal.h"
+
 /*****************************************************************************
  * Module descriptor
  *****************************************************************************/
     "associated options)." )
 #define SCODEC_TEXT N_("Destination subtitles codec")
 #define SCODEC_LONGTEXT N_( \
-    "This is the subtitles coded that will be used." )
+    "This is the subtitles codec that will be used." )
 
 #define SFILTER_TEXT N_("Overlays")
 #define SFILTER_LONGTEXT N_( \
@@ -221,7 +226,7 @@ vlc_module_begin();
                  MAXWIDTH_LONGTEXT, VLC_TRUE );
     add_integer( SOUT_CFG_PREFIX "maxheight", 0, NULL, MAXHEIGHT_TEXT,
                  MAXHEIGHT_LONGTEXT, VLC_TRUE );
-    add_module_list_cat( SOUT_CFG_PREFIX "vfilter", SUBCAT_VIDEO_VFILTER2,
+    add_module_list( SOUT_CFG_PREFIX "vfilter", "video filter2",
                      NULL, NULL,
                      VFILTER_TEXT, VFILTER_LONGTEXT, VLC_FALSE );
 
@@ -372,18 +377,18 @@ struct sout_stream_sys_t
     /* Audio */
     vlc_fourcc_t    i_acodec;   /* codec audio (0 if not transcode) */
     char            *psz_aenc;
-    sout_cfg_t      *p_audio_cfg;
+    config_chain_t  *p_audio_cfg;
     int             i_sample_rate;
     int             i_channels;
     int             i_abitrate;
     char            *psz_afilters[TRANSCODE_FILTERS];
-    sout_cfg_t      *p_afilters_cfg[TRANSCODE_FILTERS];
+    config_chain_t  *p_afilters_cfg[TRANSCODE_FILTERS];
     int             i_afilters;
 
     /* Video */
     vlc_fourcc_t    i_vcodec;   /* codec video (0 if not transcode) */
     char            *psz_venc;
-    sout_cfg_t      *p_video_cfg;
+    config_chain_t  *p_video_cfg;
     int             i_vbitrate;
     double          f_scale;
     double          f_fps;
@@ -391,12 +396,12 @@ struct sout_stream_sys_t
     unsigned int    i_height, i_maxheight;
     vlc_bool_t      b_deinterlace;
     char            *psz_deinterlace;
-    sout_cfg_t      *p_deinterlace_cfg;
+    config_chain_t  *p_deinterlace_cfg;
     int             i_threads;
     vlc_bool_t      b_high_priority;
     vlc_bool_t      b_hurry_up;
     char            *psz_vfilters[TRANSCODE_FILTERS];
-    sout_cfg_t      *p_vfilters_cfg[TRANSCODE_FILTERS];
+    config_chain_t  *p_vfilters_cfg[TRANSCODE_FILTERS];
     int             i_vfilters;
 
     int             i_crop_top;
@@ -428,14 +433,14 @@ struct sout_stream_sys_t
     vlc_fourcc_t    i_scodec;   /* codec spu (0 if not transcode) */
     char            *psz_senc;
     vlc_bool_t      b_soverlay;
-    sout_cfg_t      *p_spu_cfg;
+    config_chain_t  *p_spu_cfg;
     spu_t           *p_spu;
 
     /* OSD Menu */
     sout_stream_id_t *id_osd;   /* extension for streaming OSD menus */
     vlc_fourcc_t    i_osdcodec; /* codec osd menu (0 if not transcode) */
     char            *psz_osdenc;
-    sout_cfg_t      *p_osd_cfg;
+    config_chain_t  *p_osd_cfg;
     vlc_bool_t      b_es_osd;      /* VLC_TRUE when osd es is registered */
     vlc_bool_t      b_sout_osd;
 
@@ -476,7 +481,7 @@ static int Open( vlc_object_t *p_this )
 
     p_sys->i_master_drift = 0;
 
-    sout_CfgParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
+    config_ChainParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
                    p_stream->p_cfg );
 
     /* Audio transcoding parameters */
@@ -486,8 +491,8 @@ static int Open( vlc_object_t *p_this )
     if( val.psz_string && *val.psz_string )
     {
         char *psz_next;
-        psz_next = sout_CfgCreate( &p_sys->psz_aenc, &p_sys->p_audio_cfg,
-                                   val.psz_string );
+        psz_next = config_ChainCreate( &p_sys->psz_aenc, &p_sys->p_audio_cfg,
+                                       val.psz_string );
         if( psz_next ) free( psz_next );
     }
     if( val.psz_string ) free( val.psz_string );
@@ -535,7 +540,7 @@ static int Open( vlc_object_t *p_this )
         while( (psz_parser != NULL) && (*psz_parser != '\0')
                 && (p_sys->i_afilters < TRANSCODE_FILTERS) )
         {
-            psz_parser = sout_CfgCreate(
+            psz_parser = config_ChainCreate(
                                    &p_sys->psz_afilters[p_sys->i_afilters],
                                    &p_sys->p_afilters_cfg[p_sys->i_afilters],
                                    psz_parser );
@@ -557,7 +562,7 @@ static int Open( vlc_object_t *p_this )
     if( val.psz_string && *val.psz_string )
     {
         char *psz_next;
-        psz_next = sout_CfgCreate( &p_sys->psz_venc, &p_sys->p_video_cfg,
+        psz_next = config_ChainCreate( &p_sys->psz_venc, &p_sys->p_video_cfg,
                                    val.psz_string );
         if( psz_next ) free( psz_next );
     }
@@ -607,7 +612,7 @@ static int Open( vlc_object_t *p_this )
         while( (psz_parser != NULL) && (*psz_parser != '\0')
                 && (p_sys->i_vfilters < TRANSCODE_FILTERS) )
         {
-            psz_parser = sout_CfgCreate(
+            psz_parser = config_ChainCreate(
                                    &p_sys->psz_vfilters[p_sys->i_vfilters],
                                    &p_sys->p_vfilters_cfg[p_sys->i_vfilters],
                                    psz_parser );
@@ -631,7 +636,7 @@ static int Open( vlc_object_t *p_this )
     if( val.psz_string && *val.psz_string )
     {
         char *psz_next;
-        psz_next = sout_CfgCreate( &p_sys->psz_deinterlace,
+        psz_next = config_ChainCreate( &p_sys->psz_deinterlace,
                                    &p_sys->p_deinterlace_cfg,
                                    val.psz_string );
         if( psz_next ) free( psz_next );
@@ -699,7 +704,7 @@ static int Open( vlc_object_t *p_this )
     if( val.psz_string && *val.psz_string )
     {
         char *psz_next;
-        psz_next = sout_CfgCreate( &p_sys->psz_senc, &p_sys->p_spu_cfg,
+        psz_next = config_ChainCreate( &p_sys->psz_senc, &p_sys->p_spu_cfg,
                                    val.psz_string );
         if( psz_next ) free( psz_next );
     }
@@ -745,7 +750,7 @@ static int Open( vlc_object_t *p_this )
         vlc_value_t osd_val;
         char *psz_next;
 
-        psz_next = sout_CfgCreate( &p_sys->psz_osdenc,
+        psz_next = config_ChainCreate( &p_sys->psz_osdenc,
                                    &p_sys->p_osd_cfg, strdup( "dvbsub") );
         if( psz_next ) free( psz_next );
 
@@ -795,7 +800,7 @@ static void Close( vlc_object_t * p_this )
 
     while( p_sys->p_audio_cfg != NULL )
     {
-        sout_cfg_t *p_next = p_sys->p_audio_cfg->p_next;
+        config_chain_t *p_next = p_sys->p_audio_cfg->p_next;
 
         if( p_sys->p_audio_cfg->psz_name )
             free( p_sys->p_audio_cfg->psz_name );
@@ -809,7 +814,7 @@ static void Close( vlc_object_t * p_this )
 
     while( p_sys->p_video_cfg != NULL )
     {
-        sout_cfg_t *p_next = p_sys->p_video_cfg->p_next;
+        config_chain_t *p_next = p_sys->p_video_cfg->p_next;
 
         if( p_sys->p_video_cfg->psz_name )
             free( p_sys->p_video_cfg->psz_name );
@@ -823,7 +828,7 @@ static void Close( vlc_object_t * p_this )
 
     while( p_sys->p_deinterlace_cfg != NULL )
     {
-        sout_cfg_t *p_next = p_sys->p_deinterlace_cfg->p_next;
+        config_chain_t *p_next = p_sys->p_deinterlace_cfg->p_next;
 
         if( p_sys->p_deinterlace_cfg->psz_name )
             free( p_sys->p_deinterlace_cfg->psz_name );
@@ -837,7 +842,7 @@ static void Close( vlc_object_t * p_this )
 
     while( p_sys->p_spu_cfg != NULL )
     {
-        sout_cfg_t *p_next = p_sys->p_spu_cfg->p_next;
+        config_chain_t *p_next = p_sys->p_spu_cfg->p_next;
 
         if( p_sys->p_spu_cfg->psz_name )
             free( p_sys->p_spu_cfg->psz_name );
@@ -853,7 +858,7 @@ static void Close( vlc_object_t * p_this )
 
     while( p_sys->p_osd_cfg != NULL )
     {
-        sout_cfg_t *p_next = p_sys->p_osd_cfg->p_next;
+        config_chain_t *p_next = p_sys->p_osd_cfg->p_next;
 
         if( p_sys->p_osd_cfg->psz_name )
             free( p_sys->p_osd_cfg->psz_name );
@@ -1300,8 +1305,11 @@ static int transcode_audio_new( sout_stream_t *p_stream,
     id->p_decoder->fmt_out.audio.i_bitspersample = 
         audio_BitsPerSample( id->p_decoder->fmt_out.i_codec );
     fmt_last = id->p_decoder->fmt_out;
-    /* FIX decoders so we don't have to do this */
-    fmt_last.audio.i_rate = id->p_decoder->fmt_in.audio.i_rate;
+    /* Fix AAC SBR changing number of channels and sampling rate */
+    if( !(id->p_decoder->fmt_in.i_codec == VLC_FOURCC('m','p','4','a') &&
+        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;
 
     /*
      * Open encoder
@@ -1333,13 +1341,22 @@ static int transcode_audio_new( sout_stream_t *p_stream,
     {
         msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_aenc );
         module_Unneed( id->p_decoder, id->p_decoder->p_module );
-        id->p_decoder->p_module = 0;
+        id->p_decoder->p_module = NULL;
         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 =
         audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
 
+    /* Fix AAC SBR changing number of channels and sampling rate */
+    if( id->p_decoder->fmt_in.i_codec == VLC_FOURCC('m','p','4','a') &&
+        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 )
+    {
+      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;
+    }
+
     /* 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 )
@@ -1399,11 +1416,11 @@ static int transcode_audio_new( sout_stream_t *p_stream,
 
     if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels )
     {
-        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 );
-#if 0
-        /* FIXME : this might work, but only if the encoder is restarted */
+#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;
 
@@ -1413,7 +1430,30 @@ static int transcode_audio_new( sout_stream_t *p_stream,
         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, VLC_TRUE );
+        if( !id->p_encoder->p_module )
+        {
+            msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_aenc );
+            transcode_audio_close( p_stream, 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 =
+            audio_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 );
+
         transcode_audio_close( p_stream, id );
         return VLC_EGENERIC;
 #endif
@@ -1449,12 +1489,12 @@ static void transcode_audio_close( sout_stream_t *p_stream,
     /* Close decoder */
     if( id->p_decoder->p_module )
         module_Unneed( id->p_decoder, id->p_decoder->p_module );
-    id->p_decoder->p_module = 0;
+    id->p_decoder->p_module = NULL;
 
     /* Close encoder */
     if( id->p_encoder->p_module )
         module_Unneed( id->p_encoder, id->p_encoder->p_module );
-    id->p_encoder->p_module = 0;
+    id->p_encoder->p_module = NULL;
 
     /* Close filters */
     for( i = 0; i < id->i_filter; i++ )
@@ -1492,7 +1532,7 @@ static int transcode_audio_process( sout_stream_t *p_stream,
                                                           &in )) )
     {
         if( p_input )
-            stats_UpdateInteger( p_input, p_input->counters.p_decoded_audio,
+            stats_UpdateInteger( p_input, p_input->p->counters.p_decoded_audio,
                                  1, NULL );
         if( p_sys->b_master_sync )
         {
@@ -1673,7 +1713,11 @@ static int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_t *id )
      * We'll open it only when we have the first frame. */
     module_Unneed( id->p_encoder, id->p_encoder->p_module );
     if( id->p_encoder->fmt_out.p_extra )
+    {
         free( id->p_encoder->fmt_out.p_extra );
+        id->p_encoder->fmt_out.p_extra = NULL;
+        id->p_encoder->fmt_out.i_extra = 0;
+    }
     id->p_encoder->p_module = NULL;
 
     if( p_sys->i_threads >= 1 )
@@ -2086,7 +2130,7 @@ static int transcode_video_process( sout_stream_t *p_stream,
     {
         subpicture_t *p_subpic = 0;
         if( p_input )
-            stats_UpdateInteger( p_input, p_input->counters.p_decoded_video,
+            stats_UpdateInteger( p_input, p_input->p->counters.p_decoded_video,
                                  1, NULL );
 
         if( p_stream->p_sout->i_out_pace_nocontrol && p_sys->b_hurry_up )
@@ -2296,7 +2340,8 @@ static int transcode_video_process( sout_stream_t *p_stream,
         /* Check if we have a subpicture to overlay */
         if( p_sys->p_spu )
         {
-            p_subpic = spu_SortSubpictures( p_sys->p_spu, p_pic->date );
+            p_subpic = spu_SortSubpictures( p_sys->p_spu, p_pic->date,
+                       VLC_FALSE /* Fixme: check if stream is paused */ );
             /* TODO: get another pic */
         }
 
@@ -2861,7 +2906,7 @@ static int transcode_osd_process( sout_stream_t *p_stream,
     /* Check if we have a subpicture to send */
     if( p_sys->p_spu && in->i_dts > 0)
     {
-        p_subpic = spu_SortSubpictures( p_sys->p_spu, in->i_dts );
+        p_subpic = spu_SortSubpictures( p_sys->p_spu, in->i_dts, VLC_FALSE );
     }
     else
     {