]> git.sesse.net Git - vlc/commitdiff
* src/stream_output/stream_output.c: small sout_cfg_parser() changes.
authorGildas Bazin <gbazin@videolan.org>
Sun, 25 Apr 2004 14:15:29 +0000 (14:15 +0000)
committerGildas Bazin <gbazin@videolan.org>
Sun, 25 Apr 2004 14:15:29 +0000 (14:15 +0000)
* modules/stream_out/duplicate.c: small coding style changes.
* modules/stream_out/transcode.c:
  + Forward the aopts{foo=bar,etc..} and vopts={foo=bar,etc...} options to the encoders.
  + Got rid of the ffmpeg encoder specific options.
* modules/codec/ffmpeg/*:
  + Changed the encoder options to normal config options.
  + Parse the options forwarded by transcode.
* include/vlc_codec.h:
  + encoder_t cleanup.
  + include a "sout_cfg_t *" in encoder_t to allow passing options.

include/vlc_codec.h
modules/codec/ffmpeg/encoder.c
modules/codec/ffmpeg/ffmpeg.c
modules/codec/ffmpeg/ffmpeg.h
modules/codec/ffmpeg/video.c
modules/stream_out/duplicate.c
modules/stream_out/transcode.c
src/stream_output/stream_output.c

index c0b7617aa957cc25ca355d99e25f59d5da9691a6..5224a1bdd8ebae3ab2779efea5f38f2adf1c0389 100644 (file)
@@ -111,24 +111,11 @@ struct encoder_t
     /* Properties of the output of the encoder */
     es_format_t         fmt_out;
 
-    /* FIXME: move these to the ffmpeg encoder */
-    int i_key_int;
-    int i_b_frames;
-    int i_vtolerance;
-    int i_qmin;
-    int i_qmax;
-    int i_hq;
-    vlc_bool_t          b_strict_rc;
-    vlc_bool_t          b_pre_me;
-    vlc_bool_t          b_hurry_up;
-    vlc_bool_t          b_interlace;
-    int                 i_rc_buffer_size;
-    float               f_rc_buffer_aggressivity;
-    float               f_i_quant_factor;
-    int                 i_noise_reduction;
-    vlc_bool_t          b_mpeg4_matrix;
+    /* Number of threads to use during encoding */
     int                 i_threads;
-    vlc_bool_t          b_trellis;
+
+    /* Encoder config */
+    sout_cfg_t *p_cfg;
 };
 
 /**
index 839daec56de3b0cf5cfa013fbd569d3762c61e1c..1343e7146d8bd69ca61859450beeb77f3aa08339 100644 (file)
@@ -5,7 +5,7 @@
  * $Id$
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
- *          Gildas Bazin <gbazin@netcourrier.com>
+ *          Gildas Bazin <gbazin@videolan.org>
  *          Christophe Massiot <massiot@via.ecp.fr>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -29,6 +29,7 @@
 #include <vlc/vlc.h>
 #include <vlc/vout.h>
 #include <vlc/aout.h>
+#include <vlc/sout.h>
 #include <vlc/decoder.h>
 
 /* ffmpeg header */
@@ -115,6 +116,31 @@ struct encoder_sys_t
     int i_frame_size;
     int i_samples_delay;
     mtime_t i_pts;
