00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <stdlib.h>
00030 #include <string.h>
00031 #include <math.h>
00032
00033 #include <vlc/vlc.h>
00034 #include <vlc/input.h>
00035 #include <vlc/sout.h>
00036 #include <vlc/vout.h>
00037 #include <vlc/decoder.h>
00038 #include "vlc_filter.h"
00039 #include "vlc_osd.h"
00040
00041 #define MASTER_SYNC_MAX_DRIFT 100000
00042
00043
00044
00045
00046 #define VENC_TEXT N_("Video encoder")
00047 #define VENC_LONGTEXT N_( \
00048 "Allows you to specify the video encoder to use and its associated " \
00049 "options." )
00050 #define VCODEC_TEXT N_("Destination video codec")
00051 #define VCODEC_LONGTEXT N_( \
00052 "Allows you to specify the destination video codec used for the " \
00053 "streaming output." )
00054 #define VB_TEXT N_("Video bitrate")
00055 #define VB_LONGTEXT N_( \
00056 "Allows you to specify the video bitrate used for the streaming " \
00057 "output." )
00058 #define SCALE_TEXT N_("Video scaling")
00059 #define SCALE_LONGTEXT N_( \
00060 "Allows you to scale the video before encoding." )
00061 #define FPS_TEXT N_("Video frame-rate")
00062 #define FPS_LONGTEXT N_( \
00063 "Allows you to specify an output frame rate for the video." )
00064 #define DEINTERLACE_TEXT N_("Deinterlace video")
00065 #define DEINTERLACE_LONGTEXT N_( \
00066 "Allows you to deinterlace the video before encoding." )
00067 #define DEINTERLACE_MODULE_TEXT N_("Deinterlace module")
00068 #define DEINTERLACE_MODULE_LONGTEXT N_( \
00069 "Specifies the deinterlace module to use." )
00070 #define WIDTH_TEXT N_("Video width")
00071 #define WIDTH_LONGTEXT N_( \
00072 "Allows you to specify the output video width." )
00073 #define HEIGHT_TEXT N_("Video height")
00074 #define HEIGHT_LONGTEXT N_( \
00075 "Allows you to specify the output video height." )
00076 #define MAXWIDTH_TEXT N_("Maximum video width")
00077 #define MAXWIDTH_LONGTEXT N_( \
00078 "Allows you to specify a maximum output video width." )
00079 #define MAXHEIGHT_TEXT N_("Maximum video height")
00080 #define MAXHEIGHT_LONGTEXT N_( \
00081 "Allows you to specify a maximum output video height." )
00082 #define VFILTER_TEXT N_("Video filter")
00083 #define VFILTER_LONGTEXT N_( \
00084 "Allows you to specify video filters used after the video " \
00085 "transcoding and subpictures overlaying." )
00086
00087 #define CROPTOP_TEXT N_("Video crop top")
00088 #define CROPTOP_LONGTEXT N_( \
00089 "Allows you to specify the top coordinate for the video cropping." )
00090 #define CROPLEFT_TEXT N_("Video crop left")
00091 #define CROPLEFT_LONGTEXT N_( \
00092 "Allows you to specify the left coordinate for the video cropping." )
00093 #define CROPBOTTOM_TEXT N_("Video crop bottom")
00094 #define CROPBOTTOM_LONGTEXT N_( \
00095 "Allows you to specify the bottom coordinate for the video cropping." )
00096 #define CROPRIGHT_TEXT N_("Video crop right")
00097 #define CROPRIGHT_LONGTEXT N_( \
00098 "Allows you to specify the right coordinate for the video cropping." )
00099
00100 #define AENC_TEXT N_("Audio encoder")
00101 #define AENC_LONGTEXT N_( \
00102 "Allows you to specify the audio encoder to use and its associated " \
00103 "options." )
00104 #define ACODEC_TEXT N_("Destination audio codec")
00105 #define ACODEC_LONGTEXT N_( \
00106 "Allows you to specify the destination audio codec used for the " \
00107 "streaming output." )
00108 #define AB_TEXT N_("Audio bitrate")
00109 #define AB_LONGTEXT N_( \
00110 "Allows you to specify the audio bitrate used for the streaming " \
00111 "output." )
00112 #define ARATE_TEXT N_("Audio sample rate")
00113 #define ARATE_LONGTEXT N_( \
00114 "Allows you to specify the audio sample rate used for the streaming " \
00115 "output." )
00116 #define ACHANS_TEXT N_("Audio channels")
00117 #define ACHANS_LONGTEXT N_( \
00118 "Allows you to specify the number of audio channels used for the " \
00119 "streaming output." )
00120
00121 #define SENC_TEXT N_("Subtitles encoder")
00122 #define SENC_LONGTEXT N_( \
00123 "Allows you to specify the subtitles encoder to use and its associated " \
00124 "options." )
00125 #define SCODEC_TEXT N_("Destination subtitles codec")
00126 #define SCODEC_LONGTEXT N_( \
00127 "Allows you to specify the destination subtitles codec used for the " \
00128 "streaming output." )
00129 #define SFILTER_TEXT N_("Subpictures filter")
00130 #define SFILTER_LONGTEXT N_( \
00131 "Allows you to specify subpictures filters used during the video " \
00132 "transcoding. The subpictures produced by the filters will be overlayed " \
00133 "directly onto the video." )
00134
00135 #define OSD_TEXT N_("OSD menu")
00136 #define OSD_LONGTEXT N_(\
00137 "Enable streaming of the On Screen Display. It uses the osdmenu subfilter." )
00138
00139 #define THREADS_TEXT N_("Number of threads")
00140 #define THREADS_LONGTEXT N_( \
00141 "Allows you to specify the number of threads used for the transcoding." )
00142 #define HP_TEXT N_("High priority")
00143 #define HP_LONGTEXT N_( \
00144 "Runs the optional encoder thread at the OUTPUT priority instead of " \
00145 "VIDEO." )
00146
00147 #define ASYNC_TEXT N_("Synchronise on audio track")
00148 #define ASYNC_LONGTEXT N_( \
00149 "This option will drop/duplicate video frames to synchronise the video " \
00150 "track on the audio track." )
00151
00152 #define HURRYUP_TEXT N_( "Hurry up" )
00153 #define HURRYUP_LONGTEXT N_( "Allows you to specify if the transcoder " \
00154 "should drop frames if your CPU can't keep up with the encoding rate." )
00155
00156 static char *ppsz_deinterlace_type[] =
00157 {
00158 "deinterlace", "ffmpeg-deinterlace"
00159 };
00160
00161 static int Open ( vlc_object_t * );
00162 static void Close( vlc_object_t * );
00163
00164 #define SOUT_CFG_PREFIX "sout-transcode-"
00165
00166 vlc_module_begin();
00167 set_shortname( _("Transcode"));
00168 set_description( _("Transcode stream output") );
00169 set_capability( "sout stream", 50 );
00170 add_shortcut( "transcode" );
00171 set_callbacks( Open, Close );
00172 set_category( CAT_SOUT );
00173 set_subcategory( SUBCAT_SOUT_STREAM );
00174 set_section( N_("Video"), NULL );
00175 add_string( SOUT_CFG_PREFIX "venc", NULL, NULL, VENC_TEXT,
00176 VENC_LONGTEXT, VLC_FALSE );
00177 add_string( SOUT_CFG_PREFIX "vcodec", NULL, NULL, VCODEC_TEXT,
00178 VCODEC_LONGTEXT, VLC_FALSE );
00179 add_integer( SOUT_CFG_PREFIX "vb", 800 * 1000, NULL, VB_TEXT,
00180 VB_LONGTEXT, VLC_FALSE );
00181 add_float( SOUT_CFG_PREFIX "scale", 1, NULL, SCALE_TEXT,
00182 SCALE_LONGTEXT, VLC_FALSE );
00183 add_float( SOUT_CFG_PREFIX "fps", 0, NULL, FPS_TEXT,
00184 FPS_LONGTEXT, VLC_FALSE );
00185 add_bool( SOUT_CFG_PREFIX "hurry-up", VLC_TRUE, NULL, HURRYUP_TEXT,
00186 HURRYUP_LONGTEXT, VLC_FALSE );
00187 add_bool( SOUT_CFG_PREFIX "deinterlace", 0, NULL, DEINTERLACE_TEXT,
00188 DEINTERLACE_LONGTEXT, VLC_FALSE );
00189 add_string( SOUT_CFG_PREFIX "deinterlace-module", "deinterlace", NULL,
00190 DEINTERLACE_MODULE_TEXT, DEINTERLACE_MODULE_LONGTEXT,
00191 VLC_FALSE );
00192 change_string_list( ppsz_deinterlace_type, 0, 0 );
00193 add_integer( SOUT_CFG_PREFIX "width", 0, NULL, WIDTH_TEXT,
00194 WIDTH_LONGTEXT, VLC_TRUE );
00195 add_integer( SOUT_CFG_PREFIX "height", 0, NULL, HEIGHT_TEXT,
00196 HEIGHT_LONGTEXT, VLC_TRUE );
00197 add_integer( SOUT_CFG_PREFIX "maxwidth", 0, NULL, MAXWIDTH_TEXT,
00198 MAXWIDTH_LONGTEXT, VLC_TRUE );
00199 add_integer( SOUT_CFG_PREFIX "maxheight", 0, NULL, MAXHEIGHT_TEXT,
00200 MAXHEIGHT_LONGTEXT, VLC_TRUE );
00201 add_module_list_cat( SOUT_CFG_PREFIX "vfilter", SUBCAT_VIDEO_VFILTER,
00202 NULL, NULL,
00203 VFILTER_TEXT, VFILTER_LONGTEXT, VLC_FALSE );
00204
00205 add_integer( SOUT_CFG_PREFIX "croptop", 0, NULL, CROPTOP_TEXT,
00206 CROPTOP_LONGTEXT, VLC_TRUE );
00207 add_integer( SOUT_CFG_PREFIX "cropleft", 0, NULL, CROPLEFT_TEXT,
00208 CROPLEFT_LONGTEXT, VLC_TRUE );
00209 add_integer( SOUT_CFG_PREFIX "cropbottom", 0, NULL, CROPBOTTOM_TEXT,
00210 CROPBOTTOM_LONGTEXT, VLC_TRUE );
00211 add_integer( SOUT_CFG_PREFIX "cropright", 0, NULL, CROPRIGHT_TEXT,
00212 CROPRIGHT_LONGTEXT, VLC_TRUE );
00213
00214 set_section( N_("Audio"), NULL );
00215 add_string( SOUT_CFG_PREFIX "aenc", NULL, NULL, AENC_TEXT,
00216 AENC_LONGTEXT, VLC_FALSE );
00217 add_string( SOUT_CFG_PREFIX "acodec", NULL, NULL, ACODEC_TEXT,
00218 ACODEC_LONGTEXT, VLC_FALSE );
00219 add_integer( SOUT_CFG_PREFIX "ab", 64000, NULL, AB_TEXT,
00220 AB_LONGTEXT, VLC_FALSE );
00221 add_integer( SOUT_CFG_PREFIX "channels", 0, NULL, ACHANS_TEXT,
00222 ACHANS_LONGTEXT, VLC_FALSE );
00223 add_integer( SOUT_CFG_PREFIX "samplerate", 0, NULL, ARATE_TEXT,
00224 ARATE_LONGTEXT, VLC_TRUE );
00225 add_bool( SOUT_CFG_PREFIX "audio-sync", 0, NULL, ASYNC_TEXT,
00226 ASYNC_LONGTEXT, VLC_FALSE );
00227
00228 set_section( N_("Overlays/Subtitles"), NULL );
00229 add_string( SOUT_CFG_PREFIX "senc", NULL, NULL, SENC_TEXT,
00230 SENC_LONGTEXT, VLC_FALSE );
00231 add_string( SOUT_CFG_PREFIX "scodec", NULL, NULL, SCODEC_TEXT,
00232 SCODEC_LONGTEXT, VLC_FALSE );
00233 add_bool( SOUT_CFG_PREFIX "soverlay", 0, NULL, SCODEC_TEXT,
00234 SCODEC_LONGTEXT, VLC_FALSE );
00235 add_module_list_cat( SOUT_CFG_PREFIX "sfilter", SUBCAT_VIDEO_SUBPIC,
00236 NULL, NULL,
00237 SFILTER_TEXT, SFILTER_LONGTEXT, VLC_FALSE );
00238
00239 set_section( N_("On Screen Display"), NULL );
00240 add_bool( SOUT_CFG_PREFIX "osd", 0, NULL, OSD_TEXT,
00241 OSD_LONGTEXT, VLC_FALSE );
00242
00243 set_section( N_("Miscellaneous"), NULL );
00244 add_integer( SOUT_CFG_PREFIX "threads", 0, NULL, THREADS_TEXT,
00245 THREADS_LONGTEXT, VLC_TRUE );
00246 add_bool( SOUT_CFG_PREFIX "high-priority", 0, NULL, HP_TEXT, HP_LONGTEXT,
00247 VLC_TRUE );
00248
00249 vlc_module_end();
00250
00251 static const char *ppsz_sout_options[] = {
00252 "venc", "vcodec", "vb", "croptop", "cropbottom", "cropleft", "cropright",
00253 "scale", "fps", "width", "height", "vfilter", "deinterlace",
00254 "deinterlace-module", "threads", "hurry-up", "aenc", "acodec", "ab",
00255 "samplerate", "channels", "senc", "scodec", "soverlay", "sfilter",
00256 "osd", "audio-sync", "high-priority", "maxwidth", "maxheight", NULL
00257 };
00258
00259
00260
00261
00262 static sout_stream_id_t *Add ( sout_stream_t *, es_format_t * );
00263 static int Del ( sout_stream_t *, sout_stream_id_t * );
00264 static int Send( sout_stream_t *, sout_stream_id_t *, block_t* );
00265
00266 static int transcode_audio_new ( sout_stream_t *, sout_stream_id_t * );
00267 static void transcode_audio_close ( sout_stream_t *, sout_stream_id_t * );
00268 static int transcode_audio_process( sout_stream_t *, sout_stream_id_t *,
00269 block_t *, block_t ** );
00270
00271 static aout_buffer_t *audio_new_buffer( decoder_t *, int );
00272 static void audio_del_buffer( decoder_t *, aout_buffer_t * );
00273
00274 static int transcode_video_new ( sout_stream_t *, sout_stream_id_t * );
00275 static void transcode_video_close ( sout_stream_t *, sout_stream_id_t * );
00276 static int transcode_video_encoder_open( sout_stream_t *, sout_stream_id_t *);
00277 static int transcode_video_process( sout_stream_t *, sout_stream_id_t *,
00278 block_t *, block_t ** );
00279
00280 static void video_del_buffer( vlc_object_t *, picture_t * );
00281 static picture_t *video_new_buffer_decoder( decoder_t * );
00282 static void video_del_buffer_decoder( decoder_t *, picture_t * );
00283 static void video_link_picture_decoder( decoder_t *, picture_t * );
00284 static void video_unlink_picture_decoder( decoder_t *, picture_t * );
00285 static picture_t *video_new_buffer_filter( filter_t * );
00286 static void video_del_buffer_filter( filter_t *, picture_t * );
00287
00288 static int transcode_spu_new ( sout_stream_t *, sout_stream_id_t * );
00289 static void transcode_spu_close ( sout_stream_t *, sout_stream_id_t * );
00290 static int transcode_spu_process( sout_stream_t *, sout_stream_id_t *,
00291 block_t *, block_t ** );
00292
00293 static int transcode_osd_new ( sout_stream_t *, sout_stream_id_t * );
00294 static void transcode_osd_close ( sout_stream_t *, sout_stream_id_t * );
00295 static int transcode_osd_process( sout_stream_t *, sout_stream_id_t *,
00296 block_t *, block_t ** );
00297
00298 static int EncoderThread( struct sout_stream_sys_t * p_sys );
00299
00300 static int pi_channels_maps[6] =
00301 {
00302 0,
00303 AOUT_CHAN_CENTER, AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
00304 AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
00305 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
00306 | AOUT_CHAN_REARRIGHT,
00307 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
00308 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
00309 };
00310
00311 #define PICTURE_RING_SIZE 64
00312 #define SUBPICTURE_RING_SIZE 20
00313
00314 struct sout_stream_sys_t
00315 {
00316 VLC_COMMON_MEMBERS
00317
00318 sout_stream_t *p_out;
00319 sout_stream_id_t *id_video;
00320 block_t *p_buffers;
00321 vlc_mutex_t lock_out;
00322 vlc_cond_t cond;
00323 picture_t * pp_pics[PICTURE_RING_SIZE];
00324 int i_first_pic, i_last_pic;
00325
00326
00327 vlc_fourcc_t i_acodec;
00328 char *psz_aenc;
00329 sout_cfg_t *p_audio_cfg;
00330 int i_sample_rate;
00331 int i_channels;
00332 int i_abitrate;
00333
00334
00335 vlc_fourcc_t i_vcodec;
00336 char *psz_venc;
00337 sout_cfg_t *p_video_cfg;
00338 int i_vbitrate;
00339 double f_scale;
00340 double f_fps;
00341 unsigned int i_width, i_maxwidth;
00342 unsigned int i_height, i_maxheight;
00343 vlc_bool_t b_deinterlace;
00344 char *psz_deinterlace;
00345 sout_cfg_t *p_deinterlace_cfg;
00346 int i_threads;
00347 vlc_bool_t b_high_priority;
00348 vlc_bool_t b_hurry_up;
00349 char *psz_vfilters[10];
00350 sout_cfg_t *p_vfilters_cfg[10];
00351 int i_vfilters;
00352
00353 int i_crop_top;
00354 int i_crop_bottom;
00355 int i_crop_right;
00356 int i_crop_left;
00357
00358
00359 vlc_fourcc_t i_scodec;
00360 char *psz_senc;
00361 vlc_bool_t b_soverlay;
00362 sout_cfg_t *p_spu_cfg;
00363 spu_t *p_spu;
00364
00365
00366 sout_stream_id_t *id_osd;
00367 vlc_fourcc_t i_osdcodec;
00368 char *psz_osdenc;
00369 sout_cfg_t *p_osd_cfg;
00370 vlc_bool_t b_es_osd;
00371 vlc_bool_t b_sout_osd;
00372
00373
00374 vlc_bool_t b_master_sync;
00375 mtime_t i_master_drift;
00376 };
00377
00378 struct decoder_owner_sys_t
00379 {
00380 picture_t *pp_pics[PICTURE_RING_SIZE];
00381 sout_stream_sys_t *p_sys;
00382 };
00383 struct filter_owner_sys_t
00384 {
00385 picture_t *pp_pics[PICTURE_RING_SIZE];
00386 sout_stream_sys_t *p_sys;
00387 };
00388
00389
00390
00391
00392 static int Open( vlc_object_t *p_this )
00393 {
00394 sout_stream_t *p_stream = (sout_stream_t*)p_this;
00395 sout_stream_sys_t *p_sys;
00396 vlc_value_t val;
00397
00398 p_sys = vlc_object_create( p_this, sizeof( sout_stream_sys_t ) );
00399
00400 p_sys->p_out = sout_StreamNew( p_stream->p_sout, p_stream->psz_next );
00401 if( !p_sys->p_out )
00402 {
00403 msg_Err( p_stream, "cannot create chain" );
00404 vlc_object_destroy( p_sys );
00405 return VLC_EGENERIC;
00406 }
00407
00408 p_sys->i_master_drift = 0;
00409
00410 sout_CfgParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
00411 p_stream->p_cfg );
00412
00413
00414 var_Get( p_stream, SOUT_CFG_PREFIX "aenc", &val );
00415 p_sys->psz_aenc = NULL;
00416 p_sys->p_audio_cfg = NULL;
00417 if( val.psz_string && *val.psz_string )
00418 {
00419 char *psz_next;
00420 psz_next = sout_CfgCreate( &p_sys->psz_aenc, &p_sys->p_audio_cfg,
00421 val.psz_string );
00422 if( psz_next ) free( psz_next );
00423 }
00424 if( val.psz_string ) free( val.psz_string );
00425
00426 var_Get( p_stream, SOUT_CFG_PREFIX "acodec", &val );
00427 p_sys->i_acodec = 0;
00428 if( val.psz_string && *val.psz_string )
00429 {
00430 char fcc[4] = " ";
00431 memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
00432 p_sys->i_acodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
00433 }
00434 if( val.psz_string ) free( val.psz_string );
00435
00436 var_Get( p_stream, SOUT_CFG_PREFIX "ab", &val );
00437 p_sys->i_abitrate = val.i_int;
00438 if( p_sys->i_abitrate < 4000 ) p_sys->i_abitrate *= 1000;
00439
00440 var_Get( p_stream, SOUT_CFG_PREFIX "samplerate", &val );
00441 p_sys->i_sample_rate = val.i_int;
00442
00443 var_Get( p_stream, SOUT_CFG_PREFIX "channels", &val );
00444 p_sys->i_channels = val.i_int;
00445
00446 if( p_sys->i_acodec )
00447 {
00448 if( (strncmp( (char *)&p_sys->i_acodec, "mp3", 3) == 0) &&
00449 (p_sys->i_channels > 2) )
00450 {
00451 msg_Warn( p_stream, "%d channels invalid for mp3, forcing to 2",
00452 p_sys->i_channels );
00453 p_sys->i_channels = 2;
00454 }
00455 msg_Dbg( p_stream, "codec audio=%4.4s %dHz %d channels %dKb/s",
00456 (char *)&p_sys->i_acodec, p_sys->i_sample_rate,
00457 p_sys->i_channels, p_sys->i_abitrate / 1000 );
00458 }
00459
00460
00461 var_Get( p_stream, SOUT_CFG_PREFIX "venc", &val );
00462 p_sys->psz_venc = NULL;
00463 p_sys->p_video_cfg = NULL;
00464 if( val.psz_string && *val.psz_string )
00465 {
00466 char *psz_next;
00467 psz_next = sout_CfgCreate( &p_sys->psz_venc, &p_sys->p_video_cfg,
00468 val.psz_string );
00469 if( psz_next ) free( psz_next );
00470 }
00471 if( val.psz_string ) free( val.psz_string );
00472
00473 var_Get( p_stream, SOUT_CFG_PREFIX "vcodec", &val );
00474 p_sys->i_vcodec = 0;
00475 if( val.psz_string && *val.psz_string )
00476 {
00477 char fcc[4] = " ";
00478 memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
00479 p_sys->i_vcodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
00480 }
00481 if( val.psz_string ) free( val.psz_string );
00482
00483 var_Get( p_stream, SOUT_CFG_PREFIX "vb", &val );
00484 p_sys->i_vbitrate = val.i_int;
00485 if( p_sys->i_vbitrate < 16000 ) p_sys->i_vbitrate *= 1000;
00486
00487 var_Get( p_stream, SOUT_CFG_PREFIX "scale", &val );
00488 p_sys->f_scale = val.f_float;
00489
00490 var_Get( p_stream, SOUT_CFG_PREFIX "fps", &val );
00491 p_sys->f_fps = val.f_float;
00492
00493 var_Get( p_stream, SOUT_CFG_PREFIX "hurry-up", &val );
00494 p_sys->b_hurry_up = val.b_bool;
00495
00496 var_Get( p_stream, SOUT_CFG_PREFIX "width", &val );
00497 p_sys->i_width = val.i_int;
00498
00499 var_Get( p_stream, SOUT_CFG_PREFIX "height", &val );
00500 p_sys->i_height = val.i_int;
00501
00502 var_Get( p_stream, SOUT_CFG_PREFIX "maxwidth", &val );
00503 p_sys->i_maxwidth = val.i_int;
00504
00505 var_Get( p_stream, SOUT_CFG_PREFIX "maxheight", &val );
00506 p_sys->i_maxheight = val.i_int;
00507
00508 var_Get( p_stream, SOUT_CFG_PREFIX "vfilter", &val );
00509 p_sys->i_vfilters = 0;
00510 if( val.psz_string && *val.psz_string )
00511 {
00512 char *psz_parser = val.psz_string;
00513
00514 while( psz_parser != NULL && *psz_parser != '\0' )
00515 {
00516 psz_parser = sout_CfgCreate(
00517 &p_sys->psz_vfilters[p_sys->i_vfilters],
00518 &p_sys->p_vfilters_cfg[p_sys->i_vfilters],
00519 psz_parser );
00520 p_sys->i_vfilters++;
00521 if( psz_parser != NULL && *psz_parser != '\0' ) psz_parser++;
00522 }
00523 }
00524 if( val.psz_string ) free( val.psz_string );
00525 p_sys->psz_vfilters[p_sys->i_vfilters] = NULL;
00526 p_sys->p_vfilters_cfg[p_sys->i_vfilters] = NULL;
00527
00528 var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace", &val );
00529 p_sys->b_deinterlace = val.b_bool;
00530
00531 var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace-module", &val );
00532 p_sys->psz_deinterlace = NULL;
00533 p_sys->p_deinterlace_cfg = NULL;
00534 if( val.psz_string && *val.psz_string )
00535 {
00536 char *psz_next;
00537 psz_next = sout_CfgCreate( &p_sys->psz_deinterlace,
00538 &p_sys->p_deinterlace_cfg,
00539 val.psz_string );
00540 if( psz_next ) free( psz_next );
00541 }
00542 if( val.psz_string ) free( val.psz_string );
00543
00544 var_Get( p_stream, SOUT_CFG_PREFIX "croptop", &val );
00545 p_sys->i_crop_top = val.i_int;
00546 var_Get( p_stream, SOUT_CFG_PREFIX "cropbottom", &val );
00547 p_sys->i_crop_bottom = val.i_int;
00548 var_Get( p_stream, SOUT_CFG_PREFIX "cropleft", &val );
00549 p_sys->i_crop_left = val.i_int;
00550 var_Get( p_stream, SOUT_CFG_PREFIX "cropright", &val );
00551 p_sys->i_crop_right = val.i_int;
00552
00553 var_Get( p_stream, SOUT_CFG_PREFIX "threads", &val );
00554 p_sys->i_threads = val.i_int;
00555 var_Get( p_stream, SOUT_CFG_PREFIX "high-priority", &val );
00556 p_sys->b_high_priority = val.b_bool;
00557
00558 if( p_sys->i_vcodec )
00559 {
00560 msg_Dbg( p_stream, "codec video=%4.4s %dx%d scaling: %f %dkb/s",
00561 (char *)&p_sys->i_vcodec, p_sys->i_width, p_sys->i_height,
00562 p_sys->f_scale, p_sys->i_vbitrate / 1000 );
00563 }
00564
00565
00566 p_sys->p_spu = NULL;
00567 p_sys->psz_senc = NULL;
00568 p_sys->p_spu_cfg = NULL;
00569 p_sys->i_scodec = 0;
00570
00571 var_Get( p_stream, SOUT_CFG_PREFIX "senc", &val );
00572 if( val.psz_string && *val.psz_string )
00573 {
00574 char *psz_next;
00575 psz_next = sout_CfgCreate( &p_sys->psz_senc, &p_sys->p_spu_cfg,
00576 val.psz_string );
00577 if( psz_next ) free( psz_next );
00578 }
00579 if( val.psz_string ) free( val.psz_string );
00580
00581 var_Get( p_stream, SOUT_CFG_PREFIX "scodec", &val );
00582 if( val.psz_string && *val.psz_string )
00583 {
00584 char fcc[4] = " ";
00585 memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
00586 p_sys->i_scodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
00587 }
00588 if( val.psz_string ) free( val.psz_string );
00589
00590 if( p_sys->i_scodec )
00591 {
00592 msg_Dbg( p_stream, "codec spu=%4.4s", (char *)&p_sys->i_scodec );
00593 }
00594
00595 var_Get( p_stream, SOUT_CFG_PREFIX "soverlay", &val );
00596 p_sys->b_soverlay = val.b_bool;
00597
00598 var_Get( p_stream, SOUT_CFG_PREFIX "sfilter", &val );
00599 if( val.psz_string && *val.psz_string )
00600 {
00601 p_sys->p_spu = spu_Create( p_stream );
00602 var_Create( p_sys->p_spu, "sub-filter", VLC_VAR_STRING );
00603 var_Set( p_sys->p_spu, "sub-filter", val );
00604 spu_Init( p_sys->p_spu );
00605 }
00606 if( val.psz_string ) free( val.psz_string );
00607
00608
00609 p_sys->psz_osdenc = NULL;
00610 p_sys->p_osd_cfg = NULL;
00611 p_sys->i_osdcodec = 0;
00612 p_sys->b_es_osd = VLC_FALSE;
00613
00614 var_Get( p_stream, SOUT_CFG_PREFIX "osd", &val );
00615 p_sys->b_sout_osd = val.b_bool;
00616 if( p_sys->b_sout_osd )
00617 {
00618 vlc_value_t osd_val;
00619 char *psz_next;
00620
00621 psz_next = sout_CfgCreate( &p_sys->psz_osdenc,
00622 &p_sys->p_osd_cfg, strdup( "dvbsub") );
00623 if( psz_next ) free( psz_next );
00624
00625 p_sys->i_osdcodec = VLC_FOURCC('Y','U','V','P' );
00626
00627 msg_Dbg( p_stream, "codec osd=%4.4s", (char *)&p_sys->i_osdcodec );
00628
00629 if( !p_sys->p_spu )
00630 {
00631 osd_val.psz_string = strdup("osdmenu");
00632 p_sys->p_spu = spu_Create( p_stream );
00633 var_Create( p_sys->p_spu, "sub-filter", VLC_VAR_STRING );
00634 var_Set( p_sys->p_spu, "sub-filter", osd_val );
00635 spu_Init( p_sys->p_spu );
00636 if( osd_val.psz_string ) free( osd_val.psz_string );
00637 }
00638 else
00639 {
00640 osd_val.psz_string = strdup("osdmenu");
00641 var_Set( p_sys->p_spu, "sub-filter", osd_val );
00642 if( osd_val.psz_string ) free( osd_val.psz_string );
00643 }
00644 }
00645
00646
00647 var_Get( p_stream, SOUT_CFG_PREFIX "audio-sync", &val );
00648 p_sys->b_master_sync = val.b_bool;
00649 if( p_sys->f_fps > 0 ) p_sys->b_master_sync = VLC_TRUE;
00650
00651 p_stream->pf_add = Add;
00652 p_stream->pf_del = Del;
00653 p_stream->pf_send = Send;
00654 p_stream->p_sys = p_sys;
00655
00656 return VLC_SUCCESS;
00657 }
00658
00659
00660
00661
00662 static void Close( vlc_object_t * p_this )
00663 {
00664 sout_stream_t *p_stream = (sout_stream_t*)p_this;
00665 sout_stream_sys_t *p_sys = p_stream->p_sys;
00666
00667 sout_StreamDelete( p_sys->p_out );
00668
00669 while( p_sys->p_audio_cfg != NULL )
00670 {
00671 sout_cfg_t *p_next = p_sys->p_audio_cfg->p_next;
00672
00673 if( p_sys->p_audio_cfg->psz_name )
00674 free( p_sys->p_audio_cfg->psz_name );
00675 if( p_sys->p_audio_cfg->psz_value )
00676 free( p_sys->p_audio_cfg->psz_value );
00677 free( p_sys->p_audio_cfg );
00678
00679 p_sys->p_audio_cfg = p_next;
00680 }
00681 if( p_sys->psz_aenc ) free( p_sys->psz_aenc );
00682
00683 while( p_sys->p_video_cfg != NULL )
00684 {
00685 sout_cfg_t *p_next = p_sys->p_video_cfg->p_next;
00686
00687 if( p_sys->p_video_cfg->psz_name )
00688 free( p_sys->p_video_cfg->psz_name );
00689 if( p_sys->p_video_cfg->psz_value )
00690 free( p_sys->p_video_cfg->psz_value );
00691 free( p_sys->p_video_cfg );
00692
00693 p_sys->p_video_cfg = p_next;
00694 }
00695 if( p_sys->psz_venc ) free( p_sys->psz_venc );
00696
00697 while( p_sys->p_deinterlace_cfg != NULL )
00698 {
00699 sout_cfg_t *p_next = p_sys->p_deinterlace_cfg->p_next;
00700
00701 if( p_sys->p_deinterlace_cfg->psz_name )
00702 free( p_sys->p_deinterlace_cfg->psz_name );
00703 if( p_sys->p_deinterlace_cfg->psz_value )
00704 free( p_sys->p_deinterlace_cfg->psz_value );
00705 free( p_sys->p_deinterlace_cfg );
00706
00707 p_sys->p_deinterlace_cfg = p_next;
00708 }
00709 if( p_sys->psz_deinterlace ) free( p_sys->psz_deinterlace );
00710
00711 while( p_sys->p_spu_cfg != NULL )
00712 {
00713 sout_cfg_t *p_next = p_sys->p_spu_cfg->p_next;
00714
00715 if( p_sys->p_spu_cfg->psz_name )
00716 free( p_sys->p_spu_cfg->psz_name );
00717 if( p_sys->p_spu_cfg->psz_value )
00718 free( p_sys->p_spu_cfg->psz_value );
00719 free( p_sys->p_spu_cfg );
00720
00721 p_sys->p_spu_cfg = p_next;
00722 }
00723 if( p_sys->psz_senc ) free( p_sys->psz_senc );
00724
00725 if( p_sys->p_spu ) spu_Destroy( p_sys->p_spu );
00726
00727 while( p_sys->p_osd_cfg != NULL )
00728 {
00729 sout_cfg_t *p_next = p_sys->p_osd_cfg->p_next;
00730
00731 if( p_sys->p_osd_cfg->psz_name )
00732 free( p_sys->p_osd_cfg->psz_name );
00733 if( p_sys->p_osd_cfg->psz_value )
00734 free( p_sys->p_osd_cfg->psz_value );
00735 free( p_sys->p_osd_cfg );
00736
00737 p_sys->p_osd_cfg = p_next;
00738 }
00739 if( p_sys->psz_osdenc ) free( p_sys->psz_osdenc );
00740
00741 vlc_object_destroy( p_sys );
00742 }
00743
00744 struct sout_stream_id_t
00745 {
00746 vlc_fourcc_t b_transcode;
00747
00748
00749 void *id;
00750
00751
00752 decoder_t *p_decoder;
00753
00754
00755 filter_t *pp_filter[10];
00756 int i_filter;
00757 filter_t *pp_vfilter[10];
00758 int i_vfilter;
00759
00760
00761 encoder_t *p_encoder;
00762
00763
00764 date_t interpolated_pts;
00765 };
00766
00767 static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
00768 {
00769 sout_stream_sys_t *p_sys = p_stream->p_sys;
00770 sout_stream_id_t *id;
00771
00772 id = malloc( sizeof( sout_stream_id_t ) );
00773 memset( id, 0, sizeof(sout_stream_id_t) );
00774
00775 id->id = NULL;
00776 id->p_decoder = NULL;
00777 id->p_encoder = NULL;
00778
00779
00780 id->p_decoder = vlc_object_create( p_stream, VLC_OBJECT_DECODER );
00781 if( !id->p_decoder )
00782 {
00783 msg_Err( p_stream, "out of memory" );
00784 goto error;
00785 }
00786 vlc_object_attach( id->p_decoder, p_stream );
00787 id->p_decoder->p_module = NULL;
00788 id->p_decoder->fmt_in = *p_fmt;
00789 id->p_decoder->b_pace_control = VLC_TRUE;
00790
00791
00792 id->p_encoder = vlc_object_create( p_stream, VLC_OBJECT_ENCODER );
00793 if( !id->p_encoder )
00794 {
00795 msg_Err( p_stream, "out of memory" );
00796 goto error;
00797 }
00798 vlc_object_attach( id->p_encoder, p_stream );
00799 id->p_encoder->p_module = NULL;
00800
00801
00802 es_format_Init( &id->p_encoder->fmt_out, p_fmt->i_cat, 0 );
00803 id->p_encoder->fmt_out.i_id = p_fmt->i_id;
00804 id->p_encoder->fmt_out.i_group = p_fmt->i_group;
00805 if( p_fmt->psz_language )
00806 id->p_encoder->fmt_out.psz_language = strdup( p_fmt->psz_language );
00807
00808 if( p_fmt->i_cat == AUDIO_ES && (p_sys->i_acodec || p_sys->psz_aenc) )
00809 {
00810 msg_Dbg( p_stream,
00811 "creating audio transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
00812 (char*)&p_fmt->i_codec, (char*)&p_sys->i_acodec );
00813
00814
00815 id->p_encoder->fmt_out.i_codec = p_sys->i_acodec;
00816 id->p_encoder->fmt_out.audio.i_rate = p_sys->i_sample_rate > 0 ?
00817 p_sys->i_sample_rate : (int)p_fmt->audio.i_rate;
00818 id->p_encoder->fmt_out.i_bitrate = p_sys->i_abitrate;
00819 id->p_encoder->fmt_out.audio.i_bitspersample =
00820 p_fmt->audio.i_bitspersample;
00821 id->p_encoder->fmt_out.audio.i_channels = p_sys->i_channels > 0 ?
00822 p_sys->i_channels : p_fmt->audio.i_channels;
00823
00824 id->p_encoder->fmt_out.audio.i_channels =
00825 __MIN( id->p_encoder->fmt_out.audio.i_channels,
00826 id->p_decoder->fmt_in.audio.i_channels );
00827 id->p_encoder->fmt_out.audio.i_original_channels =
00828 id->p_decoder->fmt_in.audio.i_physical_channels;
00829 if( id->p_decoder->fmt_in.audio.i_channels ==
00830 id->p_encoder->fmt_out.audio.i_channels )
00831 {
00832 id->p_encoder->fmt_out.audio.i_physical_channels =
00833 id->p_decoder->fmt_in.audio.i_physical_channels;
00834 }
00835 else
00836 {
00837 id->p_encoder->fmt_out.audio.i_physical_channels =
00838 pi_channels_maps[id->p_encoder->fmt_out.audio.i_channels];
00839 }
00840
00841
00842 if( transcode_audio_new( p_stream, id ) )
00843 {
00844 msg_Err( p_stream, "cannot create audio chain" );
00845 goto error;
00846 }
00847
00848
00849 id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
00850 id->b_transcode = VLC_TRUE;
00851
00852 if( !id->id )
00853 {
00854 transcode_audio_close( p_stream, id );
00855 goto error;
00856 }
00857
00858 date_Init( &id->interpolated_pts, p_fmt->audio.i_rate, 1 );
00859 }
00860 else if( p_fmt->i_cat == VIDEO_ES &&
00861 (p_sys->i_vcodec != 0 || p_sys->psz_venc) )
00862 {
00863 msg_Dbg( p_stream,
00864 "creating video transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
00865 (char*)&p_fmt->i_codec, (char*)&p_sys->i_vcodec );
00866
00867
00868 id->p_encoder->fmt_out.i_codec = p_sys->i_vcodec;
00869 id->p_encoder->fmt_out.video.i_width = p_sys->i_width;
00870 id->p_encoder->fmt_out.video.i_height = p_sys->i_height;
00871 id->p_encoder->fmt_out.i_bitrate = p_sys->i_vbitrate;
00872
00873
00874 if( transcode_video_new( p_stream, id ) )
00875 {
00876 msg_Err( p_stream, "cannot create video chain" );
00877 goto error;
00878 }
00879
00880
00881
00882 id->b_transcode = VLC_TRUE;
00883
00884 if( p_sys->f_fps > 0 )
00885 {
00886 id->p_encoder->fmt_out.video.i_frame_rate =
00887 (p_sys->f_fps * 1001) + 0.5;
00888 id->p_encoder->fmt_out.video.i_frame_rate_base = 1001;
00889 }
00890 }
00891 else if( p_fmt->i_cat == SPU_ES && (p_sys->i_scodec || p_sys->psz_senc) )
00892 {
00893 msg_Dbg( p_stream, "creating subtitles transcoding from fcc=`%4.4s' "
00894 "to fcc=`%4.4s'", (char*)&p_fmt->i_codec,
00895 (char*)&p_sys->i_scodec );
00896
00897
00898 id->p_encoder->fmt_out.i_codec = p_sys->i_scodec;
00899
00900
00901 if( transcode_spu_new( p_stream, id ) )
00902 {
00903 msg_Err( p_stream, "cannot create subtitles chain" );
00904 goto error;
00905 }
00906
00907
00908 id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
00909 id->b_transcode = VLC_TRUE;
00910
00911 if( !id->id )
00912 {
00913 transcode_spu_close( p_stream, id );
00914 goto error;
00915 }
00916 }
00917 else if( p_fmt->i_cat == SPU_ES && p_sys->b_soverlay )
00918 {
00919 msg_Dbg( p_stream, "subtitles (fcc=`%4.4s') overlaying",
00920 (char*)&p_fmt->i_codec );
00921
00922 id->b_transcode = VLC_TRUE;
00923
00924
00925 if( transcode_spu_new( p_stream, id ) )
00926 {
00927 msg_Err( p_stream, "cannot create subtitles chain" );
00928 goto error;
00929 }
00930 }
00931 else
00932 {
00933 msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
00934 (char*)&p_fmt->i_codec );
00935 id->id = p_sys->p_out->pf_add( p_sys->p_out, p_fmt );
00936 id->b_transcode = VLC_FALSE;
00937
00938 if( !id->id ) goto error;
00939 }
00940
00941 if( p_sys->b_sout_osd )
00942 {
00943
00944 if( !p_sys->b_es_osd && (p_sys->i_osdcodec != 0 || p_sys->psz_osdenc) )
00945 {
00946 if( transcode_osd_new( p_stream, p_sys->id_osd ) )
00947 {
00948 msg_Err( p_stream, "cannot create osd chain" );
00949 goto error;
00950 }
00951 p_sys->b_es_osd = VLC_TRUE;
00952 }
00953 }
00954 return id;
00955
00956 error:
00957 if( id->p_decoder )
00958 {
00959 vlc_object_detach( id->p_decoder );
00960 vlc_object_destroy( id->p_decoder );
00961 }
00962
00963 if( id->p_encoder )
00964 {
00965 vlc_object_detach( id->p_encoder );
00966 es_format_Clean( &id->p_encoder->fmt_out );
00967 vlc_object_destroy( id->p_encoder );
00968 }
00969
00970 free( id );
00971 return NULL;
00972 }
00973
00974 static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
00975 {
00976 sout_stream_sys_t *p_sys = p_stream->p_sys;
00977
00978 if( p_sys->b_es_osd )
00979 transcode_osd_close( p_stream, p_sys->id_osd );
00980
00981 if( id->b_transcode )
00982 {
00983 switch( id->p_decoder->fmt_in.i_cat )
00984 {
00985 case AUDIO_ES:
00986 transcode_audio_close( p_stream, id );
00987 break;
00988 case VIDEO_ES:
00989 transcode_video_close( p_stream, id );
00990 break;
00991 case SPU_ES:
00992 transcode_spu_close( p_stream, id );
00993 break;
00994 }
00995 }
00996
00997 if( id->id ) p_sys->p_out->pf_del( p_sys->p_out, id->id );
00998
00999 if( id->p_decoder )
01000 {
01001 vlc_object_detach( id->p_decoder );
01002 vlc_object_destroy( id->p_decoder );
01003 }
01004
01005 if( id->p_encoder )
01006 {
01007 vlc_object_detach( id->p_encoder );
01008 es_format_Clean( &id->p_encoder->fmt_out );
01009 vlc_object_destroy( id->p_encoder );
01010 }
01011
01012 free( id );
01013
01014 return VLC_SUCCESS;
01015 }
01016
01017 static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
01018 block_t *p_buffer )
01019 {
01020 sout_stream_sys_t *p_sys = p_stream->p_sys;
01021 block_t *p_out = NULL;
01022
01023 if( !id->b_transcode && id->id )
01024 {
01025
01026 if( p_sys->b_es_osd )
01027 {
01028 transcode_osd_process( p_stream, id, p_buffer, &p_out );
01029 }
01030 return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_buffer );
01031 }
01032 else if( !id->b_transcode )
01033 {
01034 block_Release( p_buffer );
01035 return VLC_EGENERIC;
01036 }
01037
01038 switch( id->p_decoder->fmt_in.i_cat )
01039 {
01040 case AUDIO_ES:
01041 transcode_audio_process( p_stream, id, p_buffer, &p_out );
01042 break;
01043
01044 case VIDEO_ES:
01045 if( transcode_video_process( p_stream, id, p_buffer, &p_out )
01046 != VLC_SUCCESS )
01047 {
01048 return VLC_EGENERIC;
01049 }
01050 break;
01051
01052 case SPU_ES:
01053 if( transcode_spu_process( p_stream, id, p_buffer, &p_out ) !=
01054 VLC_SUCCESS )
01055 {
01056 return VLC_EGENERIC;
01057 }
01058 break;
01059
01060 default:
01061 p_out = NULL;
01062 block_Release( p_buffer );
01063 break;
01064 }
01065
01066 if( p_out ) return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_out );
01067 return VLC_SUCCESS;
01068 }
01069
01070
01071
01072
01073 int audio_BitsPerSample( vlc_fourcc_t i_format )
01074 {
01075 switch( i_format )
01076 {
01077 case VLC_FOURCC('u','8',' ',' '):
01078 case VLC_FOURCC('s','8',' ',' '):
01079 return 8;
01080
01081 case VLC_FOURCC('u','1','6','l'):
01082 case VLC_FOURCC('s','1','6','l'):
01083 case VLC_FOURCC('u','1','6','b'):
01084 case VLC_FOURCC('s','1','6','b'):
01085 return 16;
01086
01087 case VLC_FOURCC('u','2','4','l'):
01088 case VLC_FOURCC('s','2','4','l'):
01089 case VLC_FOURCC('u','2','4','b'):
01090 case VLC_FOURCC('s','2','4','b'):
01091 return 24;
01092
01093 case VLC_FOURCC('u','3','2','l'):
01094 case VLC_FOURCC('s','3','2','l'):
01095 case VLC_FOURCC('u','3','2','b'):
01096 case VLC_FOURCC('s','3','2','b'):
01097 case VLC_FOURCC('f','l','3','2'):
01098 case VLC_FOURCC('f','i','3','2'):
01099 return 32;
01100
01101 case VLC_FOURCC('f','l','6','4'):
01102 return 64;
01103 }
01104
01105 return 0;
01106 }
01107
01108 static filter_t *transcode_audio_filter_new( sout_stream_t *p_stream,
01109 sout_stream_id_t *id,
01110 es_format_t *p_fmt_in,
01111 es_format_t *p_fmt_out )
01112 {
01113 filter_t *p_filter = vlc_object_create( p_stream, VLC_OBJECT_FILTER );
01114
01115 vlc_object_attach( p_filter, p_stream );
01116 p_filter->pf_audio_buffer_new = (block_t* (*) (filter_t*, int))__block_New;
01117
01118 p_filter->fmt_in = *p_fmt_in;
01119 p_filter->fmt_out = *p_fmt_out;
01120
01121 p_filter->p_module = module_Need( p_filter, "audio filter2", 0, 0 );
01122 if( p_filter->p_module )
01123 {
01124 p_filter->fmt_out.audio.i_bitspersample =
01125 audio_BitsPerSample( p_filter->fmt_out.i_codec );
01126 *p_fmt_in = p_filter->fmt_out;
01127 }
01128 else
01129 {
01130 vlc_object_detach( p_filter );
01131 vlc_object_destroy( p_filter );
01132 p_filter = 0;
01133 }
01134
01135 return p_filter;
01136 }
01137
01138 static int transcode_audio_new( sout_stream_t *p_stream,
01139 sout_stream_id_t *id )
01140 {
01141 sout_stream_sys_t *p_sys = p_stream->p_sys;
01142 es_format_t fmt_last;
01143 int i_pass = 6;
01144
01145
01146
01147
01148
01149
01150 id->p_decoder->fmt_out = id->p_decoder->fmt_in;
01151 id->p_decoder->fmt_out.i_extra = 0;
01152 id->p_decoder->fmt_out.p_extra = 0;
01153 id->p_decoder->pf_decode_audio = 0;
01154 id->p_decoder->pf_aout_buffer_new = audio_new_buffer;
01155 id->p_decoder->pf_aout_buffer_del = audio_del_buffer;
01156
01157
01158 id->p_decoder->p_module =
01159 module_Need( id->p_decoder, "decoder", "$codec", 0 );
01160
01161 if( !id->p_decoder->p_module )
01162 {
01163 msg_Err( p_stream, "cannot find decoder" );
01164 return VLC_EGENERIC;
01165 }
01166 id->p_decoder->fmt_out.audio.i_bitspersample =
01167 audio_BitsPerSample( id->p_decoder->fmt_out.i_codec );
01168 fmt_last = id->p_decoder->fmt_out;
01169
01170 fmt_last.audio.i_rate = id->p_decoder->fmt_in.audio.i_rate;
01171
01172
01173
01174
01175
01176
01177 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
01178 id->p_decoder->fmt_out.i_codec );
01179 id->p_encoder->fmt_in.audio.i_format = id->p_decoder->fmt_out.i_codec;
01180
01181
01182 es_format_Init( &id->p_encoder->fmt_in, AUDIO_ES, AOUT_FMT_S16_NE );
01183 id->p_encoder->fmt_in.audio.i_format = AOUT_FMT_S16_NE;
01184 id->p_encoder->fmt_in.audio.i_rate = id->p_encoder->fmt_out.audio.i_rate;
01185 id->p_encoder->fmt_in.audio.i_physical_channels =
01186 id->p_encoder->fmt_out.audio.i_physical_channels;
01187 id->p_encoder->fmt_in.audio.i_original_channels =
01188 id->p_encoder->fmt_out.audio.i_original_channels;
01189 id->p_encoder->fmt_in.audio.i_channels =
01190 id->p_encoder->fmt_out.audio.i_channels;
01191 id->p_encoder->fmt_in.audio.i_bitspersample =
01192 audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
01193
01194 id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
01195
01196 id->p_encoder->p_module =
01197 module_Need( id->p_encoder, "encoder", p_sys->psz_aenc, VLC_TRUE );
01198 if( !id->p_encoder->p_module )
01199 {
01200 msg_Err( p_stream, "cannot find encoder" );
01201 module_Unneed( id->p_decoder, id->p_decoder->p_module );
01202 id->p_decoder->p_module = 0;
01203 return VLC_EGENERIC;
01204 }
01205 id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
01206 id->p_encoder->fmt_in.audio.i_bitspersample =
01207 audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
01208
01209
01210 if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels ||
01211 fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate )
01212 {
01213
01214 es_format_t fmt_out = id->p_encoder->fmt_in;
01215 fmt_out.i_codec = fmt_out.audio.i_format = VLC_FOURCC('f','l','3','2');
01216
01217 id->pp_filter[id->i_filter] =
01218 transcode_audio_filter_new( p_stream, id, &fmt_last, &fmt_out );
01219
01220 if( id->pp_filter[id->i_filter] ) id->i_filter++;
01221 }
01222
01223 while( i_pass-- )
01224 {
01225 if( fmt_last.audio.i_channels !=
01226 id->p_encoder->fmt_in.audio.i_channels ||
01227 fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate ||
01228 fmt_last.i_codec != id->p_encoder->fmt_in.i_codec )
01229 {
01230 id->pp_filter[id->i_filter] =
01231 transcode_audio_filter_new( p_stream, id, &fmt_last,
01232 &id->p_encoder->fmt_in );
01233
01234 if( id->pp_filter[id->i_filter] ) id->i_filter++;
01235 else break;
01236 }
01237 }
01238
01239
01240 if( fmt_last.i_codec != id->p_encoder->fmt_in.i_codec )
01241 {
01242 msg_Err( p_stream, "no audio filter found (%4.4s->%4.4s)",
01243 (char *)&fmt_last.i_codec,
01244 (char *)&id->p_encoder->fmt_in.i_codec );
01245 transcode_audio_close( p_stream, id );
01246 return VLC_EGENERIC;
01247 }
01248
01249 if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels )
01250 {
01251 msg_Err( p_stream, "no audio filter found for mixing from"
01252 " %i to %i channels", fmt_last.audio.i_channels,
01253 id->p_encoder->fmt_in.audio.i_channels );
01254 #if 0
01255
01256 id->p_encoder->fmt_in.audio.i_channels = fmt_last.audio.i_channels;
01257 id->p_encoder->fmt_out.audio.i_channels = fmt_last.audio.i_channels;
01258
01259 id->p_encoder->fmt_in.audio.i_physical_channels =
01260 id->p_encoder->fmt_in.audio.i_original_channels =
01261 fmt_last.audio.i_physical_channels;
01262 id->p_encoder->fmt_out.audio.i_physical_channels =
01263 id->p_encoder->fmt_out.audio.i_original_channels =
01264 fmt_last.audio.i_physical_channels;
01265 #else
01266 transcode_audio_close( p_stream, id );
01267 return VLC_EGENERIC;
01268 #endif
01269 }
01270
01271 if( fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate )
01272 {
01273 msg_Err( p_stream, "no audio filter found for resampling from"
01274 " %iHz to %iHz", fmt_last.audio.i_rate,
01275 id->p_encoder->fmt_in.audio.i_rate );
01276 #if 0
01277
01278 id->p_encoder->fmt_in.audio.i_rate = fmt_last.audio.i_rate;
01279 id->p_encoder->fmt_out.audio.i_rate = fmt_last.audio.i_rate;
01280 #else
01281 transcode_audio_close( p_stream, id );
01282 return VLC_EGENERIC;
01283 #endif
01284 }
01285
01286
01287 if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC( 'm','p','3',' ' ) )
01288 id->p_encoder->fmt_out.i_codec = VLC_FOURCC( 'm','p','g','a' );
01289
01290 return VLC_SUCCESS;
01291 }
01292
01293 static void transcode_audio_close( sout_stream_t *p_stream,
01294 sout_stream_id_t *id )
01295 {
01296 int i;
01297
01298
01299 if( id->p_decoder->p_module )
01300 module_Unneed( id->p_decoder, id->p_decoder->p_module );
01301 id->p_decoder->p_module = 0;
01302
01303
01304 if( id->p_encoder->p_module )
01305 module_Unneed( id->p_encoder, id->p_encoder->p_module );
01306 id->p_encoder->p_module = 0;
01307
01308
01309 for( i = 0; i < id->i_filter; i++ )
01310 {
01311 vlc_object_detach( id->pp_filter[i] );
01312 if( id->pp_filter[i]->p_module )
01313 module_Unneed( id->pp_filter[i], id->pp_filter[i]->p_module );
01314 vlc_object_destroy( id->pp_filter[i] );
01315 }
01316 }
01317
01318 static int transcode_audio_process( sout_stream_t *p_stream,
01319 sout_stream_id_t *id,
01320 block_t *in, block_t **out )
01321 {
01322 sout_stream_sys_t *p_sys = p_stream->p_sys;
01323 aout_buffer_t *p_audio_buf;
01324 block_t *p_block, *p_audio_block;
01325 int i;
01326 *out = NULL;
01327
01328 while( (p_audio_buf = id->p_decoder->pf_decode_audio( id->p_decoder,
01329 &in )) )
01330 {
01331 if( p_sys->b_master_sync )
01332 {
01333 mtime_t i_dts = date_Get( &id->interpolated_pts ) + 1;
01334 if ( p_audio_buf->start_date - i_dts > MASTER_SYNC_MAX_DRIFT
01335 || p_audio_buf->start_date - i_dts < -MASTER_SYNC_MAX_DRIFT )
01336 {
01337 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
01338 date_Set( &id->interpolated_pts, p_audio_buf->start_date );
01339 i_dts = p_audio_buf->start_date + 1;
01340 }
01341 p_sys->i_master_drift = p_audio_buf->start_date - i_dts;
01342 date_Increment( &id->interpolated_pts, p_audio_buf->i_nb_samples );
01343 p_audio_buf->start_date -= p_sys->i_master_drift;
01344 p_audio_buf->end_date -= p_sys->i_master_drift;
01345 }
01346
01347 p_audio_block = p_audio_buf->p_sys;
01348 p_audio_block->i_buffer = p_audio_buf->i_nb_bytes;
01349 p_audio_block->i_dts = p_audio_block->i_pts =
01350 p_audio_buf->start_date;
01351 p_audio_block->i_length = p_audio_buf->end_date -
01352 p_audio_buf->start_date;
01353 p_audio_block->i_samples = p_audio_buf->i_nb_samples;
01354
01355
01356 for( i = 0; i < id->i_filter; i++ )
01357 {
01358 p_audio_block =
01359 id->pp_filter[i]->pf_audio_filter( id->pp_filter[i],
01360 p_audio_block );
01361 }
01362
01363 p_audio_buf->p_buffer = p_audio_block->p_buffer;
01364 p_audio_buf->i_nb_bytes = p_audio_block->i_buffer;
01365 p_audio_buf->i_nb_samples = p_audio_block->i_samples;
01366 p_audio_buf->start_date = p_audio_block->i_dts;
01367 p_audio_buf->end_date = p_audio_block->i_dts + p_audio_block->i_length;
01368
01369 p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf );
01370 block_ChainAppend( out, p_block );
01371 block_Release( p_audio_block );
01372 free( p_audio_buf );
01373 }
01374
01375 return VLC_SUCCESS;
01376 }
01377
01378 static void audio_release_buffer( aout_buffer_t *p_buffer )
01379 {
01380 if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
01381 if( p_buffer ) free( p_buffer );
01382 }
01383
01384 static aout_buffer_t *audio_new_buffer( decoder_t *p_dec, int i_samples )
01385 {
01386 aout_buffer_t *p_buffer;
01387 block_t *p_block;
01388 int i_size;
01389
01390 if( p_dec->fmt_out.audio.i_bitspersample )
01391 {
01392 i_size = i_samples * p_dec->fmt_out.audio.i_bitspersample / 8 *
01393 p_dec->fmt_out.audio.i_channels;
01394 }
01395 else if( p_dec->fmt_out.audio.i_bytes_per_frame &&
01396 p_dec->fmt_out.audio.i_frame_length )
01397 {
01398 i_size = i_samples * p_dec->fmt_out.audio.i_bytes_per_frame /
01399 p_dec->fmt_out.audio.i_frame_length;
01400 }
01401 else
01402 {
01403 i_size = i_samples * 4 * p_dec->fmt_out.audio.i_channels;
01404 }
01405
01406 p_buffer = malloc( sizeof(aout_buffer_t) );
01407 p_buffer->pf_release = audio_release_buffer;
01408 p_buffer->p_sys = p_block = block_New( p_dec, i_size );
01409
01410 p_buffer->p_buffer = p_block->p_buffer;
01411 p_buffer->i_size = p_buffer->i_nb_bytes = p_block->i_buffer;
01412 p_buffer->i_nb_samples = i_samples;
01413 p_block->i_samples = i_samples;
01414
01415 return p_buffer;
01416 }
01417
01418 static void audio_del_buffer( decoder_t *p_dec, aout_buffer_t *p_buffer )
01419 {
01420 if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
01421 if( p_buffer ) free( p_buffer );
01422 }
01423
01424
01425
01426
01427 static int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_t *id )
01428 {
01429 sout_stream_sys_t *p_sys = p_stream->p_sys;
01430 int i;
01431
01432
01433
01434
01435
01436
01437 id->p_decoder->fmt_out = id->p_decoder->fmt_in;
01438 id->p_decoder->fmt_out.i_extra = 0;
01439 id->p_decoder->fmt_out.p_extra = 0;
01440 id->p_decoder->pf_decode_video = 0;
01441 id->p_decoder->pf_vout_buffer_new = video_new_buffer_decoder;
01442 id->p_decoder->pf_vout_buffer_del = video_del_buffer_decoder;
01443 id->p_decoder->pf_picture_link = video_link_picture_decoder;
01444 id->p_decoder->pf_picture_unlink = video_unlink_picture_decoder;
01445 id->p_decoder->p_owner = malloc( sizeof(decoder_owner_sys_t) );
01446 for( i = 0; i < PICTURE_RING_SIZE; i++ )
01447 id->p_decoder->p_owner->pp_pics[i] = 0;
01448 id->p_decoder->p_owner->p_sys = p_sys;
01449
01450
01451 id->p_decoder->p_module =
01452 module_Need( id->p_decoder, "decoder", "$codec", 0 );
01453
01454 if( !id->p_decoder->p_module )
01455 {
01456 msg_Err( p_stream, "cannot find decoder" );
01457 return VLC_EGENERIC;
01458 }
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
01469 id->p_decoder->fmt_out.i_codec );
01470 id->p_encoder->fmt_in.video.i_chroma = id->p_decoder->fmt_out.i_codec;
01471
01472
01473
01474 id->p_encoder->fmt_in.video.i_width =
01475 id->p_encoder->fmt_out.video.i_width ?
01476 id->p_encoder->fmt_out.video.i_width :
01477 id->p_decoder->fmt_in.video.i_width ?
01478 id->p_decoder->fmt_in.video.i_width : 16;
01479 id->p_encoder->fmt_in.video.i_height =
01480 id->p_encoder->fmt_out.video.i_height ?
01481 id->p_encoder->fmt_out.video.i_height :
01482 id->p_decoder->fmt_in.video.i_height ?
01483 id->p_decoder->fmt_in.video.i_height : 16;
01484 id->p_encoder->fmt_in.video.i_frame_rate = 25;
01485 id->p_encoder->fmt_in.video.i_frame_rate_base = 1;
01486
01487 id->p_encoder->i_threads = p_sys->i_threads;
01488 id->p_encoder->p_cfg = p_sys->p_video_cfg;
01489
01490 id->p_encoder->p_module =
01491 module_Need( id->p_encoder, "encoder", p_sys->psz_venc, VLC_TRUE );
01492 if( !id->p_encoder->p_module )
01493 {
01494 msg_Err( p_stream, "cannot find encoder" );
01495 module_Unneed( id->p_decoder, id->p_decoder->p_module );
01496 id->p_decoder->p_module = 0;
01497 return VLC_EGENERIC;
01498 }
01499
01500
01501
01502 module_Unneed( id->p_encoder, id->p_encoder->p_module );
01503 if( id->p_encoder->fmt_out.p_extra )
01504 free( id->p_encoder->fmt_out.p_extra );
01505 id->p_encoder->p_module = NULL;
01506
01507 if( p_sys->i_threads >= 1 )
01508 {
01509 int i_priority = p_sys->b_high_priority ? VLC_THREAD_PRIORITY_OUTPUT :
01510 VLC_THREAD_PRIORITY_VIDEO;
01511 p_sys->id_video = id;
01512 vlc_mutex_init( p_stream, &p_sys->lock_out );
01513 vlc_cond_init( p_stream, &p_sys->cond );
01514 memset( p_sys->pp_pics, 0, sizeof(p_sys->pp_pics) );
01515 p_sys->i_first_pic = 0;
01516 p_sys->i_last_pic = 0;
01517 p_sys->p_buffers = NULL;
01518 p_sys->b_die = p_sys->b_error = 0;
01519 if( vlc_thread_create( p_sys, "encoder", EncoderThread, i_priority,
01520 VLC_FALSE ) )
01521 {
01522 msg_Err( p_stream, "cannot spawn encoder thread" );
01523 module_Unneed( id->p_decoder, id->p_decoder->p_module );
01524 id->p_decoder->p_module = 0;
01525 return VLC_EGENERIC;
01526 }
01527 }
01528
01529 return VLC_SUCCESS;
01530 }
01531
01532 static int transcode_video_encoder_open( sout_stream_t *p_stream,
01533 sout_stream_id_t *id )
01534 {
01535 sout_stream_sys_t *p_sys = p_stream->p_sys;
01536
01537
01538
01539
01540 int i_width = id->p_decoder->fmt_out.video.i_width -
01541 p_sys->i_crop_left - p_sys->i_crop_right;
01542 int i_height = id->p_decoder->fmt_out.video.i_height -
01543 p_sys->i_crop_top - p_sys->i_crop_bottom;
01544
01545 if( id->p_encoder->fmt_out.video.i_width <= 0 &&
01546 id->p_encoder->fmt_out.video.i_height <= 0 && p_sys->f_scale )
01547 {
01548
01549 id->p_encoder->fmt_out.video.i_width = i_width * p_sys->f_scale;
01550 id->p_encoder->fmt_out.video.i_height = i_height * p_sys->f_scale;
01551 }
01552 else if( id->p_encoder->fmt_out.video.i_width > 0 &&
01553 id->p_encoder->fmt_out.video.i_height <= 0 )
01554 {
01555 id->p_encoder->fmt_out.video.i_height =
01556 id->p_encoder->fmt_out.video.i_width / (double)i_width * i_height;
01557 }
01558 else if( id->p_encoder->fmt_out.video.i_width <= 0 &&
01559 id->p_encoder->fmt_out.video.i_height > 0 )
01560 {
01561 id->p_encoder->fmt_out.video.i_width =
01562 id->p_encoder->fmt_out.video.i_height / (double)i_height * i_width;
01563 }
01564
01565 if( p_sys->i_maxwidth
01566 && id->p_encoder->fmt_out.video.i_width > p_sys->i_maxwidth )
01567 id->p_encoder->fmt_out.video.i_width = p_sys->i_maxwidth;
01568 if( p_sys->i_maxheight
01569 && id->p_encoder->fmt_out.video.i_height > p_sys->i_maxheight )
01570 id->p_encoder->fmt_out.video.i_height = p_sys->i_maxheight;
01571
01572
01573 id->p_encoder->fmt_out.video.i_width =
01574 (id->p_encoder->fmt_out.video.i_width + 1) >> 1 << 1;
01575 id->p_encoder->fmt_out.video.i_height =
01576 (id->p_encoder->fmt_out.video.i_height + 1) >> 1 << 1;
01577
01578 id->p_encoder->fmt_in.video.i_width =
01579 id->p_encoder->fmt_out.video.i_width;
01580 id->p_encoder->fmt_in.video.i_height =
01581 id->p_encoder->fmt_out.video.i_height;
01582
01583 if( !id->p_encoder->fmt_out.video.i_frame_rate ||
01584 !id->p_encoder->fmt_out.video.i_frame_rate_base )
01585 {
01586 if( id->p_decoder->fmt_out.video.i_frame_rate &&
01587 id->p_decoder->fmt_out.video.i_frame_rate_base )
01588 {
01589 id->p_encoder->fmt_out.video.i_frame_rate =
01590 id->p_decoder->fmt_out.video.i_frame_rate;
01591 id->p_encoder->fmt_out.video.i_frame_rate_base =
01592 id->p_decoder->fmt_out.video.i_frame_rate_base;
01593 }
01594 else
01595 {
01596
01597 id->p_encoder->fmt_out.video.i_frame_rate = 25;
01598 id->p_encoder->fmt_out.video.i_frame_rate_base = 1;
01599 }
01600 }
01601
01602 id->p_encoder->fmt_in.video.i_frame_rate =
01603 id->p_encoder->fmt_out.video.i_frame_rate;
01604 id->p_encoder->fmt_in.video.i_frame_rate_base =
01605 id->p_encoder->fmt_out.video.i_frame_rate_base;
01606
01607 date_Init( &id->interpolated_pts,
01608 id->p_encoder->fmt_out.video.i_frame_rate,
01609 id->p_encoder->fmt_out.video.i_frame_rate_base );
01610
01611
01612 if( !id->p_encoder->fmt_out.video.i_aspect )
01613 {
01614 id->p_encoder->fmt_out.video.i_aspect =
01615 id->p_decoder->fmt_out.video.i_aspect;
01616 }
01617 id->p_encoder->fmt_in.video.i_aspect =
01618 id->p_encoder->fmt_out.video.i_aspect;
01619
01620 id->p_encoder->p_module =
01621 module_Need( id->p_encoder, "encoder", p_sys->psz_venc, VLC_TRUE );
01622 if( !id->p_encoder->p_module )
01623 {
01624 msg_Err( p_stream, "cannot find encoder" );
01625 return VLC_EGENERIC;
01626 }
01627
01628 id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
01629
01630
01631 if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','1','v') ||
01632 id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','2','v') )
01633 {
01634 id->p_encoder->fmt_out.i_codec = VLC_FOURCC('m','p','g','v');
01635 }
01636
01637 id->id = p_stream->p_sys->p_out->pf_add( p_stream->p_sys->p_out,
01638 &id->p_encoder->fmt_out );
01639 if( !id->id )
01640 {
01641 msg_Err( p_stream, "cannot add this stream" );
01642 return VLC_EGENERIC;
01643 }
01644
01645 return VLC_SUCCESS;
01646 }
01647
01648 static void transcode_video_close( sout_stream_t *p_stream,
01649 sout_stream_id_t *id )
01650 {
01651 int i, j;
01652
01653 if( p_stream->p_sys->i_threads >= 1 )
01654 {
01655 vlc_mutex_lock( &p_stream->p_sys->lock_out );
01656 p_stream->p_sys->b_die = 1;
01657 vlc_cond_signal( &p_stream->p_sys->cond );
01658 vlc_mutex_unlock( &p_stream->p_sys->lock_out );
01659 vlc_thread_join( p_stream->p_sys );
01660 vlc_mutex_destroy( &p_stream->p_sys->lock_out );
01661 vlc_cond_destroy( &p_stream->p_sys->cond );
01662 }
01663
01664
01665 if( id->p_decoder->p_module )
01666 module_Unneed( id->p_decoder, id->p_decoder->p_module );
01667
01668 if( id->p_decoder->p_owner )
01669 {
01670
01671 for( i = 0; i < PICTURE_RING_SIZE; i++ )
01672 {
01673 if( id->p_decoder->p_owner->pp_pics[i] )
01674 video_del_buffer( VLC_OBJECT(id->p_decoder),
01675 id->p_decoder->p_owner->pp_pics[i] );
01676 }
01677 free( id->p_decoder->p_owner );
01678 }
01679
01680
01681 if( id->p_encoder->p_module )
01682 module_Unneed( id->p_encoder, id->p_encoder->p_module );
01683
01684
01685 for( i = 0; i < id->i_filter; i++ )
01686 {
01687 vlc_object_detach( id->pp_filter[i] );
01688 if( id->pp_filter[i]->p_module )
01689 module_Unneed( id->pp_filter[i], id->pp_filter[i]->p_module );
01690
01691
01692 for( j = 0; j < PICTURE_RING_SIZE; j++ )
01693 {
01694 if( id->pp_filter[i]->p_owner->pp_pics[j] )
01695 video_del_buffer( VLC_OBJECT(id->pp_filter[i]),
01696 id->pp_filter[i]->p_owner->pp_pics[j] );
01697 }
01698 free( id->pp_filter[i]->p_owner );
01699
01700 vlc_object_destroy( id->pp_filter[i] );
01701 }
01702 for( i = 0; i < id->i_vfilter; i++ )
01703 {
01704 vlc_object_detach( id->pp_vfilter[i] );
01705 if( id->pp_vfilter[i]->p_module )
01706 module_Unneed( id->pp_vfilter[i], id->pp_vfilter[i]->p_module );
01707
01708
01709 for( j = 0; j < PICTURE_RING_SIZE; j++ )
01710 {
01711 if( id->pp_vfilter[i]->p_owner->pp_pics[j] )
01712 video_del_buffer( VLC_OBJECT(id->pp_vfilter[i]),
01713 id->pp_vfilter[i]->p_owner->pp_pics[j] );
01714 }
01715 free( id->pp_vfilter[i]->p_owner );
01716
01717 vlc_object_destroy( id->pp_vfilter[i] );
01718 }
01719 }
01720
01721 static int transcode_video_process( sout_stream_t *p_stream,
01722 sout_stream_id_t *id,
01723 block_t *in, block_t **out )
01724 {
01725 sout_stream_sys_t *p_sys = p_stream->p_sys;
01726 int i_duplicate = 1, i;
01727 picture_t *p_pic, *p_pic2 = NULL;
01728 *out = NULL;
01729
01730 while( (p_pic = id->p_decoder->pf_decode_video( id->p_decoder, &in )) )
01731 {
01732 subpicture_t *p_subpic = 0;
01733
01734 if( p_stream->p_sout->i_out_pace_nocontrol && p_sys->b_hurry_up )
01735 {
01736 mtime_t current_date = mdate();
01737 if( current_date + 50000 > p_pic->date )
01738 {
01739 msg_Dbg( p_stream, "late picture skipped ("I64Fd")",
01740 current_date + 50000 - p_pic->date );
01741 p_pic->pf_release( p_pic );
01742 continue;
01743 }
01744 }
01745
01746 if( p_sys->b_master_sync )
01747 {
01748 mtime_t i_video_drift;
01749 mtime_t i_master_drift = p_sys->i_master_drift;
01750 mtime_t i_pts;
01751
01752 i_pts = date_Get( &id->interpolated_pts ) + 1;
01753 if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
01754 || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
01755 {
01756 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
01757 date_Set( &id->interpolated_pts, p_pic->date );
01758 i_pts = p_pic->date + 1;
01759 }
01760 i_video_drift = p_pic->date - i_pts;
01761 i_duplicate = 1;
01762
01763
01764 p_pic->date = i_pts;
01765
01766 if( i_video_drift < i_master_drift - 50000 )
01767 {
01768 #if 0
01769 msg_Dbg( p_stream, "dropping frame (%i)",
01770 (int)(i_video_drift - i_master_drift) );
01771 #endif
01772 p_pic->pf_release( p_pic );
01773 continue;
01774 }
01775 else if( i_video_drift > i_master_drift + 50000 )
01776 {
01777 #if 0
01778 msg_Dbg( p_stream, "adding frame (%i)",
01779 (int)(i_video_drift - i_master_drift) );
01780 #endif
01781 i_duplicate = 2;
01782 }
01783 }
01784
01785 if( !id->p_encoder->p_module )
01786 {
01787 if( transcode_video_encoder_open( p_stream, id ) != VLC_SUCCESS )
01788 {
01789 p_pic->pf_release( p_pic );
01790 transcode_video_close( p_stream, id );
01791 id->b_transcode = VLC_FALSE;
01792 return VLC_EGENERIC;
01793 }
01794
01795
01796 if( p_stream->p_sys->b_deinterlace )
01797 {
01798 id->pp_filter[id->i_filter] =
01799 vlc_object_create( p_stream, VLC_OBJECT_FILTER );
01800 vlc_object_attach( id->pp_filter[id->i_filter], p_stream );
01801
01802 id->pp_filter[id->i_filter]->pf_vout_buffer_new =
01803 video_new_buffer_filter;
01804 id->pp_filter[id->i_filter]->pf_vout_buffer_del =
01805 video_del_buffer_filter;
01806
01807 id->pp_filter[id->i_filter]->fmt_in = id->p_decoder->fmt_out;
01808 id->pp_filter[id->i_filter]->fmt_out = id->p_decoder->fmt_out;
01809 id->pp_filter[id->i_filter]->p_cfg = p_sys->p_deinterlace_cfg;
01810 id->pp_filter[id->i_filter]->p_module =
01811 module_Need( id->pp_filter[id->i_filter],
01812 "video filter2", p_sys->psz_deinterlace, 0 );
01813 if( id->pp_filter[id->i_filter]->p_module )
01814 {
01815 id->pp_filter[id->i_filter]->p_owner =
01816 malloc( sizeof(filter_owner_sys_t) );
01817 for( i = 0; i < PICTURE_RING_SIZE; i++ )
01818 id->pp_filter[id->i_filter]->p_owner->pp_pics[i] = 0;
01819 id->pp_filter[id->i_filter]->p_owner->p_sys = p_sys;
01820
01821 id->i_filter++;
01822 }
01823 else
01824 {
01825 msg_Dbg( p_stream, "no video filter found" );
01826 vlc_object_detach( id->pp_filter[id->i_filter] );
01827 vlc_object_destroy( id->pp_filter[id->i_filter] );
01828 }
01829 }
01830
01831
01832 if( id->p_decoder->fmt_out.video.i_chroma !=
01833 id->p_encoder->fmt_in.video.i_chroma ||
01834 id->p_decoder->fmt_out.video.i_width !=
01835 id->p_encoder->fmt_out.video.i_width ||
01836 id->p_decoder->fmt_out.video.i_height !=
01837 id->p_encoder->fmt_out.video.i_height ||
01838 p_sys->i_crop_top > 0 || p_sys->i_crop_bottom > 0 ||
01839 p_sys->i_crop_left > 0 || p_sys->i_crop_right > 0 )
01840 {
01841 id->pp_filter[id->i_filter] =
01842 vlc_object_create( p_stream, VLC_OBJECT_FILTER );
01843 vlc_object_attach( id->pp_filter[id->i_filter], p_stream );
01844
01845 id->pp_filter[id->i_filter]->pf_vout_buffer_new =
01846 video_new_buffer_filter;
01847 id->pp_filter[id->i_filter]->pf_vout_buffer_del =
01848 video_del_buffer_filter;
01849
01850 id->pp_filter[id->i_filter]->fmt_in = id->p_decoder->fmt_out;
01851 id->pp_filter[id->i_filter]->fmt_out = id->p_encoder->fmt_in;
01852 id->pp_filter[id->i_filter]->p_cfg = NULL;
01853 id->pp_filter[id->i_filter]->p_module =
01854 module_Need( id->pp_filter[id->i_filter],
01855 "video filter2", 0, 0 );
01856 if( id->pp_filter[id->i_filter]->p_module )
01857 {
01858 id->pp_filter[id->i_filter]->p_owner =
01859 malloc( sizeof(filter_owner_sys_t) );
01860 for( i = 0; i < PICTURE_RING_SIZE; i++ )
01861 id->pp_filter[id->i_filter]->p_owner->pp_pics[i] = 0;
01862 id->pp_filter[id->i_filter]->p_owner->p_sys = p_sys;
01863
01864 id->i_filter++;
01865 }
01866 else
01867 {
01868 msg_Dbg( p_stream, "no video filter found" );
01869 vlc_object_detach( id->pp_filter[id->i_filter] );
01870 vlc_object_destroy( id->pp_filter[id->i_filter] );
01871
01872 p_pic->pf_release( p_pic );
01873 transcode_video_close( p_stream, id );
01874 id->b_transcode = VLC_FALSE;
01875 return VLC_EGENERIC;
01876 }
01877 }
01878
01879 for( i = 0; i < p_sys->i_vfilters; i++ )
01880 {
01881 id->pp_vfilter[id->i_vfilter] =
01882 vlc_object_create( p_stream, VLC_OBJECT_FILTER );
01883 vlc_object_attach( id->pp_vfilter[id->i_vfilter], p_stream );
01884
01885 id->pp_vfilter[id->i_vfilter]->pf_vout_buffer_new =
01886 video_new_buffer_filter;
01887 id->pp_vfilter[id->i_vfilter]->pf_vout_buffer_del =
01888 video_del_buffer_filter;
01889
01890 id->pp_vfilter[id->i_vfilter]->fmt_in = id->p_encoder->fmt_in;
01891 id->pp_vfilter[id->i_vfilter]->fmt_out = id->p_encoder->fmt_in;
01892 id->pp_vfilter[id->i_vfilter]->p_cfg = p_sys->p_vfilters_cfg[i];
01893 id->pp_vfilter[id->i_vfilter]->p_module =
01894 module_Need( id->pp_vfilter[id->i_vfilter],
01895 "video filter2", p_sys->psz_vfilters[i], 0 );
01896 if( id->pp_vfilter[id->i_vfilter]->p_module )
01897 {
01898 id->pp_vfilter[id->i_vfilter]->p_owner =
01899 malloc( sizeof(filter_owner_sys_t) );
01900 for( i = 0; i < PICTURE_RING_SIZE; i++ )
01901 id->pp_vfilter[id->i_vfilter]->p_owner->pp_pics[i] = 0;
01902 id->pp_vfilter[id->i_vfilter]->p_owner->p_sys = p_sys;
01903
01904 id->i_vfilter++;
01905 }
01906 else
01907 {
01908 msg_Dbg( p_stream, "no video filter found" );
01909 vlc_object_detach( id->pp_vfilter[id->i_vfilter] );
01910 vlc_object_destroy( id->pp_vfilter[id->i_vfilter] );
01911 }
01912 }
01913 }
01914
01915
01916 for( i = 0; i < id->i_filter; i++ )
01917 {
01918 p_pic = id->pp_filter[i]->pf_video_filter(id->pp_filter[i], p_pic);
01919 }
01920
01921
01922
01923
01924
01925
01926 if( p_sys->p_spu )
01927 {
01928 p_subpic = spu_SortSubpictures( p_sys->p_spu, p_pic->date );
01929
01930 }
01931
01932
01933 if( p_subpic )
01934 {
01935 int i_scale_width, i_scale_height;
01936 video_format_t *p_fmt;
01937
01938 i_scale_width = id->p_encoder->fmt_in.video.i_width * 1000 /
01939 id->p_decoder->fmt_out.video.i_width;
01940 i_scale_height = id->p_encoder->fmt_in.video.i_height * 1000 /
01941 id->p_decoder->fmt_out.video.i_height;
01942
01943 if( p_pic->i_refcount && !id->i_filter )
01944 {
01945
01946 picture_t *p_tmp = video_new_buffer_decoder( id->p_decoder );
01947 if( p_tmp )
01948 {
01949 vout_CopyPicture( p_stream, p_tmp, p_pic );
01950 p_pic->pf_release( p_pic );
01951 p_pic = p_tmp;
01952 }
01953 }
01954
01955 if( id->i_filter )
01956 p_fmt = &id->pp_filter[id->i_filter -1]->fmt_out.video;
01957 else
01958 p_fmt = &id->p_decoder->fmt_out.video;
01959
01960
01961 p_fmt->i_sar_num = p_fmt->i_aspect *
01962 p_fmt->i_height / p_fmt->i_width;
01963 p_fmt->i_sar_den = VOUT_ASPECT_FACTOR;
01964
01965 spu_RenderSubpictures( p_sys->p_spu, p_fmt, p_pic, p_pic, p_subpic,
01966 i_scale_width, i_scale_height );
01967 }
01968
01969
01970 for( i = 0; i < id->i_vfilter; i++ )
01971 {
01972 p_pic = id->pp_vfilter[i]->pf_video_filter(id->pp_vfilter[i], p_pic);
01973 }
01974
01975 if( p_sys->i_threads == 0 )
01976 {
01977 block_t *p_block;
01978 p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
01979 block_ChainAppend( out, p_block );
01980 }
01981
01982 if( p_sys->b_master_sync )
01983 {
01984 mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
01985 if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
01986 || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
01987 {
01988 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
01989 date_Set( &id->interpolated_pts, p_pic->date );
01990 i_pts = p_pic->date + 1;
01991 }
01992 date_Increment( &id->interpolated_pts, 1 );
01993 }
01994
01995 if( p_sys->b_master_sync && i_duplicate > 1 )
01996 {
01997 mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
01998 if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
01999 || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
02000 {
02001 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
02002 date_Set( &id->interpolated_pts, p_pic->date );
02003 i_pts = p_pic->date + 1;
02004 }
02005 date_Increment( &id->interpolated_pts, 1 );
02006
02007 if( p_sys->i_threads >= 1 )
02008 {
02009
02010 p_pic2 = video_new_buffer_decoder( id->p_decoder );
02011 if( p_pic2 != NULL )
02012 {
02013 vout_CopyPicture( p_stream, p_pic2, p_pic );
02014 p_pic2->date = i_pts;
02015 }
02016 }
02017 else
02018 {
02019 block_t *p_block;
02020 p_pic->date = i_pts;
02021 p_block = id->p_encoder->pf_encode_video(id->p_encoder, p_pic);
02022 block_ChainAppend( out, p_block );
02023 }
02024 }
02025
02026 if( p_sys->i_threads == 0 )
02027 {
02028 p_pic->pf_release( p_pic );
02029 }
02030 else
02031 {
02032 vlc_mutex_lock( &p_sys->lock_out );
02033 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic;
02034 p_sys->i_last_pic %= PICTURE_RING_SIZE;
02035 *out = p_sys->p_buffers;
02036 p_sys->p_buffers = NULL;
02037 if( p_pic2 != NULL )
02038 {
02039 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic2;
02040 p_sys->i_last_pic %= PICTURE_RING_SIZE;
02041 }
02042 vlc_cond_signal( &p_sys->cond );
02043 vlc_mutex_unlock( &p_sys->lock_out );
02044 }
02045
02046 }
02047
02048 return VLC_SUCCESS;
02049 }
02050
02051 static int EncoderThread( sout_stream_sys_t *p_sys )
02052 {
02053 sout_stream_id_t *id = p_sys->id_video;
02054 picture_t *p_pic;
02055
02056 while( !p_sys->b_die && !p_sys->b_error )
02057 {
02058 block_t *p_block;
02059
02060 vlc_mutex_lock( &p_sys->lock_out );
02061 while( p_sys->i_last_pic == p_sys->i_first_pic )
02062 {
02063 vlc_cond_wait( &p_sys->cond, &p_sys->lock_out );
02064 if( p_sys->b_die || p_sys->b_error ) break;
02065 }
02066 if( p_sys->b_die || p_sys->b_error )
02067 {
02068 vlc_mutex_unlock( &p_sys->lock_out );
02069 break;
02070 }
02071
02072 p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
02073 p_sys->i_first_pic %= PICTURE_RING_SIZE;
02074 vlc_mutex_unlock( &p_sys->lock_out );
02075
02076 p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
02077 vlc_mutex_lock( &p_sys->lock_out );
02078 block_ChainAppend( &p_sys->p_buffers, p_block );
02079
02080 vlc_mutex_unlock( &p_sys->lock_out );
02081
02082 p_pic->pf_release( p_pic );
02083 }
02084
02085 while( p_sys->i_last_pic != p_sys->i_first_pic )
02086 {
02087 p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
02088 p_sys->i_first_pic %= PICTURE_RING_SIZE;
02089
02090 p_pic->pf_release( p_pic );
02091 }
02092
02093 block_ChainRelease( p_sys->p_buffers );
02094
02095 return 0;
02096 }
02097
02098 struct picture_sys_t
02099 {
02100 vlc_object_t *p_owner;
02101 };
02102
02103 static void video_release_buffer( picture_t *p_pic )
02104 {
02105 if( p_pic && !p_pic->i_refcount && p_pic->pf_release && p_pic->p_sys )
02106 {
02107 video_del_buffer_decoder( (decoder_t *)p_pic->p_sys->p_owner, p_pic );
02108 }
02109 else if( p_pic && p_pic->i_refcount > 0 ) p_pic->i_refcount--;
02110 }
02111
02112 static picture_t *video_new_buffer( vlc_object_t *p_this, picture_t **pp_ring,
02113 sout_stream_sys_t *p_sys )
02114 {
02115 decoder_t *p_dec = (decoder_t *)p_this;
02116 picture_t *p_pic;
02117 int i;
02118
02119
02120 for( i = 0; i < PICTURE_RING_SIZE; i++ )
02121 {
02122 if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
02123 {
02124 pp_ring[i]->i_status = RESERVED_PICTURE;
02125 return pp_ring[i];
02126 }
02127 }
02128 for( i = 0; i < PICTURE_RING_SIZE; i++ )
02129 {
02130 if( pp_ring[i] == 0 ) break;
02131 }
02132
02133 if( i == PICTURE_RING_SIZE && p_sys->i_threads >= 1 )
02134 {
02135 int i_first_pic = p_sys->i_first_pic;
02136
02137 if( p_sys->i_first_pic != p_sys->i_last_pic )
02138 {
02139
02140 while( p_sys->i_first_pic == i_first_pic )
02141 msleep( 100000 );
02142 }
02143
02144
02145 for( i = 0; i < PICTURE_RING_SIZE; i++ )
02146 {
02147 if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
02148 {
02149 pp_ring[i]->i_status = RESERVED_PICTURE;
02150 return pp_ring[i];
02151 }
02152 }
02153 for( i = 0; i < PICTURE_RING_SIZE; i++ )
02154 {
02155 if( pp_ring[i] == 0 ) break;
02156 }
02157 }
02158
02159 if( i == PICTURE_RING_SIZE )
02160 {
02161 msg_Err( p_this, "decoder/filter is leaking pictures, "
02162 "resetting its ring buffer" );
02163
02164 for( i = 0; i < PICTURE_RING_SIZE; i++ )
02165 {
02166 pp_ring[i]->pf_release( pp_ring[i] );
02167 }
02168
02169 i = 0;
02170 }
02171
02172 p_pic = malloc( sizeof(picture_t) );
02173 p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
02174 vout_AllocatePicture( VLC_OBJECT(p_dec), p_pic,
02175 p_dec->fmt_out.video.i_chroma,
02176 p_dec->fmt_out.video.i_width,
02177 p_dec->fmt_out.video.i_height,
02178 p_dec->fmt_out.video.i_aspect );
02179
02180 if( !p_pic->i_planes )
02181 {
02182 free( p_pic );
02183 return 0;
02184 }
02185
02186 p_pic->pf_release = video_release_buffer;
02187 p_pic->p_sys = malloc( sizeof(picture_sys_t) );
02188 p_pic->p_sys->p_owner = p_this;
02189 p_pic->i_status = RESERVED_PICTURE;
02190
02191 pp_ring[i] = p_pic;
02192
02193 return p_pic;
02194 }
02195
02196 static picture_t *video_new_buffer_decoder( decoder_t *p_dec )
02197 {
02198 return video_new_buffer( VLC_OBJECT(p_dec),
02199 p_dec->p_owner->pp_pics, p_dec->p_owner->p_sys );
02200 }
02201
02202 static picture_t *video_new_buffer_filter( filter_t *p_filter )
02203 {
02204 return video_new_buffer( VLC_OBJECT(p_filter),
02205 p_filter->p_owner->pp_pics,
02206 p_filter->p_owner->p_sys );
02207 }
02208
02209 static void video_del_buffer( vlc_object_t *p_this, picture_t *p_pic )
02210 {
02211 if( p_pic && p_pic->p_data_orig ) free( p_pic->p_data_orig );
02212 if( p_pic && p_pic->p_sys ) free( p_pic->p_sys );
02213 if( p_pic ) free( p_pic );
02214 }
02215
02216 static void video_del_buffer_decoder( decoder_t *p_decoder, picture_t *p_pic )
02217 {
02218 p_pic->i_refcount = 0;
02219 p_pic->i_status = DESTROYED_PICTURE;
02220 }
02221
02222 static void video_del_buffer_filter( filter_t *p_filter, picture_t *p_pic )
02223 {
02224 p_pic->i_refcount = 0;
02225 p_pic->i_status = DESTROYED_PICTURE;
02226 }
02227
02228 static void video_link_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
02229 {
02230 p_pic->i_refcount++;
02231 }
02232
02233 static void video_unlink_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
02234 {
02235 video_release_buffer( p_pic );
02236 }
02237
02238
02239
02240
02241 static subpicture_t *spu_new_buffer( decoder_t * );
02242 static void spu_del_buffer( decoder_t *, subpicture_t * );
02243
02244 static int transcode_spu_new( sout_stream_t *p_stream, sout_stream_id_t *id )
02245 {
02246 sout_stream_sys_t *p_sys = p_stream->p_sys;
02247
02248
02249
02250
02251
02252
02253 id->p_decoder->pf_spu_buffer_new = spu_new_buffer;
02254 id->p_decoder->pf_spu_buffer_del = spu_del_buffer;
02255 id->p_decoder->p_owner = (decoder_owner_sys_t *)p_stream;
02256
02257
02258 id->p_decoder->p_module =
02259 module_Need( id->p_decoder, "decoder", "$codec", 0 );
02260
02261 if( !id->p_decoder->p_module )
02262 {
02263 msg_Err( p_stream, "cannot find decoder" );
02264 return VLC_EGENERIC;
02265 }
02266
02267 if( !p_sys->b_soverlay )
02268 {
02269
02270
02271
02272
02273
02274 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
02275 id->p_decoder->fmt_in.i_codec );
02276
02277 id->p_encoder->p_cfg = p_sys->p_spu_cfg;
02278
02279 id->p_encoder->p_module =
02280 module_Need( id->p_encoder, "encoder", p_sys->psz_senc, VLC_TRUE );
02281
02282 if( !id->p_encoder->p_module )
02283 {
02284 module_Unneed( id->p_decoder, id->p_decoder->p_module );
02285 msg_Err( p_stream, "cannot find encoder" );
02286 return VLC_EGENERIC;
02287 }
02288 }
02289
02290 if( !p_sys->p_spu )
02291 {
02292 p_sys->p_spu = spu_Create( p_stream );
02293 spu_Init( p_sys->p_spu );
02294 }
02295
02296 return VLC_SUCCESS;
02297 }
02298
02299 static void transcode_spu_close( sout_stream_t *p_stream, sout_stream_id_t *id)
02300 {
02301
02302 if( id->p_decoder->p_module )
02303 module_Unneed( id->p_decoder, id->p_decoder->p_module );
02304
02305
02306 if( id->p_encoder->p_module )
02307 module_Unneed( id->p_encoder, id->p_encoder->p_module );
02308 }
02309
02310 static int transcode_spu_process( sout_stream_t *p_stream,
02311 sout_stream_id_t *id,
02312 block_t *in, block_t **out )
02313 {
02314 sout_stream_sys_t *p_sys = p_stream->p_sys;
02315 subpicture_t *p_subpic;
02316 *out = NULL;
02317
02318 p_subpic = id->p_decoder->pf_decode_sub( id->p_decoder, &in );
02319 if( !p_subpic ) return VLC_EGENERIC;
02320
02321 if( p_sys->b_master_sync && p_sys->i_master_drift )
02322 {
02323 p_subpic->i_start -= p_sys->i_master_drift;
02324 if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
02325 }
02326
02327 if( p_sys->b_soverlay )
02328 {
02329 spu_DisplaySubpicture( p_sys->p_spu, p_subpic );
02330 }
02331 else
02332 {
02333 block_t *p_block;
02334
02335 p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
02336 spu_del_buffer( id->p_decoder, p_subpic );
02337
02338 if( p_block )
02339 {
02340 block_ChainAppend( out, p_block );
02341 return VLC_SUCCESS;
02342 }
02343 }
02344
02345 return VLC_EGENERIC;
02346 }
02347
02348 static subpicture_t *spu_new_buffer( decoder_t *p_dec )
02349 {
02350 sout_stream_t *p_stream = (sout_stream_t *)p_dec->p_owner;
02351 return spu_CreateSubpicture( p_stream->p_sys->p_spu );
02352 }
02353
02354 static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_subpic )
02355 {
02356 sout_stream_t *p_stream = (sout_stream_t *)p_dec->p_owner;
02357 spu_DestroySubpicture( p_stream->p_sys->p_spu, p_subpic );
02358 }
02359
02360
02361
02362
02363 static int transcode_osd_new( sout_stream_t *p_stream, sout_stream_id_t *id )
02364 {
02365 sout_stream_sys_t *p_sys = p_stream->p_sys;
02366 es_format_t fmt;
02367
02368 fmt.i_cat = SPU_ES;
02369 fmt.i_id = 0xbd1f;
02370 fmt.i_group = 3;
02371 fmt.i_codec = VLC_FOURCC( 'Y', 'U', 'V', 'A' );
02372 fmt.psz_language = strdup( "osd" );
02373
02374 id = malloc( sizeof( sout_stream_id_t ) );
02375 memset( id, 0, sizeof(sout_stream_id_t) );
02376
02377 id->id = NULL;
02378 id->p_decoder = NULL;
02379 id->p_encoder = NULL;
02380
02381
02382 id->p_encoder = vlc_object_create( p_stream, VLC_OBJECT_ENCODER );
02383 if( !id->p_encoder )
02384 {
02385 msg_Err( p_stream, "out of memory" );
02386 goto error;
02387 }
02388 vlc_object_attach( id->p_encoder, p_stream );
02389 id->p_encoder->p_module = NULL;
02390
02391
02392 es_format_Init( &id->p_encoder->fmt_out, fmt.i_cat, 0 );
02393 id->p_encoder->fmt_out.i_id = fmt.i_id;
02394 id->p_encoder->fmt_out.i_group = fmt.i_group;
02395 id->p_encoder->fmt_out.psz_language = strdup( fmt.psz_language );
02396
02397 if( p_sys->i_osdcodec != 0 || p_sys->psz_osdenc )
02398 {
02399 msg_Dbg( p_stream, "creating osdmenu transcoding from fcc=`%4.4s' "
02400 "to fcc=`%4.4s'", (char*)&fmt.i_codec,
02401 (char*)&p_sys->i_osdcodec );
02402
02403
02404 id->p_encoder->fmt_out.i_codec = p_sys->i_osdcodec;
02405
02406
02407
02408
02409
02410
02411 es_format_Init( &id->p_encoder->fmt_in, fmt.i_cat, fmt.i_codec );
02412 id->p_encoder->fmt_in.psz_language = strdup( fmt.psz_language );
02413
02414 id->p_encoder->p_cfg = p_sys->p_osd_cfg;
02415
02416 id->p_encoder->p_module =
02417 module_Need( id->p_encoder, "encoder", p_sys->psz_osdenc, VLC_TRUE );
02418
02419 if( !id->p_encoder->p_module )
02420 {
02421 msg_Err( p_stream, "cannot find encoder" );
02422 goto error;
02423 }
02424
02425
02426 id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
02427 id->b_transcode = VLC_TRUE;
02428
02429 if( !id->id ) goto error;
02430 }
02431 else
02432 {
02433 msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
02434 (char*)&fmt.i_codec );
02435 id->id = p_sys->p_out->pf_add( p_sys->p_out, &fmt );
02436 id->b_transcode = VLC_FALSE;
02437
02438 if( !id->id ) goto error;
02439 }
02440
02441 p_sys->id_osd = id;
02442 p_sys->b_es_osd = VLC_TRUE;
02443
02444 if( !p_sys->p_spu )
02445 {
02446 p_sys->p_spu = spu_Create( p_stream );
02447 if( spu_Init( p_sys->p_spu ) != VLC_SUCCESS )
02448 msg_Err( p_sys, "spu initialisation failed" );
02449 }
02450
02451 if( fmt.psz_language )
02452 free( fmt.psz_language );
02453
02454 return VLC_SUCCESS;
02455
02456 error:
02457 msg_Err( p_stream, "starting osd encoding thread failed" );
02458 if( id->p_encoder->p_module )
02459 module_Unneed( id->p_encoder, id->p_encoder->p_module );
02460 if( id->p_encoder )
02461 {
02462 vlc_object_detach( id->p_encoder );
02463 vlc_object_destroy( id->p_encoder );
02464 }
02465 if( fmt.psz_language ) free( fmt.psz_language );
02466 if( id ) free( id );
02467 p_sys->id_osd = NULL;
02468 p_sys->b_es_osd = VLC_FALSE;
02469 return VLC_EGENERIC;
02470 }
02471
02472 static void transcode_osd_close( sout_stream_t *p_stream, sout_stream_id_t *id)
02473 {
02474 sout_stream_sys_t *p_sys = p_stream->p_sys;
02475
02476
02477 if( p_sys->b_es_osd && id )
02478 {
02479 if( id->p_encoder->p_module )
02480 module_Unneed( id->p_encoder, id->p_encoder->p_module );
02481
02482 if( id->id ) p_sys->p_out->pf_del( p_sys->p_out, id->id );
02483
02484 if( id->p_encoder )
02485 {
02486 vlc_object_detach( id->p_encoder );
02487 vlc_object_destroy( id->p_encoder );
02488 }
02489 }
02490 p_sys->b_es_osd = VLC_FALSE;
02491 if( id ) free( id );
02492 }
02493
02494 static int transcode_osd_process( sout_stream_t *p_stream,
02495 sout_stream_id_t *id,
02496 block_t *in, block_t **out )
02497 {
02498 sout_stream_sys_t *p_sys = p_stream->p_sys;
02499 subpicture_t *p_subpic = NULL;
02500
02501
02502 if( p_sys->p_spu && in->i_dts > 0)
02503 {
02504 p_subpic = spu_SortSubpictures( p_sys->p_spu, in->i_dts );
02505 }
02506 else
02507 {
02508 msg_Warn( p_stream, "spu channel not initialized, doing it now" );
02509 if( !p_sys->p_spu )
02510 {
02511 p_sys->p_spu = spu_Create( p_stream );
02512 if( spu_Init( p_sys->p_spu ) != VLC_SUCCESS )
02513 msg_Err( p_stream, "spu initialisation failed" );
02514 }
02515 }
02516
02517 if( p_subpic )
02518 {
02519 block_t *p_block = NULL;
02520
02521 if( p_sys->b_master_sync && p_sys->i_master_drift )
02522 {
02523 p_subpic->i_start -= p_sys->i_master_drift;
02524 if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
02525 }
02526
02527 p_block = p_sys->id_osd->p_encoder->pf_encode_sub( p_sys->id_osd->p_encoder, p_subpic );
02528 if( p_block )
02529 {
02530 p_block->i_dts = p_block->i_pts = in->i_dts;
02531 block_ChainAppend( out, p_block );
02532 if( *out )
02533 {
02534 if( p_sys->p_out->pf_send( p_sys->p_out, p_sys->id_osd->id, *out ) == VLC_SUCCESS )
02535 spu_DestroySubpicture( p_sys->p_spu, p_subpic );
02536 }
02537 return VLC_SUCCESS;
02538 }
02539 }
02540 return VLC_EGENERIC;
02541 }