From: Gildas Bazin Date: Sun, 25 Apr 2004 14:15:29 +0000 (+0000) Subject: * src/stream_output/stream_output.c: small sout_cfg_parser() changes. X-Git-Tag: 0.7.2~267 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=3ef2227a289c65c86c5e09f272b166977c66ac77;p=vlc * src/stream_output/stream_output.c: small sout_cfg_parser() changes. * 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. --- diff --git a/include/vlc_codec.h b/include/vlc_codec.h index c0b7617aa9..5224a1bdd8 100644 --- a/include/vlc_codec.h +++ b/include/vlc_codec.h @@ -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; }; /** diff --git a/modules/codec/ffmpeg/encoder.c b/modules/codec/ffmpeg/encoder.c index 839daec56d..1343e7146d 100644 --- a/modules/codec/ffmpeg/encoder.c +++ b/modules/codec/ffmpeg/encoder.c @@ -5,7 +5,7 @@ * $Id$ * * Authors: Laurent Aimar - * Gildas Bazin + * Gildas Bazin * Christophe Massiot * * This program is free software; you can redistribute it and/or modify @@ -29,6 +29,7 @@ #include #include #include +#include #include /* 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 } } diff --git a/modules/codec/ffmpeg/ffmpeg.c b/modules/codec/ffmpeg/ffmpeg.c index 676b9af54a..5cca52de18 100644 --- a/modules/codec/ffmpeg/ffmpeg.c +++ b/modules/codec/ffmpeg/ffmpeg.c @@ -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" ) ); diff --git a/modules/codec/ffmpeg/ffmpeg.h b/modules/codec/ffmpeg/ffmpeg.h index 897141198a..ae9c58ebfa 100644 --- a/modules/codec/ffmpeg/ffmpeg.h +++ b/modules/codec/ffmpeg/ffmpeg.h @@ -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 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." ) diff --git a/modules/codec/ffmpeg/video.c b/modules/codec/ffmpeg/video.c index 53b6d42aed..13f951dfb0 100644 --- a/modules/codec/ffmpeg/video.c +++ b/modules/codec/ffmpeg/video.c @@ -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; } diff --git a/modules/stream_out/duplicate.c b/modules/stream_out/duplicate.c index fc60ca9dc5..17d81f7dcb 100644 --- a/modules/stream_out/duplicate.c +++ b/modules/stream_out/duplicate.c @@ -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; diff --git a/modules/stream_out/transcode.c b/modules/stream_out/transcode.c index fa022c1d79..46627e8039 100644 --- a/modules/stream_out/transcode.c +++ b/modules/stream_out/transcode.c @@ -48,16 +48,106 @@ /***************************************************************************** * 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; diff --git a/src/stream_output/stream_output.c b/src/stream_output/stream_output.c index 5732a69c3e..dbb3596b1d 100644 --- a/src/stream_output/stream_output.c +++ b/src/stream_output/stream_output.c @@ -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 )