+
+    /* Encoding settings */
+    int        i_key_int;
+    int        i_b_frames;
+    int        i_vtolerance;
+    int        i_qmin;
+    int        i_qmax;
+    int        i_hq;
+    vlc_bool_t b_strict_rc;
+    int        i_rc_buffer_size;
+    float      f_rc_buffer_aggressivity;
+    vlc_bool_t b_pre_me;
+    vlc_bool_t b_hurry_up;
+    vlc_bool_t b_interlace;
+    float      f_i_quant_factor;
+    int        i_noise_reduction;
+    vlc_bool_t b_mpeg4_matrix;
+    vlc_bool_t b_trellis;
+};
+
+static const char *ppsz_enc_options[] = {
+    "keyint", "bframes", "vt", "qmin", "qmax", "hq", "strict_rc",
+    "rc_buffer_size", "rc_buffer_aggressivity", "pre_me", "hurry_up",
+    "interlace", "i_quant_factor", "noise_reduction", "mpeg4_matrix",
+    "trellis", NULL
 };
 
 /*****************************************************************************
@@ -131,6 +157,7 @@ int E_(OpenEncoder)( vlc_object_t *p_this )
     AVCodec *p_codec;
     int i_codec_id, i_cat;
     char *psz_namecodec;
+    vlc_value_t val;
 
     if( !E_(GetFfmpegCodec)( p_enc->fmt_out.i_codec, &i_cat, &i_codec_id,
                              &psz_namecodec ) )
@@ -206,6 +233,68 @@ int E_(OpenEncoder)( vlc_object_t *p_this )
         p_context->dsp_mask |= FF_MM_SSE2;
     }
 
+    sout_ParseCfg( p_enc, ENC_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg );
+
+    var_Get( p_enc, ENC_CFG_PREFIX "keyint", &val );
+    p_sys->i_key_int = val.i_int;
+
+    var_Get( p_enc, ENC_CFG_PREFIX "bframes", &val );
+    p_sys->i_b_frames = val.i_int;
+
+    var_Get( p_enc, ENC_CFG_PREFIX "vt", &val );
+    p_sys->i_vtolerance = val.i_int;
+
+    var_Get( p_enc, ENC_CFG_PREFIX "interlace", &val );
+    p_sys->b_interlace = val.b_bool;
+
+    var_Get( p_enc, ENC_CFG_PREFIX "pre_me", &val );
+    p_sys->b_pre_me = val.b_bool;
+
+    var_Get( p_enc, ENC_CFG_PREFIX "hurry_up", &val );
+    p_sys->b_hurry_up = val.b_bool;
+    if( p_sys->b_hurry_up )
+    {
+        /* hurry up mode needs noise reduction, even small */
+        p_sys->i_noise_reduction = 1;
+    }
+
+    var_Get( p_enc, ENC_CFG_PREFIX "strict_rc", &val );
+    p_sys->b_strict_rc = val.b_bool;
+    var_Get( p_enc, ENC_CFG_PREFIX "rc_buffer_size", &val );
+    p_sys->i_rc_buffer_size = val.i_int;
+    var_Get( p_enc, ENC_CFG_PREFIX "rc_buffer_aggressivity", &val );
+    p_sys->f_rc_buffer_aggressivity = val.f_float;
+
+    var_Get( p_enc, ENC_CFG_PREFIX "i_quant_factor", &val );
+    p_sys->f_i_quant_factor = val.f_float;
+
+    var_Get( p_enc, ENC_CFG_PREFIX "noise_reduction", &val );
+    p_sys->i_noise_reduction = val.i_int;
+
+    var_Get( p_enc, ENC_CFG_PREFIX "mpeg4_matrix", &val );
+    p_sys->b_mpeg4_matrix = val.b_bool;
+
+    var_Get( p_enc, ENC_CFG_PREFIX "hq", &val );
+    if( val.psz_string && *val.psz_string )
+    {
+        if( !strcmp( val.psz_string, "rd" ) )
+            p_sys->i_hq = FF_MB_DECISION_RD;
+        else if( !strcmp( val.psz_string, "bits" ) )
+            p_sys->i_hq = FF_MB_DECISION_BITS;
+        else if( !strcmp( val.psz_string, "simple" ) )
+            p_sys->i_hq = FF_MB_DECISION_SIMPLE;
+        else
+            p_sys->i_hq = FF_MB_DECISION_RD;
+    }
+    if( val.psz_string ) free( val.psz_string );
+
+    var_Get( p_enc, ENC_CFG_PREFIX "qmin", &val );
+    p_sys->i_qmin = val.i_int;
+    var_Get( p_enc, ENC_CFG_PREFIX "qmax", &val );
+    p_sys->i_qmax = val.i_int;
+    var_Get( p_enc, ENC_CFG_PREFIX "trellis", &val );
+    p_sys->b_trellis = val.b_bool;
+
     if( p_enc->fmt_in.i_cat == VIDEO_ES )
     {
         if( !p_enc->fmt_in.video.i_width || !p_enc->fmt_in.video.i_height )
@@ -230,9 +319,9 @@ int E_(OpenEncoder)( vlc_object_t *p_this )
         p_context->i_quant_offset = 0.0;
         p_context->i_quant_factor = -0.8;
 
-        p_context->gop_size = p_enc->i_key_int > 0 ? p_enc->i_key_int : 50;
+        p_context->gop_size = p_sys->i_key_int > 0 ? p_sys->i_key_int : 50;
         p_context->max_b_frames =
-            __MIN( p_enc->i_b_frames, FF_MAX_B_FRAMES );
+            __MIN( p_sys->i_b_frames, FF_MAX_B_FRAMES );
         p_context->b_frame_strategy = 0;
 
 #if LIBAVCODEC_BUILD >= 4687
@@ -249,35 +338,33 @@ int E_(OpenEncoder)( vlc_object_t *p_this )
 
         p_enc->fmt_in.i_codec = VLC_FOURCC('I','4','2','0');
 
-        if ( p_enc->b_strict_rc )
+        if ( p_sys->b_strict_rc )
         {
             p_context->rc_max_rate = p_enc->fmt_out.i_bitrate;
-            p_context->rc_buffer_size = p_enc->i_rc_buffer_size;
-            p_context->rc_buffer_aggressivity = p_enc->f_rc_buffer_aggressivity;
+            p_context->rc_buffer_size = p_sys->i_rc_buffer_size;
+            p_context->rc_buffer_aggressivity = p_sys->f_rc_buffer_aggressivity;
         }
 
-        if ( p_enc->f_i_quant_factor != 0.0 )
-        {
-            p_context->i_quant_factor = p_enc->f_i_quant_factor;
-        }
+        if ( p_sys->f_i_quant_factor != 0.0 )
+            p_context->i_quant_factor = p_sys->f_i_quant_factor;
 
 #if LIBAVCODEC_BUILD >= 4690
-        p_context->noise_reduction = p_enc->i_noise_reduction;
+        p_context->noise_reduction = p_sys->i_noise_reduction;
 #endif
 
-        if ( p_enc->b_mpeg4_matrix )
+        if ( p_sys->b_mpeg4_matrix )
         {
             p_context->intra_matrix = ff_mpeg4_default_intra_matrix;
             p_context->inter_matrix = ff_mpeg4_default_non_intra_matrix;
         }
 
-        if ( p_enc->b_pre_me )
+        if ( p_sys->b_pre_me )
         {
             p_context->pre_me = 1;
             p_context->me_pre_cmp = FF_CMP_CHROMA;
         }
 
-        if ( p_enc->b_interlace )
+        if ( p_sys->b_interlace )
         {
             p_context->flags |= CODEC_FLAG_INTERLACED_DCT;
 #if LIBAVCODEC_BUILD >= 4698
@@ -285,28 +372,24 @@ int E_(OpenEncoder)( vlc_object_t *p_this )
 #endif
         }
 
-        if ( p_enc->b_trellis )
-        {
+        if ( p_sys->b_trellis )
             p_context->flags |= CODEC_FLAG_TRELLIS_QUANT;
-        }
 
 #if LIBAVCODEC_BUILD >= 4702
         if ( p_enc->i_threads >= 1 )
-        {
             p_context->thread_count = p_enc->i_threads;
-        }
 #endif
 
-        if( p_enc->i_vtolerance > 0 )
-        {
-            p_context->bit_rate_tolerance = p_enc->i_vtolerance;
-        }
+        if( p_sys->i_vtolerance > 0 )
+            p_context->bit_rate_tolerance = p_sys->i_vtolerance;
 
-        p_context->mb_qmin = p_context->qmin = p_enc->i_qmin;
-        p_context->mb_qmax = p_context->qmax = p_enc->i_qmax;
+        if( p_sys->i_qmin > 0 )
+            p_context->mb_qmin = p_context->qmin = p_sys->i_qmin;
+        if( p_sys->i_qmax > 0 )
+            p_context->mb_qmax = p_context->qmax = p_sys->i_qmax;
         p_context->max_qdiff = 3;
 
-        p_context->mb_decision = p_enc->i_hq;
+        p_context->mb_decision = p_sys->i_hq;
     }
     else if( p_enc->fmt_in.i_cat == AUDIO_ES )
     {
@@ -517,7 +600,7 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict )
     {
         frame.pts = p_pict->date ? p_pict->date : AV_NOPTS_VALUE;
 
-        if ( p_enc->b_hurry_up && frame.pts != AV_NOPTS_VALUE )
+        if ( p_sys->b_hurry_up && frame.pts != AV_NOPTS_VALUE )
         {
             mtime_t current_date = mdate();
 
@@ -529,24 +612,24 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict )
             }
             else
             {
-                p_sys->p_context->mb_decision = p_enc->i_hq;
+                p_sys->p_context->mb_decision = p_sys->i_hq;
 
                 if ( current_date + HURRY_UP_GUARD2 > frame.pts )
                 {
                     p_sys->p_context->flags &= ~CODEC_FLAG_TRELLIS_QUANT;
 #if LIBAVCODEC_BUILD >= 4690
-                    p_sys->p_context->noise_reduction = p_enc->i_noise_reduction
+                    p_sys->p_context->noise_reduction = p_sys->i_noise_reduction
                          + (HURRY_UP_GUARD2 + current_date - frame.pts) / 500;
 #endif
                     msg_Dbg( p_enc, "hurry up mode 2" );
                 }
                 else
                 {
-                    if ( p_enc->b_trellis )
+                    if ( p_sys->b_trellis )
                         p_sys->p_context->flags |= CODEC_FLAG_TRELLIS_QUANT;
 #if LIBAVCODEC_BUILD >= 4690
                     p_sys->p_context->noise_reduction =
-                                    p_enc->i_noise_reduction;
+                        p_sys->i_noise_reduction;
 #endif
                 }
             }
index 676b9af54ae6517d9a45e8fde29ae3804d1c4bc2..5cca52de18f9f1203bd076663e8f6d02c2d75f47 100644 (file)
@@ -70,6 +70,8 @@ struct decoder_sys_t
 static int OpenDecoder( vlc_object_t * );
 static void CloseDecoder( vlc_object_t * );
 
+static char *enc_hq_list[] = { "rd", "bits", "simple" };
+static char *enc_hq_list_text[] = { N_("rd"), N_("bits"), N_("simple") };
 /*****************************************************************************
  * Module descriptor
  *****************************************************************************/
@@ -93,7 +95,8 @@ vlc_module_begin();
     add_string( "ffmpeg-pp-name", "default", NULL, LIBAVCODEC_PP_TEXT,
         LIBAVCODEC_PP_LONGTEXT, VLC_TRUE );
 #endif
-    add_integer( "ffmpeg-debug", 0, NULL, DEBUG_TEST, DEBUG_LONGTEST, VLC_TRUE );
+    add_integer( "ffmpeg-debug", 0, NULL, DEBUG_TEXT, DEBUG_LONGTEXT,
+                 VLC_TRUE );
 
     /* chroma conversion submodule */
     add_submodule();
@@ -107,6 +110,40 @@ vlc_module_begin();
     set_capability( "encoder", 100 );
     set_callbacks( E_(OpenEncoder), E_(CloseEncoder) );
 
+    add_string( ENC_CFG_PREFIX "hq", "simple", NULL, ENC_HQ_TEXT,
+                ENC_HQ_LONGTEXT, VLC_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, VLC_FALSE );
+    add_integer( ENC_CFG_PREFIX "bframes", 0, NULL, ENC_BFRAMES_TEXT,
+                 ENC_BFRAMES_LONGTEXT, VLC_FALSE );
+    add_bool( ENC_CFG_PREFIX "hurry_up", 0, NULL, ENC_HURRYUP_TEXT,
+              ENC_HURRYUP_LONGTEXT, VLC_FALSE );
+    add_bool( ENC_CFG_PREFIX "interlace", 0, NULL, ENC_INTERLACE_TEXT,
+              ENC_INTERLACE_LONGTEXT, VLC_TRUE );
+    add_integer( ENC_CFG_PREFIX "vt", 0, NULL, ENC_VT_TEXT,
+                 ENC_VT_LONGTEXT, VLC_TRUE );
+    add_bool( ENC_CFG_PREFIX "pre_me", 0, NULL, ENC_PRE_ME_TEXT,
+              ENC_PRE_ME_LONGTEXT, VLC_TRUE );
+    add_bool( ENC_CFG_PREFIX "strict_rc", 0, NULL, ENC_RC_STRICT_TEXT,
+              ENC_RC_STRICT_LONGTEXT, VLC_TRUE );
+    add_integer( ENC_CFG_PREFIX "rc_buffer_size", 224*1024*8 * 3/2, NULL,
+                 ENC_RC_BUF_TEXT, ENC_RC_BUF_LONGTEXT, VLC_TRUE );
+    add_float( ENC_CFG_PREFIX "rc_buffer_aggressivity", 0.1, NULL,
+               ENC_RC_BUF_AGGR_TEXT, ENC_RC_BUF_AGGR_LONGTEXT, VLC_TRUE );
+    add_float( ENC_CFG_PREFIX "i_quant_factor", 0, NULL,
+               ENC_QUANT_FACTOR_TEXT, ENC_QUANT_FACTOR_LONGTEXT, VLC_TRUE );
+    add_integer( ENC_CFG_PREFIX "noise_reduction", 0, NULL,
+                 ENC_NOISE_RED_TEXT, ENC_NOISE_RED_LONGTEXT, VLC_TRUE );
+    add_bool( ENC_CFG_PREFIX "mpeg4_matrix", 0, NULL,
+              ENC_MPEG4_MATRIX_TEXT, ENC_MPEG4_MATRIX_LONGTEXT, VLC_TRUE );
+    add_integer( ENC_CFG_PREFIX "qmin", 0, NULL,
+                 ENC_QMIN_TEXT, ENC_QMIN_LONGTEXT, VLC_TRUE );
+    add_integer( ENC_CFG_PREFIX "qmax", 0, NULL,
+                 ENC_QMAX_TEXT, ENC_QMAX_LONGTEXT, VLC_TRUE );
+    add_bool( ENC_CFG_PREFIX "trellis", 0, NULL,
+              ENC_TRELLIS_TEXT, ENC_TRELLIS_LONGTEXT, VLC_TRUE );
+
     /* demux submodule */
     add_submodule();
     set_description( _("ffmpeg demuxer" ) );
index 897141198a9357c23b14e426c9c9a7ace2411b8b..ae9c58ebfae4379052be4c1241d38d535b23b113 100644 (file)
@@ -108,8 +108,8 @@ void E_(ClosePostproc)( decoder_t *, void * );
     "Higher levels require considerable more CPU power, but produce " \
     "better looking pictures." )
 
-#define DEBUG_TEST N_( "Debug mask" )
-#define DEBUG_LONGTEST N_( "Set ffmpeg debug mask" )
+#define DEBUG_TEXT N_( "Debug mask" )
+#define DEBUG_LONGTEXT N_( "Set ffmpeg debug mask" )
 
 #define LIBAVCODEC_PP_TEXT N_("ffmpeg postproc filter chains")
 /* FIXME (cut/past from ffmpeg */
@@ -147,3 +147,73 @@ void E_(ClosePostproc)( decoder_t *, void * );
 "tn     tmpnoise        (3 Thresholds)          Temporal Noise Reducer\n" \
 "                       1. <= 2. <= 3.          larger -> stronger filtering\n" \
 "fq     forceQuant      <quantizer>             Force quantizer\n"
+
+/*
+ * Encoder options
+ */
+#define ENC_CFG_PREFIX "sout-ffmpeg-"
+
+#define ENC_KEYINT_TEXT N_( "Ratio of key frames" )
+#define ENC_KEYINT_LONGTEXT N_( "Allows you to specify the number of frames " \
+  "that will be coded for one key frame." )
+
+#define ENC_BFRAMES_TEXT N_( "Ratio of B frames" )
+#define ENC_BFRAMES_LONGTEXT N_( "Allows you to specify the number of " \
+  "B frames that will be coded between two reference frames." )
+
+#define ENC_VT_TEXT N_( "Video bitrate tolerance" )
+#define ENC_VT_LONGTEXT N_( "Allows you to specify the video bitrate " \
+  "tolerance in kbit/s." )
+
+#define ENC_INTERLACE_TEXT N_( "Enable interlaced encoding" )
+#define ENC_INTERLACE_LONGTEXT N_( "Allows you to enable interlaced " \
+  "encoding." )
+
+#define ENC_PRE_ME_TEXT N_( "Enable pre motion estimation" )
+#define ENC_PRE_ME_LONGTEXT N_( "Allows you to enable the pre motion " \
+  "estimation." )
+
+#define ENC_RC_STRICT_TEXT N_( "Enable strict rate control" )
+#define ENC_RC_STRICT_LONGTEXT N_( "Allows you to enable the strict rate " \
+  "control algorithm." )
+
+#define ENC_RC_BUF_TEXT N_( "Rate control buffer size" )
+#define ENC_RC_BUF_LONGTEXT N_( "Allows you to specify the rate control " \
+  "buffer size." )
+
+#define ENC_RC_BUF_AGGR_TEXT N_( "Rate control buffer aggressivity" )
+#define ENC_RC_BUF_AGGR_LONGTEXT N_( "Allows you to specify the rate control "\
+  "buffer agressivity." )
+
+#define ENC_QUANT_FACTOR_TEXT N_( "Quantization factor" )
+#define ENC_QUANT_FACTOR_LONGTEXT N_( "Allows you to specify the " \
+  "quantization factor." )
+
+#define ENC_NOISE_RED_TEXT N_( "Noise reduction" )
+#define ENC_NOISE_RED_LONGTEXT N_( "Allows you to specify the noise " \
+  "reduction." )
+
+#define ENC_MPEG4_MATRIX_TEXT N_( "Enable mpeg4 quantization matrix" )
+#define ENC_MPEG4_MATRIX_LONGTEXT N_( "Allows you to use the mpeg4 " \
+  "quantization matrix for mpeg2 encoding." )
+
+#define ENC_HQ_TEXT N_( "Quality level" )
+#define ENC_HQ_LONGTEXT N_( "Allows you to specify the quality level " \
+  "for the encoding." )
+
+#define ENC_HURRYUP_TEXT N_( "Hurry up" )
+#define ENC_HURRYUP_LONGTEXT N_( "Allows you to specify if the encoder " \
+  "should make on-the-fly quality tradeoffs if your CPU can't keep up with " \
+  "the encoding rate." )
+
+#define ENC_QMIN_TEXT N_( "Minimum video quantizer scale" )
+#define ENC_QMIN_LONGTEXT N_( "Allows you to specify the minimum video " \
+  "quantizer scale." )
+
+#define ENC_QMAX_TEXT N_( "Maximum video quantizer scale" )
+#define ENC_QMAX_LONGTEXT N_( "Allows you to specify the maximum video " \
+  "quantizer scale." )
+
+#define ENC_TRELLIS_TEXT N_( "Enable trellis quantization" )
+#define ENC_TRELLIS_LONGTEXT N_( "Allows you to enable trellis " \
+  "quantization." )
index 53b6d42aed9562782b83529d288ece909e70ac02..13f951dfb0f3fb1b47579536000a7927dd874aeb 100644 (file)
@@ -400,6 +400,9 @@ picture_t *E_(DecodeVideo)( decoder_t *p_dec, block_t **pp_block )
         p_sys->i_buffer = 0;
         p_sys->i_pts = 0; /* To make sure we recover properly */
 
+        p_sys->input_pts = p_sys->input_dts = 0;
+        p_sys->i_late_frames = 0;
+
         block_Release( p_block );
         return NULL;
     }
index fc60ca9dc581e1dfac6928a9144bcf45a91d7d2a..17d81f7dcb5c13cc6e2b49943814ea16c88d5aca 100644 (file)
@@ -141,7 +141,7 @@ static void Close( vlc_object_t * p_this )
 
     int i;
 
-    msg_Dbg( p_stream, "closing a duplication");
+    msg_Dbg( p_stream, "closing a duplication" );
     for( i = 0; i < p_sys->i_nb_streams; i++ )
     {
         sout_stream_delete( p_sys->pp_streams[i] );
@@ -176,9 +176,8 @@ static sout_stream_id_t * Add( sout_stream_t *p_stream, es_format_t *p_fmt )
     id->pp_ids   = NULL;
 
     msg_Dbg( p_stream, "duplicated a new stream codec=%4.4s (es=%d group=%d)",
-             (char*)&p_fmt->i_codec,
-             p_fmt->i_id,
-             p_fmt->i_group );
+             (char*)&p_fmt->i_codec, p_fmt->i_id, p_fmt->i_group );
+
     for( i_stream = 0; i_stream < p_sys->i_nb_streams; i_stream++ )
     {
         void *id_new = NULL;
index fa022c1d7990524a9a8ed706665b132330cb20a9..46627e8039001ebe719cb723a8dc434771081eb4 100644 (file)
 /*****************************************************************************
  * Module descriptor
  *****************************************************************************/
+#define VCODEC_TEXT N_("Destination video codec")
+#define VCODEC_LONGTEXT N_( \
+    "Allows you to pecify the destination video codec used for the streaming "\
+    "output." )
+#define VB_TEXT N_("Video bitrate")
+#define VB_LONGTEXT N_( \
+    "Allows you to specify the video bitrate used for the streaming " \
+    "output." )
+#define SCALE_TEXT N_("Video scaling")
+#define SCALE_LONGTEXT N_( \
+    "Allows you to scale the video before encoding." )
+#define DEINTERLACE_TEXT N_("Deinterlace video")
+#define DEINTERLACE_LONGTEXT N_( \
+    "Allows you to deinterlace the video before encoding." )
+#define WIDTH_TEXT N_("Video width")
+#define WIDTH_LONGTEXT N_( \
+    "Allows you to specify the output video width." )
+#define HEIGHT_TEXT N_("Video height")
+#define HEIGHT_LONGTEXT N_( \
+    "Allows you to specify the output video height." )
+
+#define CROPTOP_TEXT N_("Video crop top")
+#define CROPTOP_LONGTEXT N_( \
+    "Allows you to specify the top coordinate for the video cropping." )
+#define CROPLEFT_TEXT N_("Video crop left")
+#define CROPLEFT_LONGTEXT N_( \
+    "Allows you to specify the left coordinate for the video cropping." )
+#define CROPBOTTOM_TEXT N_("Video crop bottom")
+#define CROPBOTTOM_LONGTEXT N_( \
+    "Allows you to specify the bottom coordinate for the video cropping." )
+#define CROPRIGHT_TEXT N_("Video crop right")
+#define CROPRIGHT_LONGTEXT N_( \
+    "Allows you to specify the right coordinate for the video cropping." )
+
+#define ACODEC_TEXT N_("Destination audio codec")
+#define ACODEC_LONGTEXT N_( \
+    "Allows you to specify the destination audio codec used for the " \
+    "streaming output." )
+#define AB_TEXT N_("Audio bitrate")
+#define AB_LONGTEXT N_( \
+    "Allows you to specify the audio bitrate used for the streaming " \
+    "output." )
+#define ARATE_TEXT N_("Audio sample rate")
+#define ARATE_LONGTEXT N_( \
+    "Allows you to specify the audio sample rate used for the streaming " \
+    "output." )
+#define ACHANS_TEXT N_("Audio channels")
+#define ACHANS_LONGTEXT N_( \
+    "Allows you to specify the number of audio channels used for the " \
+    "streaming output." )
+
+#define THREADS_TEXT N_("Number of threads")
+#define THREADS_LONGTEXT N_( \
+    "Allows you to specify the number of threads used for the transcoding." )
+
 static int  Open ( vlc_object_t * );
 static void Close( vlc_object_t * );
 
+#define SOUT_CFG_PREFIX "sout-transcode-"
+
 vlc_module_begin();
     set_description( _("Transcode stream output") );
     set_capability( "sout stream", 50 );
     add_shortcut( "transcode" );
     set_callbacks( Open, Close );
-vlc_module_end();
 
+    add_string( SOUT_CFG_PREFIX "vcodec", NULL, NULL, VCODEC_TEXT,
+                VCODEC_LONGTEXT, VLC_FALSE );
+    add_integer( SOUT_CFG_PREFIX "vb", 800 * 1000, NULL, VB_TEXT,
+                 VB_LONGTEXT, VLC_FALSE );
+    add_float( SOUT_CFG_PREFIX "scale", 1, NULL, SCALE_TEXT,
+               SCALE_LONGTEXT, VLC_FALSE );
+    add_bool( SOUT_CFG_PREFIX "deinterlace", 0, NULL, DEINTERLACE_TEXT,
+              DEINTERLACE_LONGTEXT, VLC_FALSE );
+    add_integer( SOUT_CFG_PREFIX "width", 0, NULL, WIDTH_TEXT,
+                 WIDTH_LONGTEXT, VLC_TRUE );
+    add_integer( SOUT_CFG_PREFIX "height", 0, NULL, HEIGHT_TEXT,
+                 HEIGHT_LONGTEXT, VLC_TRUE );
+
+    add_integer( SOUT_CFG_PREFIX "croptop", 0, NULL, CROPTOP_TEXT,
+                 CROPTOP_LONGTEXT, VLC_TRUE );
+    add_integer( SOUT_CFG_PREFIX "cropleft", 0, NULL, CROPLEFT_TEXT,
+                 CROPLEFT_LONGTEXT, VLC_TRUE );
+    add_integer( SOUT_CFG_PREFIX "cropbottom", 0, NULL, CROPBOTTOM_TEXT,
+                 CROPBOTTOM_LONGTEXT, VLC_TRUE );
+    add_integer( SOUT_CFG_PREFIX "cropright", 0, NULL, CROPRIGHT_TEXT,
+                 CROPRIGHT_LONGTEXT, VLC_TRUE );
+
+    add_string( SOUT_CFG_PREFIX "acodec", NULL, NULL, ACODEC_TEXT,
+                ACODEC_LONGTEXT, VLC_FALSE );
+    add_integer( SOUT_CFG_PREFIX "ab", 64000, NULL, AB_TEXT,
+                 AB_LONGTEXT, VLC_FALSE );
+    add_integer( SOUT_CFG_PREFIX "channels", 0, NULL, ACHANS_TEXT,
+                 ACHANS_LONGTEXT, VLC_FALSE );
+    add_integer( SOUT_CFG_PREFIX "samplerate", 0, NULL, ARATE_TEXT,
+                 ARATE_LONGTEXT, VLC_TRUE );
+
+    add_integer( SOUT_CFG_PREFIX "threads", 0, NULL, THREADS_TEXT,
+                 THREADS_LONGTEXT, VLC_TRUE );
+vlc_module_end();
 
 /*****************************************************************************
  * Exported prototypes
@@ -89,6 +179,12 @@ static int pi_channels_maps[6] =
      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
 };
 
+static const char *ppsz_sout_options[] = {
+    "vcodec", "vb", "croptop", "cropbottom", "cropleft", "cropright",
+    "scale", "width", "height", "deinterlace", "threads",
+    "acodec", "ab", "samplerate", "channels", NULL
+};
+
 #define PICTURE_RING_SIZE 64
 
 struct sout_stream_sys_t
@@ -104,33 +200,19 @@ struct sout_stream_sys_t
     int             i_first_pic, i_last_pic;
 
     vlc_fourcc_t    i_acodec;   /* codec audio (0 if not transcode) */
+    sout_cfg_t      *p_audio_cfg;
     int             i_sample_rate;
     int             i_channels;
     int             i_abitrate;
 
     vlc_fourcc_t    i_vcodec;   /*    "   video  " "   "      " */
+    sout_cfg_t      *p_video_cfg;
     int             i_vbitrate;
-    int             i_vtolerance;
     double          f_scale;
     int             i_width;
     int             i_height;
-    int             i_b_frames;
-    int             i_key_int;
-    int             i_qmin;
-    int             i_qmax;
-    vlc_bool_t      i_hq;
     vlc_bool_t      b_deinterlace;
-    vlc_bool_t      b_interlace;
-    vlc_bool_t      b_strict_rc;
-    vlc_bool_t      b_pre_me;
-    vlc_bool_t      b_hurry_up;
-    int             i_rc_buffer_size;
-    float           f_rc_buffer_aggressivity;
-    float           f_i_quant_factor;
-    int             i_noise_reduction;
-    vlc_bool_t      b_mpeg4_matrix;
     int             i_threads;
-    vlc_bool_t      b_trellis;
 
     int             i_crop_top;
     int             i_crop_bottom;
@@ -151,213 +233,119 @@ static int Open( vlc_object_t *p_this )
 {
     sout_stream_t     *p_stream = (sout_stream_t*)p_this;
     sout_stream_sys_t *p_sys;
-    char *codec;
+    vlc_value_t       val;
+    char              *psz_opts;
 
     p_sys = vlc_object_create( p_this, sizeof( sout_stream_sys_t ) );
+
     p_sys->p_out = sout_stream_new( p_stream->p_sout, p_stream->psz_next );
+    if( !p_sys->p_out )
+    {
+        msg_Err( p_stream, "cannot create chain" );
+        free( p_sys );
+        return VLC_EGENERIC;
+    }
 
-    p_sys->f_scale      = 1;
-    p_sys->i_vtolerance = -1;
-    p_sys->i_key_int    = -1;
-    p_sys->i_qmin       = 2;
-    p_sys->i_qmax       = 31;
-    p_sys->f_i_quant_factor = 0.0;
-#if LIBAVCODEC_BUILD >= 4673
-    p_sys->i_hq         = FF_MB_DECISION_SIMPLE;
-#else
-    p_sys->i_hq         = VLC_FALSE;
-#endif
-    p_sys->i_rc_buffer_size = 224*1024*8 * 3/2;
-    p_sys->f_rc_buffer_aggressivity = 0.1;
-    p_sys->i_threads = 0;
-    p_sys->b_trellis = 0;
     p_sys->b_input_has_b_frames = VLC_FALSE;
     p_sys->i_output_pts = 0;
 
-    if( ( codec = sout_cfg_find_value( p_stream->p_cfg, "acodec" ) ) )
+    psz_opts = sout_cfg_find_value( p_stream->p_cfg, "aopts" );
+    p_sys->p_audio_cfg = NULL;
+    if( psz_opts && *psz_opts )
     {
-        char fcc[4] = "    ";
-        char *val;
+        char *psz_name, *psz_next, *psz_tmp;
+        asprintf( &psz_tmp, "aopts%s", psz_opts );
+        psz_next = sout_cfg_parser( &psz_name, &p_sys->p_audio_cfg, psz_tmp );
+        if( psz_next ) free( psz_next );
+        free( psz_tmp );
+    }
 
-        memcpy( fcc, codec, __MIN( strlen( codec ), 4 ) );
+    psz_opts = sout_cfg_find_value( p_stream->p_cfg, "vopts" );
+    p_sys->p_video_cfg = NULL;
+    if( psz_opts && *psz_opts )
+    {
+        char *psz_name, *psz_next, *psz_tmp;
+        asprintf( &psz_tmp, "vopts%s", psz_opts );
+        psz_next = sout_cfg_parser( &psz_name, &p_sys->p_video_cfg, psz_tmp );
+        if( psz_next ) free( psz_next );
+        free( psz_tmp );
+    }
+
+    sout_ParseCfg( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
+                   p_stream->p_cfg );
 
+    /* Audio transcoding parameters */
+    var_Get( p_stream, SOUT_CFG_PREFIX "acodec", &val );
+    p_sys->i_acodec = 0;
+    if( val.psz_string && *val.psz_string )
+    {
+        char fcc[4] = "    ";
+        memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
         p_sys->i_acodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
+    }
+    if( val.psz_string ) free( val.psz_string );
 
-        if( ( val = sout_cfg_find_value( p_stream->p_cfg, "samplerate" ) ) )
-        {
-            p_sys->i_sample_rate = atoi( val );
-        }
-        if( ( val = sout_cfg_find_value( p_stream->p_cfg, "channels" ) ) )
-        {
-            p_sys->i_channels = atoi( val );
-        }
-        if( ( val = sout_cfg_find_value( p_stream->p_cfg, "ab" ) ) )
-        {
-            p_sys->i_abitrate = atoi( val );
-            if( p_sys->i_abitrate < 4000 )
-            {
-                p_sys->i_abitrate *= 1000;
-            }
-        }
+    var_Get( p_stream, SOUT_CFG_PREFIX "ab", &val );
+    p_sys->i_abitrate = val.i_int;
+    if( p_sys->i_abitrate < 4000 ) p_sys->i_abitrate *= 1000;
+
+    var_Get( p_stream, SOUT_CFG_PREFIX "samplerate", &val );
+    p_sys->i_sample_rate = val.i_int;
 
-        msg_Dbg( p_stream, "codec audio=%4.4s %dHz %d channels %dKb/s", fcc,
-                 p_sys->i_sample_rate, p_sys->i_channels,
-                 p_sys->i_abitrate / 1000 );
+    var_Get( p_stream, SOUT_CFG_PREFIX "channels", &val );
+    p_sys->i_channels = val.i_int;
+
+    if( p_sys->i_acodec )
+    {
+        msg_Dbg( p_stream, "codec audio=%4.4s %dHz %d channels %dKb/s",
+                 (char *)&p_sys->i_acodec, p_sys->i_sample_rate,
+                 p_sys->i_channels, p_sys->i_abitrate / 1000 );
     }
 
-    if( ( codec = sout_cfg_find_value( p_stream->p_cfg, "vcodec" ) ) )
+    /* Video transcoding parameters */
+    var_Get( p_stream, SOUT_CFG_PREFIX "vcodec", &val );
+    p_sys->i_vcodec = 0;
+    if( val.psz_string && *val.psz_string )
     {
         char fcc[4] = "    ";
-        char *val;
+        memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
+        p_sys->i_vcodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
+    }
+    if( val.psz_string ) free( val.psz_string );
 
-        memcpy( fcc, codec, __MIN( strlen( codec ), 4 ) );
+    var_Get( p_stream, SOUT_CFG_PREFIX "vb", &val );
+    p_sys->i_vbitrate = val.i_int;
+    if( p_sys->i_vbitrate < 16000 ) p_sys->i_vbitrate *= 1000;
 
-        p_sys->i_vcodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
+    var_Get( p_stream, SOUT_CFG_PREFIX "scale", &val );
+    p_sys->f_scale = val.f_float;
 
-        if( ( val = sout_cfg_find_value( p_stream->p_cfg, "scale" ) ) )
-        {
-            p_sys->f_scale = atof( val );
-        }
-        if( ( val = sout_cfg_find_value( p_stream->p_cfg, "width" ) ) )
-        {
-            p_sys->i_width = atoi( val );
-        }
-        if( ( val = sout_cfg_find_value( p_stream->p_cfg, "height" ) ) )
-        {
-            p_sys->i_height = atoi( val );
-        }
-        if( ( val = sout_cfg_find_value( p_stream->p_cfg, "vb" ) ) )
-        {
-            p_sys->i_vbitrate = atoi( val );
-            if( p_sys->i_vbitrate < 16000 )
-            {
-                p_sys->i_vbitrate *= 1000;
-            }
-        }
-        if( ( val = sout_cfg_find_value( p_stream->p_cfg, "vt" ) ) )
-        {
-            p_sys->i_vtolerance = atoi( val );
-        }
-        if( sout_cfg_find( p_stream->p_cfg, "deinterlace" ) )
-        {
-            p_sys->b_deinterlace = VLC_TRUE;
-        }
-        if( sout_cfg_find( p_stream->p_cfg, "interlace" ) )
-        {
-            p_sys->b_interlace = VLC_TRUE;
-        }
-        if( sout_cfg_find( p_stream->p_cfg, "strict_rc" ) )
-        {
-            p_sys->b_strict_rc = VLC_TRUE;
-        }
-        if( sout_cfg_find( p_stream->p_cfg, "pre_me" ) )
-        {
-            p_sys->b_pre_me = VLC_TRUE;
-        }
-        if( sout_cfg_find( p_stream->p_cfg, "hurry_up" ) )
-        {
-            p_sys->b_hurry_up = VLC_TRUE;
-            /* hurry up mode needs noise reduction, even small */
-            p_sys->i_noise_reduction = 1;
-        }
-        if( ( val = sout_cfg_find_value( p_stream->p_cfg, "rc_buffer_size" ) ) )
-        {
-            p_sys->i_rc_buffer_size = atoi( val );
-        }
-        if( ( val = sout_cfg_find_value( p_stream->p_cfg, "rc_buffer_aggressivity" ) ) )
-        {
-            p_sys->f_rc_buffer_aggressivity = atof( val );
-        }
-        if( ( val = sout_cfg_find_value( p_stream->p_cfg, "i_quant_factor" ) ) )
-        {
-            p_sys->f_i_quant_factor = atof( val );
-        }
-        if( ( val = sout_cfg_find_value( p_stream->p_cfg, "noise_reduction" ) ) )
-        {
-            p_sys->i_noise_reduction = atoi( val );
-        }
-        if( ( val = sout_cfg_find_value( p_stream->p_cfg, "mpeg4_matrix" ) ) )
-        {
-            p_sys->b_mpeg4_matrix = VLC_TRUE;
-        }
-        /* crop */
-        if( ( val = sout_cfg_find_value( p_stream->p_cfg, "croptop" ) ) )
-        {
-            p_sys->i_crop_top = atoi( val );
-        }
-        if( ( val = sout_cfg_find_value( p_stream->p_cfg, "cropbottom" ) ) )
-        {
-            p_sys->i_crop_bottom = atoi( val );
-        }
-        if( ( val = sout_cfg_find_value( p_stream->p_cfg, "cropleft" ) ) )
-        {
-            p_sys->i_crop_left = atoi( val );
-        }
-        if( ( val = sout_cfg_find_value( p_stream->p_cfg, "cropright" ) ) )
-        {
-            p_sys->i_crop_right = atoi( val );
-        }
-        if( ( val = sout_cfg_find_value( p_stream->p_cfg, "keyint" ) ) )
-        {
-            p_sys->i_key_int    = atoi( val );
-        }
-        if( ( val = sout_cfg_find_value( p_stream->p_cfg, "bframes" ) ) )
-        {
-            p_sys->i_b_frames   = atoi( val );
-        }
-#if LIBAVCODEC_BUILD >= 4673
-        if( ( val = sout_cfg_find_value( p_stream->p_cfg, "hq" ) ) )
-        {
-            if( !strcmp( val, "rd" ) )
-            {
-                p_sys->i_hq = FF_MB_DECISION_RD;
-            }
-            else if( !strcmp( val, "bits" ) )
-            {
-                p_sys->i_hq = FF_MB_DECISION_BITS;
-            }
-            else if( !strcmp( val, "simple" ) )
-            {
-                p_sys->i_hq = FF_MB_DECISION_SIMPLE;
-            }
-            else
-            {
-                p_sys->i_hq = FF_MB_DECISION_RD;
-            }
-        }
-#else
-        if( sout_cfg_find( p_stream->p_cfg, "hq" ) )
-        {
-            p_sys->i_hq = VLC_TRUE;
-        }
-#endif
-        if( ( val = sout_cfg_find_value( p_stream->p_cfg, "qmin" ) ) )
-        {
-            p_sys->i_qmin   = atoi( val );
-        }
-        if( ( val = sout_cfg_find_value( p_stream->p_cfg, "qmax" ) ) )
-        {
-            p_sys->i_qmax   = atoi( val );
-        }
-        if( ( val = sout_cfg_find_value( p_stream->p_cfg, "threads" ) ) )
-        {
-            p_sys->i_threads = atoi( val );
-        }
-        if( sout_cfg_find( p_stream->p_cfg, "trellis" ) )
-        {
-            p_sys->b_trellis = VLC_TRUE;
-        }
+    var_Get( p_stream, SOUT_CFG_PREFIX "width", &val );
+    p_sys->i_width = val.i_int;
 
-        msg_Dbg( p_stream, "codec video=%4.4s %dx%d scaling: %f %dkb/s",
-                 fcc, p_sys->i_width, p_sys->i_height, p_sys->f_scale,
-                 p_sys->i_vbitrate / 1000 );
-    }
+    var_Get( p_stream, SOUT_CFG_PREFIX "height", &val );
+    p_sys->i_height = val.i_int;
 
-    if( !p_sys->p_out )
+    var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace", &val );
+    p_sys->b_deinterlace = val.b_bool;
+
+    var_Get( p_stream, SOUT_CFG_PREFIX "croptop", &val );
+    p_sys->i_crop_top = val.i_int;
+    var_Get( p_stream, SOUT_CFG_PREFIX "cropbottom", &val );
+    p_sys->i_crop_bottom = val.i_int;
+    var_Get( p_stream, SOUT_CFG_PREFIX "cropleft", &val );
+    p_sys->i_crop_left = val.i_int;
+    var_Get( p_stream, SOUT_CFG_PREFIX "cropright", &val );
+    p_sys->i_crop_right = val.i_int;
+
+    var_Get( p_stream, SOUT_CFG_PREFIX "threads", &val );
+    p_sys->i_threads = val.i_int;
+
+    if( p_sys->i_vcodec )
     {
-        msg_Err( p_stream, "cannot create chain" );
-        free( p_sys );
-        return VLC_EGENERIC;
+        msg_Dbg( p_stream, "codec video=%4.4s %dx%d scaling: %f %dkb/s",
+                 (char *)&p_sys->i_vcodec, p_sys->i_width, p_sys->i_height,
+                 p_sys->f_scale, p_sys->i_vbitrate / 1000 );
     }
 
     p_stream->pf_add    = Add;
@@ -380,6 +368,33 @@ static void Close( vlc_object_t * p_this )
     sout_stream_sys_t   *p_sys = p_stream->p_sys;
 
     sout_stream_delete( p_sys->p_out );
+
+    while( p_sys->p_audio_cfg != NULL )
+    {
+        sout_cfg_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 );
+        if( p_sys->p_audio_cfg->psz_value )
+            free( p_sys->p_audio_cfg->psz_value );
+        free( p_sys->p_audio_cfg );
+
+        p_sys->p_audio_cfg = p_next;
+    }
+
+    while( p_sys->p_video_cfg != NULL )
+    {
+        sout_cfg_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 );
+        if( p_sys->p_video_cfg->psz_value )
+            free( p_sys->p_video_cfg->psz_value );
+        free( p_sys->p_video_cfg );
+
+        p_sys->p_video_cfg = p_next;
+    }
+
     vlc_object_destroy( p_sys );
 }
 
@@ -441,10 +456,13 @@ static sout_stream_id_t * Add( sout_stream_t *p_stream, es_format_t *p_fmt )
         es_format_Init( &id->f_dst, AUDIO_ES, p_sys->i_acodec );
         id->f_dst.i_id    = id->f_src.i_id;
         id->f_dst.i_group = id->f_src.i_group;
-        if( id->f_src.psz_language ) id->f_dst.psz_language = strdup( id->f_src.psz_language );
-        id->f_dst.audio.i_rate = p_sys->i_sample_rate  > 0 ? p_sys->i_sample_rate : id->f_src.audio.i_rate;
-        id->f_dst.audio.i_channels    = p_sys->i_channels > 0 ? p_sys->i_channels : id->f_src.audio.i_channels;
-        id->f_dst.i_bitrate     = p_sys->i_abitrate > 0 ? p_sys->i_abitrate : 64000;
+        if( id->f_src.psz_language )
+            id->f_dst.psz_language = strdup( id->f_src.psz_language );
+        id->f_dst.audio.i_rate = p_sys->i_sample_rate > 0 ?
+            p_sys->i_sample_rate : id->f_src.audio.i_rate;
+        id->f_dst.audio.i_channels = p_sys->i_channels > 0 ?
+            p_sys->i_channels : id->f_src.audio.i_channels;
+        id->f_dst.i_bitrate = p_sys->i_abitrate;
         id->f_dst.audio.i_blockalign = 0;
         id->f_dst.i_extra  = 0;
         id->f_dst.p_extra  = NULL;
@@ -471,8 +489,7 @@ static sout_stream_id_t * Add( sout_stream_t *p_stream, es_format_t *p_fmt )
     {
         msg_Dbg( p_stream,
                  "creating video transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
-                 (char*)&p_fmt->i_codec,
-                 (char*)&p_sys->i_vcodec );
+                 (char*)&p_fmt->i_codec, (char*)&p_sys->i_vcodec );
 
         memcpy( &id->f_src, p_fmt, sizeof( es_format_t ) );
 
@@ -480,12 +497,13 @@ static sout_stream_id_t * Add( sout_stream_t *p_stream, es_format_t *p_fmt )
         es_format_Init( &id->f_dst, VIDEO_ES, p_sys->i_vcodec );
         id->f_dst.i_id    = id->f_src.i_id;
         id->f_dst.i_group = id->f_src.i_group;
-        if( id->f_src.psz_language ) id->f_dst.psz_language = strdup( id->f_src.psz_language );
-        id->f_dst.video.i_width = p_sys->i_width;
-        id->f_dst.video.i_height= p_sys->i_height;
-        id->f_dst.i_bitrate     = p_sys->i_vbitrate > 0 ? p_sys->i_vbitrate : 800*1000;
-        id->f_dst.i_extra       = 0;
-        id->f_dst.p_extra       = NULL;
+        if( id->f_src.psz_language )
+            id->f_dst.psz_language = strdup( id->f_src.psz_language );
+        id->f_dst.video.i_width  = p_sys->i_width;
+        id->f_dst.video.i_height = p_sys->i_height;
+        id->f_dst.i_bitrate = p_sys->i_vbitrate;
+        id->f_dst.i_extra = 0;
+        id->f_dst.p_extra = NULL;
 
         /* build decoder -> filter -> encoder */
         if( transcode_video_ffmpeg_new( p_stream, id ) )
@@ -799,6 +817,11 @@ static int transcode_audio_ffmpeg_new( sout_stream_t *p_stream,
     id->p_encoder->fmt_out.i_codec = id->f_dst.i_codec;
     id->p_encoder->fmt_out.i_bitrate = id->f_dst.i_bitrate;
 
+    id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
+
+    /* Attach object to parent so object variables inheritance works */
+    vlc_object_attach( id->p_encoder, p_stream );
+
     id->p_encoder->p_module =
         module_Need( id->p_encoder, "encoder", NULL, 0 );
     if( !id->p_encoder->p_module )
@@ -831,6 +854,8 @@ static void transcode_audio_ffmpeg_close( sout_stream_t *p_stream,
     av_free( id->ff_dec_c );
 
     module_Unneed( id->p_encoder, id->p_encoder->p_module );
+
+    vlc_object_detach( id->p_encoder );
     vlc_object_destroy( id->p_encoder );
 
     free( id->p_buffer );
@@ -1095,8 +1120,7 @@ static int transcode_audio_ffmpeg_process( sout_stream_t *p_stream,
 static int transcode_video_ffmpeg_new( sout_stream_t *p_stream,
                                        sout_stream_id_t *id )
 {
-    sout_stream_sys_t   *p_sys = p_stream->p_sys;
-
+    sout_stream_sys_t *p_sys = p_stream->p_sys;
     int i_ff_codec;
 
     /* Open decoder */
@@ -1254,23 +1278,7 @@ static int transcode_video_ffmpeg_new( sout_stream_t *p_stream,
     id->p_encoder->fmt_out.i_codec = id->f_dst.i_codec;
     id->p_encoder->fmt_out.i_bitrate = id->f_dst.i_bitrate;
 
-    id->p_encoder->i_vtolerance = p_sys->i_vtolerance;
-    id->p_encoder->i_key_int = p_sys->i_key_int;
-    id->p_encoder->i_b_frames = p_sys->i_b_frames;
-    id->p_encoder->i_qmin = p_sys->i_qmin;
-    id->p_encoder->i_qmax = p_sys->i_qmax;
-    id->p_encoder->i_hq = p_sys->i_hq;
-    id->p_encoder->b_strict_rc = p_sys->b_strict_rc;
-    id->p_encoder->b_pre_me = p_sys->b_pre_me;
-    id->p_encoder->b_hurry_up = p_sys->b_hurry_up;
-    id->p_encoder->b_interlace = p_sys->b_interlace;
-    id->p_encoder->i_rc_buffer_size = p_sys->i_rc_buffer_size;
-    id->p_encoder->f_rc_buffer_aggressivity = p_sys->f_rc_buffer_aggressivity;
-    id->p_encoder->f_i_quant_factor = p_sys->f_i_quant_factor;
-    id->p_encoder->i_noise_reduction = p_sys->i_noise_reduction;
-    id->p_encoder->b_mpeg4_matrix = p_sys->b_mpeg4_matrix;
     id->p_encoder->i_threads = p_sys->i_threads;
-    id->p_encoder->b_trellis = p_sys->b_trellis;
 
     id->p_ff_pic         = avcodec_alloc_frame();
     id->p_ff_pic_tmp0    = NULL;
@@ -1278,6 +1286,11 @@ static int transcode_video_ffmpeg_new( sout_stream_t *p_stream,
     id->p_ff_pic_tmp2    = NULL;
     id->p_vresample      = NULL;
 
+    id->p_encoder->p_cfg = p_sys->p_video_cfg;
+
+    /* Attach object to parent so object variables inheritance works */
+    vlc_object_attach( id->p_encoder, p_stream );
+
     id->p_encoder->p_module =
         module_Need( id->p_encoder, "encoder", NULL, 0 );
 
@@ -1338,6 +1351,7 @@ static void transcode_video_ffmpeg_close ( sout_stream_t *p_stream,
     /* Close encoder */
     if( id->p_encoder->p_module )
         module_Unneed( id->p_encoder, id->p_encoder->p_module );
+    vlc_object_detach( id->p_encoder );
     vlc_object_destroy( id->p_encoder );
 
     /* Misc cleanup */
@@ -1802,7 +1816,7 @@ static int transcode_video_ffmpeg_getframebuf(struct AVCodecContext *p_context,
             !p_frame->reference || !p_sys->i_output_pts )
         {
             p_frame->pts = p_sys->i_input_dts +
-                /* Hack: ffmpeg encoding doesn't like frames with identical pts */
+            /* Hack: ffmpeg encoding doesn't like frames with identical pts */
                 (p_sys->i_output_pts ? 0 : 50000);
         }
         else p_frame->pts = AV_NOPTS_VALUE;
index 5732a69c3e1dcc112278abc246158e74e90488c4..dbb3596b1d56239291529fc902aaa633a8b45dcd 100644 (file)
@@ -704,17 +704,6 @@ static void mrl_Clean( mrl_t *p_mrl )
     module{option=*:option=*}[:module{option=*:...}]
  */
 
-static char *_strndup( char *str, int i_len )
-{
-    char *p;
-
-    p = malloc( i_len + 1 );
-    strncpy( p, str, i_len );
-    p[i_len] = '\0';
-
-    return( p );
-}
-
 /*
  * parse module{options=str, option="str "}:
  *  return a pointer on the rest
@@ -778,7 +767,7 @@ static char *_get_chain_end( char *str )
     }
 }
 
-char * sout_cfg_parser( char **ppsz_name, sout_cfg_t **pp_cfg, char *psz_chain )
+char *sout_cfg_parser( char **ppsz_name, sout_cfg_t **pp_cfg, char *psz_chain )
 {
     sout_cfg_t *p_cfg = NULL;
     char       *p = psz_chain;
@@ -786,24 +775,15 @@ char * sout_cfg_parser( char **ppsz_name, sout_cfg_t **pp_cfg, char *psz_chain )
     *ppsz_name = NULL;
     *pp_cfg    = NULL;
 
-    if( p == NULL )
-    {
-        return NULL;
-    }
+    if( !p ) return NULL;
 
     SKIPSPACE( p );
 
-    while( *p && *p != '{' && *p != ':' && *p != ' ' && *p != '\t' )
-    {
-        p++;
-    }
+    while( *p && *p != '{' && *p != ':' && *p != ' ' && *p != '\t' ) p++;
 
-    if( p == psz_chain )
-    {
-        return NULL;
-    }
+    if( p == psz_chain ) return NULL;
 
-    *ppsz_name = _strndup( psz_chain, p - psz_chain );
+    *ppsz_name = strndup( psz_chain, p - psz_chain );
 
     SKIPSPACE( p );
 
@@ -821,11 +801,8 @@ char * sout_cfg_parser( char **ppsz_name, sout_cfg_t **pp_cfg, char *psz_chain )
 
             psz_name = p;
 
-            while( *p && *p != '=' && *p != ',' && *p != '}' &&
-                   *p != ' ' && *p != '\t' )
-            {
-                p++;
-            }
+            while( *p && *p != '=' && *p != ',' && *p != '{' && *p != '}' &&
+                   *p != ' ' && *p != '\t' ) p++;
 
             /* fprintf( stderr, "name=%s - rest=%s\n", psz_name, p ); */
             if( p == psz_name )
@@ -834,15 +811,16 @@ char * sout_cfg_parser( char **ppsz_name, sout_cfg_t **pp_cfg, char *psz_chain )
                 break;
             }
 
-            cfg.psz_name = _strndup( psz_name, p - psz_name );
+            cfg.psz_name = strndup( psz_name, p - psz_name );
 
             SKIPSPACE( p );
 
-            if( *p == '=' )
+            if( *p == '=' || *p == '{' )
             {
                 char *end;
+                vlc_bool_t b_keep_brackets = (*p == '{');
 
-                p++;
+                if( *p == '=' ) p++;
 
                 end = _get_chain_end( p );
                 if( end <= p )
@@ -851,19 +829,14 @@ char * sout_cfg_parser( char **ppsz_name, sout_cfg_t **pp_cfg, char *psz_chain )
                 }
                 else
                 {
-                    if( *p == '\'' || *p =='"' || *p == '{' )
+                    if( *p == '\'' || *p =='"' ||
+                        ( !b_keep_brackets && *p == '{' ) )
                     {
                         p++;
                         end--;
                     }
-                    if( end <= p )
-                    {
-                        cfg.psz_value = NULL;
-                    }
-                    else
-                    {
-                        cfg.psz_value = _strndup( p, end - p );
-                    }
+                    if( end <= p ) cfg.psz_value = NULL;
+                    else cfg.psz_value = strndup( p, end - p );
                 }
 
                 p = end;
@@ -890,26 +863,19 @@ char * sout_cfg_parser( char **ppsz_name, sout_cfg_t **pp_cfg, char *psz_chain )
                 *pp_cfg = p_cfg;
             }
 
-            if( *p == ',' )
-            {
-                p++;
-            }
+            if( *p == ',' ) p++;
 
             if( *p == '}' )
             {
                 p++;
-
                 break;
             }
         }
     }
 
-    if( *p == ':' )
-    {
-        return( strdup( p + 1 ) );
-    }
+    if( *p == ':' ) return( strdup( p + 1 ) );
 
-    return( NULL );
+    return NULL;
 }
 
 static void sout_cfg_free( sout_cfg_t *p_cfg )