1 /*****************************************************************************
2 * transcode.c: transcoding stream output module
3 *****************************************************************************
4 * Copyright (C) 2003-2004 the VideoLAN team
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8 * Gildas Bazin <gbazin@videolan.org>
9 * Jean-Paul Saman <jpsaman #_at_# m2x dot nl>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24 *****************************************************************************/
26 /*****************************************************************************
28 *****************************************************************************/
34 #include <vlc/input.h>
37 #include <vlc/decoder.h>
38 #include <vlc_filter.h>
41 #define MASTER_SYNC_MAX_DRIFT 100000
43 /*****************************************************************************
45 *****************************************************************************/
46 #define VENC_TEXT N_("Video encoder")
47 #define VENC_LONGTEXT N_( \
48 "This is the video encoder module that will be used (and its associated "\
50 #define VCODEC_TEXT N_("Destination video codec")
51 #define VCODEC_LONGTEXT N_( \
52 "This is the video codec that will be used.")
53 #define VB_TEXT N_("Video bitrate")
54 #define VB_LONGTEXT N_( \
55 "Target bitrate of the transcoded video stream." )
56 #define SCALE_TEXT N_("Video scaling")
57 #define SCALE_LONGTEXT N_( \
58 "Scale factor to apply to the video while transcoding (eg: 0.25)")
59 #define FPS_TEXT N_("Video frame-rate")
60 #define FPS_LONGTEXT N_( \
61 "Target output frame rate for the video stream." )
62 #define DEINTERLACE_TEXT N_("Deinterlace video")
63 #define DEINTERLACE_LONGTEXT N_( \
64 "Deinterlace the video before encoding." )
65 #define DEINTERLACE_MODULE_TEXT N_("Deinterlace module")
66 #define DEINTERLACE_MODULE_LONGTEXT N_( \
67 "Specify the deinterlace module to use." )
68 #define WIDTH_TEXT N_("Video width")
69 #define WIDTH_LONGTEXT N_( \
70 "Output video width." )
71 #define HEIGHT_TEXT N_("Video height")
72 #define HEIGHT_LONGTEXT N_( \
73 "Output video height." )
74 #define MAXWIDTH_TEXT N_("Maximum video width")
75 #define MAXWIDTH_LONGTEXT N_( \
76 "Maximum output video width." )
77 #define MAXHEIGHT_TEXT N_("Maximum video height")
78 #define MAXHEIGHT_LONGTEXT N_( \
79 "Maximum output video height." )
80 #define VFILTER_TEXT N_("Video filter")
81 #define VFILTER_LONGTEXT N_( \
82 "Video filters will be applied to the video streams (after overlays " \
83 "are applied). You must enter a comma-separated list of filters." )
85 #define CROPTOP_TEXT N_("Video crop (top)")
86 #define CROPTOP_LONGTEXT N_( \
87 "Number of pixels to crop at the top of the video." )
88 #define CROPLEFT_TEXT N_("Video crop (left)")
89 #define CROPLEFT_LONGTEXT N_( \
90 "Number of pixels to crop at the left of the video." )
91 #define CROPBOTTOM_TEXT N_("Video crop (bottom)")
92 #define CROPBOTTOM_LONGTEXT N_( \
93 "Number of pixels to crop at the bottom of the video." )
94 #define CROPRIGHT_TEXT N_("Video crop (right)")
95 #define CROPRIGHT_LONGTEXT N_( \
96 "Number of pixels to crop at the right of the video." )
98 #define PADDTOP_TEXT N_("Video padding (top)")
99 #define PADDTOP_LONGTEXT N_( \
100 "Size of the black border to add at the top of the video." )
101 #define PADDLEFT_TEXT N_("Video padding (left)")
102 #define PADDLEFT_LONGTEXT N_( \
103 "Size of the black border to add at the left of the video." )
104 #define PADDBOTTOM_TEXT N_("Video padding (bottom)")
105 #define PADDBOTTOM_LONGTEXT N_( \
106 "Size of the black border to add at the bottom of the video." )
107 #define PADDRIGHT_TEXT N_("Video padding (right)")
108 #define PADDRIGHT_LONGTEXT N_( \
109 "Size of the black border to add at the right of the video." )
111 #define CANVAS_WIDTH_TEXT N_("Video canvas width")
112 #define CANVAS_WIDTH_LONGTEXT N_( \
113 "This will automatically crod and pad the video to a specified width." )
114 #define CANVAS_HEIGHT_TEXT N_("Video canvas height")
115 #define CANVAS_HEIGHT_LONGTEXT N_( \
116 "This will automatically crod and pad the video to a specified height." )
117 #define CANVAS_ASPECT_TEXT N_("Video canvas aspect ratio")
118 #define CANVAS_ASPECT_LONGTEXT N_( \
119 "This sets aspect (like 4:3) of the video canvas and letterbox the video "\
122 #define AENC_TEXT N_("Audio encoder")
123 #define AENC_LONGTEXT N_( \
124 "This is the audio encoder module that will be used (and its associated "\
126 #define ACODEC_TEXT N_("Destination audio codec")
127 #define ACODEC_LONGTEXT N_( \
128 "This is the audio codec that will be used.")
129 #define AB_TEXT N_("Audio bitrate")
130 #define AB_LONGTEXT N_( \
131 "Target bitrate of the transcoded audio stream." )
132 #define ARATE_TEXT N_("Audio sample rate")
133 #define ARATE_LONGTEXT N_( \
134 "Sample rate of the transcoded audio stream (11250, 22500, 44100 or 48000).")
135 #define ACHANS_TEXT N_("Audio channels")
136 #define ACHANS_LONGTEXT N_( \
137 "Number of audio channels in the transcoded streams." )
138 #define AFILTER_TEXT N_("Audio filter")
139 #define AFILTER_LONGTEXT N_( \
140 "Audio filters will be applied to the audio streams (after conversion " \
141 "filters are applied). You must enter a comma-separated list of filters." )
143 #define SENC_TEXT N_("Subtitles encoder")
144 #define SENC_LONGTEXT N_( \
145 "This is the subtitles encoder module that will be used (and its " \
146 "associated options)." )
147 #define SCODEC_TEXT N_("Destination subtitles codec")
148 #define SCODEC_LONGTEXT N_( \
149 "This is the subtitles codec that will be used." )
151 #define SFILTER_TEXT N_("Overlays")
152 #define SFILTER_LONGTEXT N_( \
153 "This allows you to add overlays (also known as \"subpictures\" on the "\
154 "transcoded video stream. The subpictures produced by the filters will "\
155 "be overlayed directly onto the video. You must specify a comma-separated "\
156 "list of subpicture modules" )
158 #define OSD_TEXT N_("OSD menu")
159 #define OSD_LONGTEXT N_(\
160 "Stream the On Screen Display menu (using the osdmenu subpicture module)." )
162 #define THREADS_TEXT N_("Number of threads")
163 #define THREADS_LONGTEXT N_( \
164 "Number of threads used for the transcoding." )
165 #define HP_TEXT N_("High priority")
166 #define HP_LONGTEXT N_( \
167 "Runs the optional encoder thread at the OUTPUT priority instead of " \
170 #define ASYNC_TEXT N_("Synchronise on audio track")
171 #define ASYNC_LONGTEXT N_( \
172 "This option will drop/duplicate video frames to synchronise the video " \
173 "track on the audio track." )
175 #define HURRYUP_TEXT N_( "Hurry up" )
176 #define HURRYUP_LONGTEXT N_( "The transcoder will drop frames if your CPU " \
177 "can't keep up with the encoding rate." )
179 static char *ppsz_deinterlace_type[] =
181 "deinterlace", "ffmpeg-deinterlace"
184 static int Open ( vlc_object_t * );
185 static void Close( vlc_object_t * );
187 #define SOUT_CFG_PREFIX "sout-transcode-"
190 set_shortname( _("Transcode"));
191 set_description( _("Transcode stream output") );
192 set_capability( "sout stream", 50 );
193 add_shortcut( "transcode" );
194 set_callbacks( Open, Close );
195 set_category( CAT_SOUT );
196 set_subcategory( SUBCAT_SOUT_STREAM );
197 set_section( N_("Video"), NULL );
198 add_string( SOUT_CFG_PREFIX "venc", NULL, NULL, VENC_TEXT,
199 VENC_LONGTEXT, VLC_FALSE );
200 add_string( SOUT_CFG_PREFIX "vcodec", NULL, NULL, VCODEC_TEXT,
201 VCODEC_LONGTEXT, VLC_FALSE );
202 add_integer( SOUT_CFG_PREFIX "vb", 800 * 1000, NULL, VB_TEXT,
203 VB_LONGTEXT, VLC_FALSE );
204 add_float( SOUT_CFG_PREFIX "scale", 1, NULL, SCALE_TEXT,
205 SCALE_LONGTEXT, VLC_FALSE );
206 add_float( SOUT_CFG_PREFIX "fps", 0, NULL, FPS_TEXT,
207 FPS_LONGTEXT, VLC_FALSE );
208 add_bool( SOUT_CFG_PREFIX "hurry-up", VLC_TRUE, NULL, HURRYUP_TEXT,
209 HURRYUP_LONGTEXT, VLC_FALSE );
210 add_bool( SOUT_CFG_PREFIX "deinterlace", 0, NULL, DEINTERLACE_TEXT,
211 DEINTERLACE_LONGTEXT, VLC_FALSE );
212 add_string( SOUT_CFG_PREFIX "deinterlace-module", "deinterlace", NULL,
213 DEINTERLACE_MODULE_TEXT, DEINTERLACE_MODULE_LONGTEXT,
215 change_string_list( ppsz_deinterlace_type, 0, 0 );
216 add_integer( SOUT_CFG_PREFIX "width", 0, NULL, WIDTH_TEXT,
217 WIDTH_LONGTEXT, VLC_TRUE );
218 add_integer( SOUT_CFG_PREFIX "height", 0, NULL, HEIGHT_TEXT,
219 HEIGHT_LONGTEXT, VLC_TRUE );
220 add_integer( SOUT_CFG_PREFIX "maxwidth", 0, NULL, MAXWIDTH_TEXT,
221 MAXWIDTH_LONGTEXT, VLC_TRUE );
222 add_integer( SOUT_CFG_PREFIX "maxheight", 0, NULL, MAXHEIGHT_TEXT,
223 MAXHEIGHT_LONGTEXT, VLC_TRUE );
224 add_module_list( SOUT_CFG_PREFIX "vfilter", "video filter2",
226 VFILTER_TEXT, VFILTER_LONGTEXT, VLC_FALSE );
228 add_integer( SOUT_CFG_PREFIX "croptop", 0, NULL, CROPTOP_TEXT,
229 CROPTOP_LONGTEXT, VLC_TRUE );
230 add_integer( SOUT_CFG_PREFIX "cropleft", 0, NULL, CROPLEFT_TEXT,
231 CROPLEFT_LONGTEXT, VLC_TRUE );
232 add_integer( SOUT_CFG_PREFIX "cropbottom", 0, NULL, CROPBOTTOM_TEXT,
233 CROPBOTTOM_LONGTEXT, VLC_TRUE );
234 add_integer( SOUT_CFG_PREFIX "cropright", 0, NULL, CROPRIGHT_TEXT,
235 CROPRIGHT_LONGTEXT, VLC_TRUE );
237 add_integer( SOUT_CFG_PREFIX "paddtop", 0, NULL, PADDTOP_TEXT,
238 PADDTOP_LONGTEXT, VLC_TRUE );
239 add_integer( SOUT_CFG_PREFIX "paddleft", 0, NULL, PADDLEFT_TEXT,
240 PADDLEFT_LONGTEXT, VLC_TRUE );
241 add_integer( SOUT_CFG_PREFIX "paddbottom", 0, NULL, PADDBOTTOM_TEXT,
242 PADDBOTTOM_LONGTEXT, VLC_TRUE );
243 add_integer( SOUT_CFG_PREFIX "paddright", 0, NULL, PADDRIGHT_TEXT,
244 PADDRIGHT_LONGTEXT, VLC_TRUE );
246 add_integer( SOUT_CFG_PREFIX "canvas-width", 0, NULL, CANVAS_WIDTH_TEXT,
247 CANVAS_WIDTH_LONGTEXT, VLC_TRUE );
248 add_integer( SOUT_CFG_PREFIX "canvas-height", 0, NULL, CANVAS_HEIGHT_TEXT,
249 CANVAS_HEIGHT_LONGTEXT, VLC_TRUE );
250 add_string( SOUT_CFG_PREFIX "canvas-aspect", NULL, NULL, CANVAS_ASPECT_TEXT,
251 CANVAS_ASPECT_LONGTEXT, VLC_FALSE );
253 set_section( N_("Audio"), NULL );
254 add_string( SOUT_CFG_PREFIX "aenc", NULL, NULL, AENC_TEXT,
255 AENC_LONGTEXT, VLC_FALSE );
256 add_string( SOUT_CFG_PREFIX "acodec", NULL, NULL, ACODEC_TEXT,
257 ACODEC_LONGTEXT, VLC_FALSE );
258 add_integer( SOUT_CFG_PREFIX "ab", 64000, NULL, AB_TEXT,
259 AB_LONGTEXT, VLC_FALSE );
260 add_integer( SOUT_CFG_PREFIX "channels", 0, NULL, ACHANS_TEXT,
261 ACHANS_LONGTEXT, VLC_FALSE );
262 add_integer( SOUT_CFG_PREFIX "samplerate", 0, NULL, ARATE_TEXT,
263 ARATE_LONGTEXT, VLC_TRUE );
264 add_bool( SOUT_CFG_PREFIX "audio-sync", 0, NULL, ASYNC_TEXT,
265 ASYNC_LONGTEXT, VLC_FALSE );
266 add_module_list_cat( SOUT_CFG_PREFIX "afilter", SUBCAT_AUDIO_MISC,
268 AFILTER_TEXT, AFILTER_LONGTEXT, VLC_FALSE );
270 set_section( N_("Overlays/Subtitles"), NULL );
271 add_string( SOUT_CFG_PREFIX "senc", NULL, NULL, SENC_TEXT,
272 SENC_LONGTEXT, VLC_FALSE );
273 add_string( SOUT_CFG_PREFIX "scodec", NULL, NULL, SCODEC_TEXT,
274 SCODEC_LONGTEXT, VLC_FALSE );
275 add_bool( SOUT_CFG_PREFIX "soverlay", 0, NULL, SCODEC_TEXT,
276 SCODEC_LONGTEXT, VLC_FALSE );
277 add_module_list_cat( SOUT_CFG_PREFIX "sfilter", SUBCAT_VIDEO_SUBPIC,
279 SFILTER_TEXT, SFILTER_LONGTEXT, VLC_FALSE );
281 set_section( N_("On Screen Display"), NULL );
282 add_bool( SOUT_CFG_PREFIX "osd", 0, NULL, OSD_TEXT,
283 OSD_LONGTEXT, VLC_FALSE );
285 set_section( N_("Miscellaneous"), NULL );
286 add_integer( SOUT_CFG_PREFIX "threads", 0, NULL, THREADS_TEXT,
287 THREADS_LONGTEXT, VLC_TRUE );
288 add_bool( SOUT_CFG_PREFIX "high-priority", 0, NULL, HP_TEXT, HP_LONGTEXT,
293 static const char *ppsz_sout_options[] = {
294 "venc", "vcodec", "vb", "croptop", "cropbottom", "cropleft", "cropright",
295 "paddtop", "paddbottom", "paddleft", "paddright",
296 "canvas-width", "canvas-height", "canvas-aspect",
297 "scale", "fps", "width", "height", "vfilter", "deinterlace",
298 "deinterlace-module", "threads", "hurry-up", "aenc", "acodec", "ab",
299 "afilter", "samplerate", "channels", "senc", "scodec", "soverlay",
300 "sfilter", "osd", "audio-sync", "high-priority", "maxwidth", "maxheight",
304 /*****************************************************************************
305 * Exported prototypes
306 *****************************************************************************/
307 static sout_stream_id_t *Add ( sout_stream_t *, es_format_t * );
308 static int Del ( sout_stream_t *, sout_stream_id_t * );
309 static int Send( sout_stream_t *, sout_stream_id_t *, block_t* );
311 static int transcode_audio_new ( sout_stream_t *, sout_stream_id_t * );
312 static void transcode_audio_close ( sout_stream_t *, sout_stream_id_t * );
313 static int transcode_audio_process( sout_stream_t *, sout_stream_id_t *,
314 block_t *, block_t ** );
316 static aout_buffer_t *audio_new_buffer( decoder_t *, int );
317 static void audio_del_buffer( decoder_t *, aout_buffer_t * );
319 static int transcode_video_new ( sout_stream_t *, sout_stream_id_t * );
320 static void transcode_video_close ( sout_stream_t *, sout_stream_id_t * );
321 static int transcode_video_encoder_open( sout_stream_t *, sout_stream_id_t *);
322 static int transcode_video_process( sout_stream_t *, sout_stream_id_t *,
323 block_t *, block_t ** );
325 static void video_del_buffer( vlc_object_t *, picture_t * );
326 static picture_t *video_new_buffer_decoder( decoder_t * );
327 static void video_del_buffer_decoder( decoder_t *, picture_t * );
328 static void video_link_picture_decoder( decoder_t *, picture_t * );
329 static void video_unlink_picture_decoder( decoder_t *, picture_t * );
330 static picture_t *video_new_buffer_filter( filter_t * );
331 static void video_del_buffer_filter( filter_t *, picture_t * );
333 static int transcode_spu_new ( sout_stream_t *, sout_stream_id_t * );
334 static void transcode_spu_close ( sout_stream_t *, sout_stream_id_t * );
335 static int transcode_spu_process( sout_stream_t *, sout_stream_id_t *,
336 block_t *, block_t ** );
338 static int transcode_osd_new ( sout_stream_t *, sout_stream_id_t * );
339 static void transcode_osd_close ( sout_stream_t *, sout_stream_id_t * );
340 static int transcode_osd_process( sout_stream_t *, sout_stream_id_t *,
341 block_t *, block_t ** );
343 static int EncoderThread( struct sout_stream_sys_t * p_sys );
345 static int pi_channels_maps[6] =
348 AOUT_CHAN_CENTER, AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
349 AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
350 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
351 | AOUT_CHAN_REARRIGHT,
352 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
353 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
356 #define PICTURE_RING_SIZE 64
357 #define SUBPICTURE_RING_SIZE 20
358 #define TRANSCODE_FILTERS 10
360 struct sout_stream_sys_t
364 sout_stream_t *p_out;
365 sout_stream_id_t *id_video;
367 vlc_mutex_t lock_out;
369 picture_t * pp_pics[PICTURE_RING_SIZE];
370 int i_first_pic, i_last_pic;
373 vlc_fourcc_t i_acodec; /* codec audio (0 if not transcode) */
375 config_chain_t *p_audio_cfg;
379 char *psz_afilters[TRANSCODE_FILTERS];
380 config_chain_t *p_afilters_cfg[TRANSCODE_FILTERS];
384 vlc_fourcc_t i_vcodec; /* codec video (0 if not transcode) */
386 config_chain_t *p_video_cfg;
390 unsigned int i_width, i_maxwidth;
391 unsigned int i_height, i_maxheight;
392 vlc_bool_t b_deinterlace;
393 char *psz_deinterlace;
394 config_chain_t *p_deinterlace_cfg;
396 vlc_bool_t b_high_priority;
397 vlc_bool_t b_hurry_up;
398 char *psz_vfilters[TRANSCODE_FILTERS];
399 config_chain_t *p_vfilters_cfg[TRANSCODE_FILTERS];
416 /* Video, calculated */
428 vlc_fourcc_t i_scodec; /* codec spu (0 if not transcode) */
430 vlc_bool_t b_soverlay;
431 config_chain_t *p_spu_cfg;
435 sout_stream_id_t *id_osd; /* extension for streaming OSD menus */
436 vlc_fourcc_t i_osdcodec; /* codec osd menu (0 if not transcode) */
438 config_chain_t *p_osd_cfg;
439 vlc_bool_t b_es_osd; /* VLC_TRUE when osd es is registered */
440 vlc_bool_t b_sout_osd;
443 vlc_bool_t b_master_sync;
444 mtime_t i_master_drift;
447 struct decoder_owner_sys_t
449 picture_t *pp_pics[PICTURE_RING_SIZE];
450 sout_stream_sys_t *p_sys;
452 struct filter_owner_sys_t
454 picture_t *pp_pics[PICTURE_RING_SIZE];
455 sout_stream_sys_t *p_sys;
458 /*****************************************************************************
460 *****************************************************************************/
461 static int Open( vlc_object_t *p_this )
463 sout_stream_t *p_stream = (sout_stream_t*)p_this;
464 sout_stream_sys_t *p_sys;
467 p_sys = vlc_object_create( p_this, sizeof( sout_stream_sys_t ) );
469 p_sys->p_out = sout_StreamNew( p_stream->p_sout, p_stream->psz_next );
472 msg_Err( p_stream, "cannot create chain" );
473 vlc_object_destroy( p_sys );
477 p_sys->i_master_drift = 0;
479 config_ChainParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
482 /* Audio transcoding parameters */
483 var_Get( p_stream, SOUT_CFG_PREFIX "aenc", &val );
484 p_sys->psz_aenc = NULL;
485 p_sys->p_audio_cfg = NULL;
486 if( val.psz_string && *val.psz_string )
489 psz_next = config_ChainCreate( &p_sys->psz_aenc, &p_sys->p_audio_cfg,
491 if( psz_next ) free( psz_next );
493 if( val.psz_string ) free( val.psz_string );
495 var_Get( p_stream, SOUT_CFG_PREFIX "acodec", &val );
497 if( val.psz_string && *val.psz_string )
500 memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
501 p_sys->i_acodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
503 if( val.psz_string ) free( val.psz_string );
505 var_Get( p_stream, SOUT_CFG_PREFIX "ab", &val );
506 p_sys->i_abitrate = val.i_int;
507 if( p_sys->i_abitrate < 4000 ) p_sys->i_abitrate *= 1000;
509 var_Get( p_stream, SOUT_CFG_PREFIX "samplerate", &val );
510 p_sys->i_sample_rate = val.i_int;
512 var_Get( p_stream, SOUT_CFG_PREFIX "channels", &val );
513 p_sys->i_channels = val.i_int;
515 if( p_sys->i_acodec )
517 if( p_sys->i_acodec == VLC_FOURCC('m','p','3',0) &&
518 p_sys->i_channels > 2 )
520 msg_Warn( p_stream, "%d channels invalid for mp3, forcing to 2",
522 p_sys->i_channels = 2;
524 msg_Dbg( p_stream, "codec audio=%4.4s %dHz %d channels %dKb/s",
525 (char *)&p_sys->i_acodec, p_sys->i_sample_rate,
526 p_sys->i_channels, p_sys->i_abitrate / 1000 );
529 var_Get( p_stream, SOUT_CFG_PREFIX "afilter", &val );
530 p_sys->i_afilters = 0;
531 if( val.psz_string && *val.psz_string )
533 char *psz_parser = val.psz_string;
535 while( (psz_parser != NULL) && (*psz_parser != '\0')
536 && (p_sys->i_afilters < TRANSCODE_FILTERS) )
538 psz_parser = config_ChainCreate(
539 &p_sys->psz_afilters[p_sys->i_afilters],
540 &p_sys->p_afilters_cfg[p_sys->i_afilters],
543 if( (psz_parser != NULL) && (*psz_parser != '\0') ) psz_parser++;
546 if( val.psz_string ) free( val.psz_string );
547 if( p_sys->i_afilters < TRANSCODE_FILTERS-1 )
549 p_sys->psz_afilters[p_sys->i_afilters] = NULL;
550 p_sys->p_afilters_cfg[p_sys->i_afilters] = NULL;
553 /* Video transcoding parameters */
554 var_Get( p_stream, SOUT_CFG_PREFIX "venc", &val );
555 p_sys->psz_venc = NULL;
556 p_sys->p_video_cfg = NULL;
557 if( val.psz_string && *val.psz_string )
560 psz_next = config_ChainCreate( &p_sys->psz_venc, &p_sys->p_video_cfg,
562 if( psz_next ) free( psz_next );
564 if( val.psz_string ) free( val.psz_string );
566 var_Get( p_stream, SOUT_CFG_PREFIX "vcodec", &val );
568 if( val.psz_string && *val.psz_string )
571 memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
572 p_sys->i_vcodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
574 if( val.psz_string ) free( val.psz_string );
576 var_Get( p_stream, SOUT_CFG_PREFIX "vb", &val );
577 p_sys->i_vbitrate = val.i_int;
578 if( p_sys->i_vbitrate < 16000 ) p_sys->i_vbitrate *= 1000;
580 var_Get( p_stream, SOUT_CFG_PREFIX "scale", &val );
581 p_sys->f_scale = val.f_float;
583 var_Get( p_stream, SOUT_CFG_PREFIX "fps", &val );
584 p_sys->f_fps = val.f_float;
586 var_Get( p_stream, SOUT_CFG_PREFIX "hurry-up", &val );
587 p_sys->b_hurry_up = val.b_bool;
589 var_Get( p_stream, SOUT_CFG_PREFIX "width", &val );
590 p_sys->i_width = val.i_int;
592 var_Get( p_stream, SOUT_CFG_PREFIX "height", &val );
593 p_sys->i_height = val.i_int;
595 var_Get( p_stream, SOUT_CFG_PREFIX "maxwidth", &val );
596 p_sys->i_maxwidth = val.i_int;
598 var_Get( p_stream, SOUT_CFG_PREFIX "maxheight", &val );
599 p_sys->i_maxheight = val.i_int;
601 var_Get( p_stream, SOUT_CFG_PREFIX "vfilter", &val );
602 p_sys->i_vfilters = 0;
603 if( val.psz_string && *val.psz_string )
605 char *psz_parser = val.psz_string;
607 while( (psz_parser != NULL) && (*psz_parser != '\0')
608 && (p_sys->i_vfilters < TRANSCODE_FILTERS) )
610 psz_parser = config_ChainCreate(
611 &p_sys->psz_vfilters[p_sys->i_vfilters],
612 &p_sys->p_vfilters_cfg[p_sys->i_vfilters],
615 if( psz_parser != NULL && *psz_parser != '\0' ) psz_parser++;
618 if( val.psz_string ) free( val.psz_string );
619 if( p_sys->i_vfilters < TRANSCODE_FILTERS-1 )
621 p_sys->psz_vfilters[p_sys->i_vfilters] = NULL;
622 p_sys->p_vfilters_cfg[p_sys->i_vfilters] = NULL;
625 var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace", &val );
626 p_sys->b_deinterlace = val.b_bool;
628 var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace-module", &val );
629 p_sys->psz_deinterlace = NULL;
630 p_sys->p_deinterlace_cfg = NULL;
631 if( val.psz_string && *val.psz_string )
634 psz_next = config_ChainCreate( &p_sys->psz_deinterlace,
635 &p_sys->p_deinterlace_cfg,
637 if( psz_next ) free( psz_next );
639 if( val.psz_string ) free( val.psz_string );
641 var_Get( p_stream, SOUT_CFG_PREFIX "croptop", &val );
642 p_sys->i_crop_top = val.i_int;
643 var_Get( p_stream, SOUT_CFG_PREFIX "cropbottom", &val );
644 p_sys->i_crop_bottom = val.i_int;
645 var_Get( p_stream, SOUT_CFG_PREFIX "cropleft", &val );
646 p_sys->i_crop_left = val.i_int;
647 var_Get( p_stream, SOUT_CFG_PREFIX "cropright", &val );
648 p_sys->i_crop_right = val.i_int;
650 var_Get( p_stream, SOUT_CFG_PREFIX "paddtop", &val );
651 p_sys->i_padd_top = val.i_int;
652 var_Get( p_stream, SOUT_CFG_PREFIX "paddbottom", &val );
653 p_sys->i_padd_bottom = val.i_int;
654 var_Get( p_stream, SOUT_CFG_PREFIX "paddleft", &val );
655 p_sys->i_padd_left = val.i_int;
656 var_Get( p_stream, SOUT_CFG_PREFIX "paddright", &val );
657 p_sys->i_padd_right = val.i_int;
659 var_Get( p_stream, SOUT_CFG_PREFIX "canvas-width", &val );
660 p_sys->i_canvas_width = val.i_int;
661 var_Get( p_stream, SOUT_CFG_PREFIX "canvas-height", &val );
662 p_sys->i_canvas_height = val.i_int;
664 var_Get( p_stream, SOUT_CFG_PREFIX "canvas-aspect", &val );
665 p_sys->i_canvas_aspect = 0;
666 if( val.psz_string && *val.psz_string )
668 char *psz_parser = strchr( val.psz_string, ':' );
671 *psz_parser++ = '\0';
672 p_sys->i_canvas_aspect = atoi( val.psz_string ) *
673 VOUT_ASPECT_FACTOR / atoi( psz_parser );
675 else msg_Warn( p_stream, "bad aspect ratio %s", val.psz_string );
678 if( val.psz_string ) free( val.psz_string );
680 var_Get( p_stream, SOUT_CFG_PREFIX "threads", &val );
681 p_sys->i_threads = val.i_int;
682 var_Get( p_stream, SOUT_CFG_PREFIX "high-priority", &val );
683 p_sys->b_high_priority = val.b_bool;
685 if( p_sys->i_vcodec )
687 msg_Dbg( p_stream, "codec video=%4.4s %dx%d scaling: %f %dkb/s",
688 (char *)&p_sys->i_vcodec, p_sys->i_width, p_sys->i_height,
689 p_sys->f_scale, p_sys->i_vbitrate / 1000 );
692 /* Subpictures transcoding parameters */
694 p_sys->psz_senc = NULL;
695 p_sys->p_spu_cfg = NULL;
698 var_Get( p_stream, SOUT_CFG_PREFIX "senc", &val );
699 if( val.psz_string && *val.psz_string )
702 psz_next = config_ChainCreate( &p_sys->psz_senc, &p_sys->p_spu_cfg,
704 if( psz_next ) free( psz_next );
706 if( val.psz_string ) free( val.psz_string );
708 var_Get( p_stream, SOUT_CFG_PREFIX "scodec", &val );
709 if( val.psz_string && *val.psz_string )
712 memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
713 p_sys->i_scodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
715 if( val.psz_string ) free( val.psz_string );
717 if( p_sys->i_scodec )
719 msg_Dbg( p_stream, "codec spu=%4.4s", (char *)&p_sys->i_scodec );
722 var_Get( p_stream, SOUT_CFG_PREFIX "soverlay", &val );
723 p_sys->b_soverlay = val.b_bool;
725 var_Get( p_stream, SOUT_CFG_PREFIX "sfilter", &val );
726 if( val.psz_string && *val.psz_string )
728 p_sys->p_spu = spu_Create( p_stream );
729 var_Create( p_sys->p_spu, "sub-filter", VLC_VAR_STRING );
730 var_Set( p_sys->p_spu, "sub-filter", val );
731 spu_Init( p_sys->p_spu );
733 if( val.psz_string ) free( val.psz_string );
735 /* OSD menu transcoding parameters */
736 p_sys->psz_osdenc = NULL;
737 p_sys->p_osd_cfg = NULL;
738 p_sys->i_osdcodec = 0;
739 p_sys->b_es_osd = VLC_FALSE;
741 var_Get( p_stream, SOUT_CFG_PREFIX "osd", &val );
742 p_sys->b_sout_osd = val.b_bool;
743 if( p_sys->b_sout_osd )
748 psz_next = config_ChainCreate( &p_sys->psz_osdenc,
749 &p_sys->p_osd_cfg, strdup( "dvbsub") );
750 if( psz_next ) free( psz_next );
752 p_sys->i_osdcodec = VLC_FOURCC('Y','U','V','P' );
754 msg_Dbg( p_stream, "codec osd=%4.4s", (char *)&p_sys->i_osdcodec );
758 osd_val.psz_string = strdup("osdmenu");
759 p_sys->p_spu = spu_Create( p_stream );
760 var_Create( p_sys->p_spu, "sub-filter", VLC_VAR_STRING );
761 var_Set( p_sys->p_spu, "sub-filter", osd_val );
762 spu_Init( p_sys->p_spu );
763 if( osd_val.psz_string ) free( osd_val.psz_string );
767 osd_val.psz_string = strdup("osdmenu");
768 var_Set( p_sys->p_spu, "sub-filter", osd_val );
769 if( osd_val.psz_string ) free( osd_val.psz_string );
774 var_Get( p_stream, SOUT_CFG_PREFIX "audio-sync", &val );
775 p_sys->b_master_sync = val.b_bool;
776 if( p_sys->f_fps > 0 ) p_sys->b_master_sync = VLC_TRUE;
778 p_stream->pf_add = Add;
779 p_stream->pf_del = Del;
780 p_stream->pf_send = Send;
781 p_stream->p_sys = p_sys;
786 /*****************************************************************************
788 *****************************************************************************/
789 static void Close( vlc_object_t * p_this )
791 sout_stream_t *p_stream = (sout_stream_t*)p_this;
792 sout_stream_sys_t *p_sys = p_stream->p_sys;
794 sout_StreamDelete( p_sys->p_out );
796 while( p_sys->p_audio_cfg != NULL )
798 config_chain_t *p_next = p_sys->p_audio_cfg->p_next;
800 if( p_sys->p_audio_cfg->psz_name )
801 free( p_sys->p_audio_cfg->psz_name );
802 if( p_sys->p_audio_cfg->psz_value )
803 free( p_sys->p_audio_cfg->psz_value );
804 free( p_sys->p_audio_cfg );
806 p_sys->p_audio_cfg = p_next;
808 if( p_sys->psz_aenc ) free( p_sys->psz_aenc );
810 while( p_sys->p_video_cfg != NULL )
812 config_chain_t *p_next = p_sys->p_video_cfg->p_next;
814 if( p_sys->p_video_cfg->psz_name )
815 free( p_sys->p_video_cfg->psz_name );
816 if( p_sys->p_video_cfg->psz_value )
817 free( p_sys->p_video_cfg->psz_value );
818 free( p_sys->p_video_cfg );
820 p_sys->p_video_cfg = p_next;
822 if( p_sys->psz_venc ) free( p_sys->psz_venc );
824 while( p_sys->p_deinterlace_cfg != NULL )
826 config_chain_t *p_next = p_sys->p_deinterlace_cfg->p_next;
828 if( p_sys->p_deinterlace_cfg->psz_name )
829 free( p_sys->p_deinterlace_cfg->psz_name );
830 if( p_sys->p_deinterlace_cfg->psz_value )
831 free( p_sys->p_deinterlace_cfg->psz_value );
832 free( p_sys->p_deinterlace_cfg );
834 p_sys->p_deinterlace_cfg = p_next;
836 if( p_sys->psz_deinterlace ) free( p_sys->psz_deinterlace );
838 while( p_sys->p_spu_cfg != NULL )
840 config_chain_t *p_next = p_sys->p_spu_cfg->p_next;
842 if( p_sys->p_spu_cfg->psz_name )
843 free( p_sys->p_spu_cfg->psz_name );
844 if( p_sys->p_spu_cfg->psz_value )
845 free( p_sys->p_spu_cfg->psz_value );
846 free( p_sys->p_spu_cfg );
848 p_sys->p_spu_cfg = p_next;
850 if( p_sys->psz_senc ) free( p_sys->psz_senc );
852 if( p_sys->p_spu ) spu_Destroy( p_sys->p_spu );
854 while( p_sys->p_osd_cfg != NULL )
856 config_chain_t *p_next = p_sys->p_osd_cfg->p_next;
858 if( p_sys->p_osd_cfg->psz_name )
859 free( p_sys->p_osd_cfg->psz_name );
860 if( p_sys->p_osd_cfg->psz_value )
861 free( p_sys->p_osd_cfg->psz_value );
862 free( p_sys->p_osd_cfg );
864 p_sys->p_osd_cfg = p_next;
866 if( p_sys->psz_osdenc ) free( p_sys->psz_osdenc );
868 vlc_object_destroy( p_sys );
871 struct sout_stream_id_t
873 vlc_fourcc_t b_transcode;
875 /* id of the out stream */
879 decoder_t *p_decoder;
882 filter_t *pp_filter[TRANSCODE_FILTERS];
884 /* User specified filters */
885 filter_t *pp_ufilter[TRANSCODE_FILTERS];
889 encoder_t *p_encoder;
892 date_t interpolated_pts;
895 static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
897 sout_stream_sys_t *p_sys = p_stream->p_sys;
898 sout_stream_id_t *id;
900 id = malloc( sizeof( sout_stream_id_t ) );
901 memset( id, 0, sizeof(sout_stream_id_t) );
904 id->p_decoder = NULL;
905 id->p_encoder = NULL;
907 /* Create decoder object */
908 id->p_decoder = vlc_object_create( p_stream, VLC_OBJECT_DECODER );
911 msg_Err( p_stream, "out of memory" );
914 vlc_object_attach( id->p_decoder, p_stream );
915 id->p_decoder->p_module = NULL;
916 id->p_decoder->fmt_in = *p_fmt;
917 id->p_decoder->b_pace_control = VLC_TRUE;
919 /* Create encoder object */
920 id->p_encoder = vlc_object_create( p_stream, VLC_OBJECT_ENCODER );
923 msg_Err( p_stream, "out of memory" );
926 vlc_object_attach( id->p_encoder, p_stream );
927 id->p_encoder->p_module = NULL;
929 /* Create destination format */
930 es_format_Init( &id->p_encoder->fmt_out, p_fmt->i_cat, 0 );
931 id->p_encoder->fmt_out.i_id = p_fmt->i_id;
932 id->p_encoder->fmt_out.i_group = p_fmt->i_group;
933 if( p_fmt->psz_language )
934 id->p_encoder->fmt_out.psz_language = strdup( p_fmt->psz_language );
936 if( p_fmt->i_cat == AUDIO_ES && (p_sys->i_acodec || p_sys->psz_aenc) )
939 "creating audio transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
940 (char*)&p_fmt->i_codec, (char*)&p_sys->i_acodec );
942 /* Complete destination format */
943 id->p_encoder->fmt_out.i_codec = p_sys->i_acodec;
944 id->p_encoder->fmt_out.audio.i_rate = p_sys->i_sample_rate > 0 ?
945 p_sys->i_sample_rate : (int)p_fmt->audio.i_rate;
946 id->p_encoder->fmt_out.i_bitrate = p_sys->i_abitrate;
947 id->p_encoder->fmt_out.audio.i_bitspersample =
948 p_fmt->audio.i_bitspersample;
949 id->p_encoder->fmt_out.audio.i_channels = p_sys->i_channels > 0 ?
950 p_sys->i_channels : p_fmt->audio.i_channels;
951 /* Sanity check for audio channels */
952 id->p_encoder->fmt_out.audio.i_channels =
953 __MIN( id->p_encoder->fmt_out.audio.i_channels,
954 id->p_decoder->fmt_in.audio.i_channels );
955 id->p_encoder->fmt_out.audio.i_original_channels =
956 id->p_decoder->fmt_in.audio.i_physical_channels;
957 if( id->p_decoder->fmt_in.audio.i_channels ==
958 id->p_encoder->fmt_out.audio.i_channels )
960 id->p_encoder->fmt_out.audio.i_physical_channels =
961 id->p_decoder->fmt_in.audio.i_physical_channels;
965 id->p_encoder->fmt_out.audio.i_physical_channels =
966 pi_channels_maps[id->p_encoder->fmt_out.audio.i_channels];
969 /* Build decoder -> filter -> encoder chain */
970 if( transcode_audio_new( p_stream, id ) )
972 msg_Err( p_stream, "cannot create audio chain" );
976 /* Open output stream */
977 id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
978 id->b_transcode = VLC_TRUE;
982 transcode_audio_close( p_stream, id );
986 date_Init( &id->interpolated_pts, p_fmt->audio.i_rate, 1 );
988 else if( p_fmt->i_cat == VIDEO_ES &&
989 (p_sys->i_vcodec != 0 || p_sys->psz_venc) )
992 "creating video transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
993 (char*)&p_fmt->i_codec, (char*)&p_sys->i_vcodec );
995 /* Complete destination format */
996 id->p_encoder->fmt_out.i_codec = p_sys->i_vcodec;
997 id->p_encoder->fmt_out.video.i_width = p_sys->i_width & ~1;
998 id->p_encoder->fmt_out.video.i_height = p_sys->i_height & ~1;
999 id->p_encoder->fmt_out.i_bitrate = p_sys->i_vbitrate;
1001 /* Build decoder -> filter -> encoder chain */
1002 if( transcode_video_new( p_stream, id ) )
1004 msg_Err( p_stream, "cannot create video chain" );
1008 /* Stream will be added later on because we don't know
1009 * all the characteristics of the decoded stream yet */
1010 id->b_transcode = VLC_TRUE;
1012 if( p_sys->f_fps > 0 )
1014 id->p_encoder->fmt_out.video.i_frame_rate =
1015 (p_sys->f_fps * 1001) + 0.5;
1016 id->p_encoder->fmt_out.video.i_frame_rate_base = 1001;
1019 else if( p_fmt->i_cat == SPU_ES && (p_sys->i_scodec || p_sys->psz_senc) )
1021 msg_Dbg( p_stream, "creating subtitles transcoding from fcc=`%4.4s' "
1022 "to fcc=`%4.4s'", (char*)&p_fmt->i_codec,
1023 (char*)&p_sys->i_scodec );
1025 /* Complete destination format */
1026 id->p_encoder->fmt_out.i_codec = p_sys->i_scodec;
1028 /* build decoder -> filter -> encoder */
1029 if( transcode_spu_new( p_stream, id ) )
1031 msg_Err( p_stream, "cannot create subtitles chain" );
1035 /* open output stream */
1036 id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
1037 id->b_transcode = VLC_TRUE;
1041 transcode_spu_close( p_stream, id );
1045 else if( p_fmt->i_cat == SPU_ES && p_sys->b_soverlay )
1047 msg_Dbg( p_stream, "subtitles (fcc=`%4.4s') overlaying",
1048 (char*)&p_fmt->i_codec );
1050 id->b_transcode = VLC_TRUE;
1052 /* Build decoder -> filter -> overlaying chain */
1053 if( transcode_spu_new( p_stream, id ) )
1055 msg_Err( p_stream, "cannot create subtitles chain" );
1061 msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
1062 (char*)&p_fmt->i_codec );
1063 id->id = p_sys->p_out->pf_add( p_sys->p_out, p_fmt );
1064 id->b_transcode = VLC_FALSE;
1066 if( !id->id ) goto error;
1069 if( p_sys->b_sout_osd )
1071 /* Create a fake OSD menu elementary stream */
1072 if( !p_sys->b_es_osd && (p_sys->i_osdcodec != 0 || p_sys->psz_osdenc) )
1074 if( transcode_osd_new( p_stream, p_sys->id_osd ) )
1076 msg_Err( p_stream, "cannot create osd chain" );
1079 p_sys->b_es_osd = VLC_TRUE;
1087 vlc_object_detach( id->p_decoder );
1088 vlc_object_destroy( id->p_decoder );
1089 id->p_decoder = NULL;
1094 vlc_object_detach( id->p_encoder );
1095 es_format_Clean( &id->p_encoder->fmt_out );
1096 vlc_object_destroy( id->p_encoder );
1097 id->p_encoder = NULL;
1104 static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
1106 sout_stream_sys_t *p_sys = p_stream->p_sys;
1108 if( p_sys->b_es_osd )
1109 transcode_osd_close( p_stream, p_sys->id_osd );
1111 if( id->b_transcode )
1113 switch( id->p_decoder->fmt_in.i_cat )
1116 transcode_audio_close( p_stream, id );
1119 transcode_video_close( p_stream, id );
1122 transcode_spu_close( p_stream, id );
1127 if( id->id ) p_sys->p_out->pf_del( p_sys->p_out, id->id );
1131 vlc_object_detach( id->p_decoder );
1132 vlc_object_destroy( id->p_decoder );
1133 id->p_decoder = NULL;
1138 vlc_object_detach( id->p_encoder );
1139 es_format_Clean( &id->p_encoder->fmt_out );
1140 vlc_object_destroy( id->p_encoder );
1141 id->p_encoder = NULL;
1148 static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
1151 sout_stream_sys_t *p_sys = p_stream->p_sys;
1152 block_t *p_out = NULL;
1154 if( !id->b_transcode && id->id )
1156 /* Transcode OSD menu pictures. */
1157 if( p_sys->b_es_osd )
1159 transcode_osd_process( p_stream, id, p_buffer, &p_out );
1161 return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_buffer );
1163 else if( !id->b_transcode )
1165 block_Release( p_buffer );
1166 return VLC_EGENERIC;
1169 switch( id->p_decoder->fmt_in.i_cat )
1172 transcode_audio_process( p_stream, id, p_buffer, &p_out );
1176 if( transcode_video_process( p_stream, id, p_buffer, &p_out )
1179 return VLC_EGENERIC;
1184 if( transcode_spu_process( p_stream, id, p_buffer, &p_out ) !=
1187 return VLC_EGENERIC;
1193 block_Release( p_buffer );
1197 if( p_out ) return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_out );
1201 /****************************************************************************
1202 * decoder reencoder part
1203 ****************************************************************************/
1204 int audio_BitsPerSample( vlc_fourcc_t i_format )
1208 case VLC_FOURCC('u','8',' ',' '):
1209 case VLC_FOURCC('s','8',' ',' '):
1212 case VLC_FOURCC('u','1','6','l'):
1213 case VLC_FOURCC('s','1','6','l'):
1214 case VLC_FOURCC('u','1','6','b'):
1215 case VLC_FOURCC('s','1','6','b'):
1218 case VLC_FOURCC('u','2','4','l'):
1219 case VLC_FOURCC('s','2','4','l'):
1220 case VLC_FOURCC('u','2','4','b'):
1221 case VLC_FOURCC('s','2','4','b'):
1224 case VLC_FOURCC('u','3','2','l'):
1225 case VLC_FOURCC('s','3','2','l'):
1226 case VLC_FOURCC('u','3','2','b'):
1227 case VLC_FOURCC('s','3','2','b'):
1228 case VLC_FOURCC('f','l','3','2'):
1229 case VLC_FOURCC('f','i','3','2'):
1232 case VLC_FOURCC('f','l','6','4'):
1239 static filter_t *transcode_audio_filter_new( sout_stream_t *p_stream,
1240 sout_stream_id_t *id,
1241 es_format_t *p_fmt_in,
1242 es_format_t *p_fmt_out,
1245 sout_stream_sys_t *p_sys = p_stream->p_sys;
1246 filter_t *p_filter = vlc_object_create( p_stream, VLC_OBJECT_FILTER );
1248 vlc_object_attach( p_filter, p_stream );
1249 p_filter->pf_audio_buffer_new = (block_t* (*) (filter_t*, int))__block_New;
1251 p_filter->fmt_in = *p_fmt_in;
1252 p_filter->fmt_out = *p_fmt_out;
1254 p_filter->p_cfg = p_sys->p_afilters_cfg[id->i_ufilter];
1256 p_filter->p_module = module_Need( p_filter, "audio filter2", psz_name, 0 );
1257 if( p_filter->p_module )
1259 p_filter->fmt_out.audio.i_bitspersample =
1260 audio_BitsPerSample( p_filter->fmt_out.i_codec );
1261 *p_fmt_in = p_filter->fmt_out;
1265 vlc_object_detach( p_filter );
1266 vlc_object_destroy( p_filter );
1273 static int transcode_audio_new( sout_stream_t *p_stream,
1274 sout_stream_id_t *id )
1276 sout_stream_sys_t *p_sys = p_stream->p_sys;
1277 es_format_t fmt_last;
1284 /* Initialization of decoder structures */
1285 id->p_decoder->fmt_out = id->p_decoder->fmt_in;
1286 id->p_decoder->fmt_out.i_extra = 0;
1287 id->p_decoder->fmt_out.p_extra = 0;
1288 id->p_decoder->pf_decode_audio = 0;
1289 id->p_decoder->pf_aout_buffer_new = audio_new_buffer;
1290 id->p_decoder->pf_aout_buffer_del = audio_del_buffer;
1291 /* id->p_decoder->p_cfg = p_sys->p_audio_cfg; */
1293 id->p_decoder->p_module =
1294 module_Need( id->p_decoder, "decoder", "$codec", 0 );
1295 if( !id->p_decoder->p_module )
1297 msg_Err( p_stream, "cannot find decoder" );
1298 return VLC_EGENERIC;
1300 id->p_decoder->fmt_out.audio.i_bitspersample =
1301 audio_BitsPerSample( id->p_decoder->fmt_out.i_codec );
1302 fmt_last = id->p_decoder->fmt_out;
1303 /* FIX decoders so we don't have to do this */
1304 fmt_last.audio.i_rate = id->p_decoder->fmt_in.audio.i_rate;
1310 /* Initialization of encoder format structures */
1311 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1312 id->p_decoder->fmt_out.i_codec );
1313 id->p_encoder->fmt_in.audio.i_format = id->p_decoder->fmt_out.i_codec;
1315 /* Initialization of encoder format structures */
1316 es_format_Init( &id->p_encoder->fmt_in, AUDIO_ES, VLC_FOURCC('f','l','3','2') );
1317 id->p_encoder->fmt_in.audio.i_format = VLC_FOURCC('f','l','3','2');
1319 id->p_encoder->fmt_in.audio.i_rate = id->p_encoder->fmt_out.audio.i_rate;
1320 id->p_encoder->fmt_in.audio.i_physical_channels =
1321 id->p_encoder->fmt_out.audio.i_physical_channels;
1322 id->p_encoder->fmt_in.audio.i_original_channels =
1323 id->p_encoder->fmt_out.audio.i_original_channels;
1324 id->p_encoder->fmt_in.audio.i_channels =
1325 id->p_encoder->fmt_out.audio.i_channels;
1326 id->p_encoder->fmt_in.audio.i_bitspersample =
1327 audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1329 id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
1330 id->p_encoder->p_module =
1331 module_Need( id->p_encoder, "encoder", p_sys->psz_aenc, VLC_TRUE );
1332 if( !id->p_encoder->p_module )
1334 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_aenc );
1335 module_Unneed( id->p_decoder, id->p_decoder->p_module );
1336 id->p_decoder->p_module = NULL;
1337 return VLC_EGENERIC;
1339 id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
1340 id->p_encoder->fmt_in.audio.i_bitspersample =
1341 audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1343 /* Load conversion filters */
1344 if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels ||
1345 fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate )
1347 /* We'll have to go through fl32 first */
1348 es_format_t fmt_out = id->p_encoder->fmt_in;
1349 fmt_out.i_codec = fmt_out.audio.i_format = VLC_FOURCC('f','l','3','2');
1351 id->pp_filter[id->i_filter] =
1352 transcode_audio_filter_new( p_stream, id, &fmt_last, &fmt_out, NULL );
1354 if( id->pp_filter[id->i_filter] ) id->i_filter++;
1357 for( i = 0; i < TRANSCODE_FILTERS; i++ )
1359 if( (fmt_last.audio.i_channels !=
1360 id->p_encoder->fmt_in.audio.i_channels) ||
1361 (fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate) ||
1362 (fmt_last.i_codec != id->p_encoder->fmt_in.i_codec) )
1364 id->pp_filter[id->i_filter] =
1365 transcode_audio_filter_new( p_stream, id, &fmt_last,
1366 &id->p_encoder->fmt_in, NULL );
1368 if( id->pp_filter[id->i_filter] )
1375 /* Final checks to see if conversions were successful */
1376 if( fmt_last.i_codec != id->p_encoder->fmt_in.i_codec )
1378 msg_Err( p_stream, "no audio filter found (%4.4s->%4.4s)",
1379 (char *)&fmt_last.i_codec,
1380 (char *)&id->p_encoder->fmt_in.i_codec );
1381 transcode_audio_close( p_stream, id );
1382 return VLC_EGENERIC;
1385 /* Load user specified audio filters now */
1386 for( i = 0; (i < p_sys->i_afilters) &&
1387 (id->i_ufilter < TRANSCODE_FILTERS); i++ )
1389 id->pp_ufilter[id->i_ufilter] =
1390 transcode_audio_filter_new( p_stream, id, &fmt_last,
1391 &id->p_encoder->fmt_in,
1392 p_sys->psz_afilters[i] );
1394 if( id->pp_ufilter[id->i_ufilter] )
1400 if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels )
1403 module_Unneed( id->p_encoder, id->p_encoder->p_module );
1404 id->p_encoder->p_module = NULL;
1406 /* This might work, but only if the encoder is restarted */
1407 id->p_encoder->fmt_in.audio.i_channels = fmt_last.audio.i_channels;
1408 id->p_encoder->fmt_out.audio.i_channels = fmt_last.audio.i_channels;
1410 id->p_encoder->fmt_in.audio.i_physical_channels =
1411 id->p_encoder->fmt_in.audio.i_original_channels =
1412 fmt_last.audio.i_physical_channels;
1413 id->p_encoder->fmt_out.audio.i_physical_channels =
1414 id->p_encoder->fmt_out.audio.i_original_channels =
1415 fmt_last.audio.i_physical_channels;
1417 msg_Dbg( p_stream, "number of audio channels for mixing changed, "
1418 "trying to reopen the encoder for mixing %i to %i channels",
1419 fmt_last.audio.i_channels,
1420 id->p_encoder->fmt_in.audio.i_channels );
1422 /* reload encoder */
1423 id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
1424 id->p_encoder->p_module =
1425 module_Need( id->p_encoder, "encoder", p_sys->psz_aenc, VLC_TRUE );
1426 if( !id->p_encoder->p_module )
1428 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_aenc );
1429 transcode_audio_close( p_stream, id );
1430 return VLC_EGENERIC;
1432 id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
1433 id->p_encoder->fmt_in.audio.i_bitspersample =
1434 audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1436 msg_Err( p_stream, "no audio filter found for mixing from"
1437 " %i to %i channels", fmt_last.audio.i_channels,
1438 id->p_encoder->fmt_in.audio.i_channels );
1440 transcode_audio_close( p_stream, id );
1441 return VLC_EGENERIC;
1445 if( fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate )
1447 msg_Err( p_stream, "no audio filter found for resampling from"
1448 " %iHz to %iHz", fmt_last.audio.i_rate,
1449 id->p_encoder->fmt_in.audio.i_rate );
1451 /* FIXME : this might work, but only if the encoder is restarted */
1452 id->p_encoder->fmt_in.audio.i_rate = fmt_last.audio.i_rate;
1453 id->p_encoder->fmt_out.audio.i_rate = fmt_last.audio.i_rate;
1455 transcode_audio_close( p_stream, id );
1456 return VLC_EGENERIC;
1460 /* FIXME: Hack for mp3 transcoding support */
1461 if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC( 'm','p','3',' ' ) )
1462 id->p_encoder->fmt_out.i_codec = VLC_FOURCC( 'm','p','g','a' );
1467 static void transcode_audio_close( sout_stream_t *p_stream,
1468 sout_stream_id_t *id )
1473 if( id->p_decoder->p_module )
1474 module_Unneed( id->p_decoder, id->p_decoder->p_module );
1475 id->p_decoder->p_module = NULL;
1478 if( id->p_encoder->p_module )
1479 module_Unneed( id->p_encoder, id->p_encoder->p_module );
1480 id->p_encoder->p_module = NULL;
1483 for( i = 0; i < id->i_filter; i++ )
1485 vlc_object_detach( id->pp_filter[i] );
1486 if( id->pp_filter[i]->p_module )
1487 module_Unneed( id->pp_filter[i], id->pp_filter[i]->p_module );
1488 vlc_object_destroy( id->pp_filter[i] );
1490 for( i = 0; i < id->i_ufilter; i++ )
1492 vlc_object_detach( id->pp_ufilter[i] );
1493 if( id->pp_ufilter[i]->p_module )
1494 module_Unneed( id->pp_ufilter[i], id->pp_ufilter[i]->p_module );
1495 vlc_object_destroy( id->pp_ufilter[i] );
1499 static int transcode_audio_process( sout_stream_t *p_stream,
1500 sout_stream_id_t *id,
1501 block_t *in, block_t **out )
1503 sout_stream_sys_t *p_sys = p_stream->p_sys;
1504 aout_buffer_t *p_audio_buf;
1505 block_t *p_block, *p_audio_block;
1508 input_thread_t *p_input = NULL;
1510 if( p_stream->p_parent->p_parent && p_stream->p_parent->p_parent->
1511 i_object_type == VLC_OBJECT_INPUT )
1512 p_input = (input_thread_t *)p_stream->p_parent->p_parent;
1514 while( (p_audio_buf = id->p_decoder->pf_decode_audio( id->p_decoder,
1518 stats_UpdateInteger( p_input, p_input->counters.p_decoded_audio,
1520 if( p_sys->b_master_sync )
1522 mtime_t i_dts = date_Get( &id->interpolated_pts ) + 1;
1523 if ( p_audio_buf->start_date - i_dts > MASTER_SYNC_MAX_DRIFT
1524 || p_audio_buf->start_date - i_dts < -MASTER_SYNC_MAX_DRIFT )
1526 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
1527 date_Set( &id->interpolated_pts, p_audio_buf->start_date );
1528 i_dts = p_audio_buf->start_date + 1;
1530 p_sys->i_master_drift = p_audio_buf->start_date - i_dts;
1531 date_Increment( &id->interpolated_pts, p_audio_buf->i_nb_samples );
1532 p_audio_buf->start_date -= p_sys->i_master_drift;
1533 p_audio_buf->end_date -= p_sys->i_master_drift;
1536 p_audio_block = p_audio_buf->p_sys;
1537 p_audio_block->i_buffer = p_audio_buf->i_nb_bytes;
1538 p_audio_block->i_dts = p_audio_block->i_pts =
1539 p_audio_buf->start_date;
1540 p_audio_block->i_length = p_audio_buf->end_date -
1541 p_audio_buf->start_date;
1542 p_audio_block->i_samples = p_audio_buf->i_nb_samples;
1544 /* Run filter chain */
1545 for( i = 0; i < id->i_filter; i++ )
1548 id->pp_filter[i]->pf_audio_filter( id->pp_filter[i],
1552 /* Run user specified filter chain */
1553 for( i = 0; i < id->i_ufilter; i++ )
1556 id->pp_ufilter[i]->pf_audio_filter( id->pp_ufilter[i],
1560 p_audio_buf->p_buffer = p_audio_block->p_buffer;
1561 p_audio_buf->i_nb_bytes = p_audio_block->i_buffer;
1562 p_audio_buf->i_nb_samples = p_audio_block->i_samples;
1563 p_audio_buf->start_date = p_audio_block->i_dts;
1564 p_audio_buf->end_date = p_audio_block->i_dts + p_audio_block->i_length;
1566 p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf );
1567 block_ChainAppend( out, p_block );
1568 block_Release( p_audio_block );
1569 free( p_audio_buf );
1575 static void audio_release_buffer( aout_buffer_t *p_buffer )
1577 if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
1578 if( p_buffer ) free( p_buffer );
1581 static aout_buffer_t *audio_new_buffer( decoder_t *p_dec, int i_samples )
1583 aout_buffer_t *p_buffer;
1587 if( p_dec->fmt_out.audio.i_bitspersample )
1589 i_size = i_samples * p_dec->fmt_out.audio.i_bitspersample / 8 *
1590 p_dec->fmt_out.audio.i_channels;
1592 else if( p_dec->fmt_out.audio.i_bytes_per_frame &&
1593 p_dec->fmt_out.audio.i_frame_length )
1595 i_size = i_samples * p_dec->fmt_out.audio.i_bytes_per_frame /
1596 p_dec->fmt_out.audio.i_frame_length;
1600 i_size = i_samples * 4 * p_dec->fmt_out.audio.i_channels;
1603 p_buffer = malloc( sizeof(aout_buffer_t) );
1604 p_buffer->pf_release = audio_release_buffer;
1605 p_buffer->p_sys = p_block = block_New( p_dec, i_size );
1607 p_buffer->p_buffer = p_block->p_buffer;
1608 p_buffer->i_size = p_buffer->i_nb_bytes = p_block->i_buffer;
1609 p_buffer->i_nb_samples = i_samples;
1610 p_block->i_samples = i_samples;
1615 static void audio_del_buffer( decoder_t *p_dec, aout_buffer_t *p_buffer )
1617 if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
1618 if( p_buffer ) free( p_buffer );
1624 static int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_t *id )
1626 sout_stream_sys_t *p_sys = p_stream->p_sys;
1630 * Initialization of decoder structures
1632 id->p_decoder->fmt_out = id->p_decoder->fmt_in;
1633 id->p_decoder->fmt_out.i_extra = 0;
1634 id->p_decoder->fmt_out.p_extra = 0;
1635 id->p_decoder->pf_decode_video = 0;
1636 id->p_decoder->pf_vout_buffer_new = video_new_buffer_decoder;
1637 id->p_decoder->pf_vout_buffer_del = video_del_buffer_decoder;
1638 id->p_decoder->pf_picture_link = video_link_picture_decoder;
1639 id->p_decoder->pf_picture_unlink = video_unlink_picture_decoder;
1640 id->p_decoder->p_owner = malloc( sizeof(decoder_owner_sys_t) );
1641 for( i = 0; i < PICTURE_RING_SIZE; i++ )
1642 id->p_decoder->p_owner->pp_pics[i] = 0;
1643 id->p_decoder->p_owner->p_sys = p_sys;
1644 /* id->p_decoder->p_cfg = p_sys->p_video_cfg; */
1646 id->p_decoder->p_module =
1647 module_Need( id->p_decoder, "decoder", "$codec", 0 );
1649 if( !id->p_decoder->p_module )
1651 msg_Err( p_stream, "cannot find decoder" );
1652 return VLC_EGENERIC;
1657 * Because some info about the decoded input will only be available
1658 * once the first frame is decoded, we actually only test the availability
1659 * of the encoder here.
1662 /* Initialization of encoder format structures */
1663 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1664 id->p_decoder->fmt_out.i_codec );
1665 id->p_encoder->fmt_in.video.i_chroma = id->p_decoder->fmt_out.i_codec;
1667 /* The dimensions will be set properly later on.
1668 * Just put sensible values so we can test an encoder is available. */
1669 id->p_encoder->fmt_in.video.i_width =
1670 id->p_encoder->fmt_out.video.i_width ?
1671 id->p_encoder->fmt_out.video.i_width :
1672 id->p_decoder->fmt_in.video.i_width ?
1673 id->p_decoder->fmt_in.video.i_width : 16;
1674 id->p_encoder->fmt_in.video.i_height =
1675 id->p_encoder->fmt_out.video.i_height ?
1676 id->p_encoder->fmt_out.video.i_height :
1677 id->p_decoder->fmt_in.video.i_height ?
1678 id->p_decoder->fmt_in.video.i_height : 16;
1679 id->p_encoder->fmt_in.video.i_frame_rate = 25;
1680 id->p_encoder->fmt_in.video.i_frame_rate_base = 1;
1682 id->p_encoder->i_threads = p_sys->i_threads;
1683 id->p_encoder->p_cfg = p_sys->p_video_cfg;
1685 id->p_encoder->p_module =
1686 module_Need( id->p_encoder, "encoder", p_sys->psz_venc, VLC_TRUE );
1687 if( !id->p_encoder->p_module )
1689 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_venc );
1690 module_Unneed( id->p_decoder, id->p_decoder->p_module );
1691 id->p_decoder->p_module = 0;
1692 return VLC_EGENERIC;
1695 /* Close the encoder.
1696 * We'll open it only when we have the first frame. */
1697 module_Unneed( id->p_encoder, id->p_encoder->p_module );
1698 if( id->p_encoder->fmt_out.p_extra )
1699 free( id->p_encoder->fmt_out.p_extra );
1700 id->p_encoder->p_module = NULL;
1702 if( p_sys->i_threads >= 1 )
1704 int i_priority = p_sys->b_high_priority ? VLC_THREAD_PRIORITY_OUTPUT :
1705 VLC_THREAD_PRIORITY_VIDEO;
1706 p_sys->id_video = id;
1707 vlc_mutex_init( p_stream, &p_sys->lock_out );
1708 vlc_cond_init( p_stream, &p_sys->cond );
1709 memset( p_sys->pp_pics, 0, sizeof(p_sys->pp_pics) );
1710 p_sys->i_first_pic = 0;
1711 p_sys->i_last_pic = 0;
1712 p_sys->p_buffers = NULL;
1713 p_sys->b_die = p_sys->b_error = 0;
1714 if( vlc_thread_create( p_sys, "encoder", EncoderThread, i_priority,
1717 msg_Err( p_stream, "cannot spawn encoder thread" );
1718 module_Unneed( id->p_decoder, id->p_decoder->p_module );
1719 id->p_decoder->p_module = 0;
1720 return VLC_EGENERIC;
1727 static int transcode_video_encoder_open( sout_stream_t *p_stream,
1728 sout_stream_id_t *id )
1730 sout_stream_sys_t *p_sys = p_stream->p_sys;
1732 /* Calculate scaling, padding, cropping etc. */
1733 /* width/height of source */
1734 int i_src_width = id->p_decoder->fmt_out.video.i_width;
1735 int i_src_height = id->p_decoder->fmt_out.video.i_height;
1737 /* with/height scaling */
1738 float f_scale_width = 1;
1739 float f_scale_height = 1;
1741 /* width/height of output stream */
1746 float f_aspect = (float)id->p_decoder->fmt_out.video.i_aspect /
1749 msg_Dbg( p_stream, "decoder aspect is %i:%i",
1750 id->p_decoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
1752 /* Change f_aspect from source frame to source pixel */
1753 f_aspect = f_aspect * i_src_height / i_src_width;
1754 msg_Dbg( p_stream, "source pixel aspect is %f:1", f_aspect );
1756 /* width/height after cropping */
1757 p_sys->i_src_x_offset = p_sys->i_crop_left & ~1;
1758 p_sys->i_src_y_offset = p_sys->i_crop_top & ~1;
1759 p_sys->i_crop_width = i_src_width - ( p_sys->i_crop_left & ~1 ) -
1760 ( p_sys->i_crop_right & ~1 );
1761 p_sys->i_crop_height = i_src_height - ( p_sys->i_crop_top & ~1 ) -
1762 ( p_sys->i_crop_bottom & ~1 );
1764 /* Calculate scaling factor for specified parameters */
1765 if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1766 id->p_encoder->fmt_out.video.i_height <= 0 && p_sys->f_scale )
1768 /* Global scaling. Make sure width will remain a factor of 16 */
1771 int i_new_width = i_src_width * p_sys->f_scale;
1773 if( i_new_width % 16 <= 7 && i_new_width >= 16 )
1774 i_new_width -= i_new_width % 16;
1776 i_new_width += 16 - i_new_width % 16;
1778 f_real_scale = (float)( i_new_width ) / (float) i_src_width;
1780 i_new_height = __MAX( 16, i_src_height * (float)f_real_scale );
1782 f_scale_width = f_real_scale;
1783 f_scale_height = (float) i_new_height / (float) i_src_height;
1785 else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1786 id->p_encoder->fmt_out.video.i_height <= 0 )
1788 /* Only width specified */
1789 f_scale_width = (float)id->p_encoder->fmt_out.video.i_width /
1790 p_sys->i_crop_width;
1791 f_scale_height = f_scale_width;
1793 else if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1794 id->p_encoder->fmt_out.video.i_height > 0 )
1796 /* Only height specified */
1797 f_scale_height = (float)id->p_encoder->fmt_out.video.i_height /
1798 p_sys->i_crop_height;
1799 f_scale_width = f_scale_height;
1801 else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1802 id->p_encoder->fmt_out.video.i_height > 0 )
1804 /* Width and height specified */
1805 f_scale_width = (float)id->p_encoder->fmt_out.video.i_width
1806 / p_sys->i_crop_width;
1807 f_scale_height = (float)id->p_encoder->fmt_out.video.i_height
1808 / p_sys->i_crop_height;
1811 /* check maxwidth and maxheight
1812 * note: maxwidth and maxheight currently does not handle
1813 * canvas and padding, just scaling and cropping.
1815 if( p_sys->i_maxwidth && f_scale_width > (float)p_sys->i_maxwidth /
1816 p_sys->i_crop_width )
1818 f_scale_width = (float)p_sys->i_maxwidth / p_sys->i_crop_width;
1820 if( p_sys->i_maxheight && f_scale_height > (float)p_sys->i_maxheight /
1821 p_sys->i_crop_height )
1823 f_scale_height = (float)p_sys->i_maxheight / p_sys->i_crop_height;
1826 /* Change aspect ratio from source pixel to scaled pixel */
1827 f_aspect = f_aspect * f_scale_height / f_scale_width;
1828 msg_Dbg( p_stream, "scaled pixel aspect is %f:1", f_aspect );
1830 /* Correct scaling for target aspect ratio
1831 * Shrink video if necessary
1833 if ( p_sys->i_canvas_aspect > 0 )
1835 float f_target_aspect = (float)p_sys->i_canvas_aspect /
1838 if( p_sys->i_canvas_width > 0 && p_sys->i_canvas_height > 0)
1840 /* Calculate pixel aspect of canvas */
1841 f_target_aspect = f_target_aspect / p_sys->i_canvas_width *
1842 p_sys->i_canvas_height;
1844 if( f_target_aspect > f_aspect )
1846 /* Reduce width scale to increase aspect */
1847 f_scale_width = f_scale_width * f_aspect / f_target_aspect;
1851 /* Reduce height scale to decrease aspect */
1852 f_scale_height = f_scale_height * f_target_aspect / f_aspect;
1854 f_aspect = f_target_aspect;
1855 msg_Dbg( p_stream, "canvas scaled pixel aspect is %f:1", f_aspect );
1858 /* f_scale_width and f_scale_height are now final */
1859 /* Calculate width, height from scaling
1860 * Make sure its multiple of 2
1862 i_dst_width = 2 * (int)( p_sys->i_crop_width * f_scale_width / 2 + 0.5 );
1864 (int)( p_sys->i_crop_height * f_scale_height / 2 + 0.5 );
1866 p_sys->i_nopadd_width = i_dst_width;
1867 p_sys->i_nopadd_height = i_dst_height;
1868 p_sys->i_dst_x_offset = 0;
1869 p_sys->i_dst_y_offset = 0;
1871 /* Handle canvas and padding */
1872 if( p_sys->i_canvas_width <= 0 )
1874 /* No canvas width set, add explicit padding border */
1875 i_dst_width = p_sys->i_nopadd_width + ( p_sys->i_padd_left & ~1 ) +
1876 ( p_sys->i_padd_right & ~1 );
1877 p_sys->i_dst_x_offset = ( p_sys->i_padd_left & ~1 );
1881 /* Canvas set, check if we have to padd or crop */
1882 if( p_sys->i_canvas_width < p_sys->i_nopadd_width )
1884 /* need to crop more, but keep same scaling */
1885 int i_crop = 2 * (int)( ( p_sys->i_canvas_width & ~1 ) /
1886 f_scale_width / 2 + 0.5 );
1888 p_sys->i_src_x_offset += ( ( p_sys->i_crop_width - i_crop ) / 2 )
1890 p_sys->i_crop_width = i_crop;
1891 i_dst_width = p_sys->i_canvas_width & ~1;
1892 p_sys->i_nopadd_width = i_dst_width;
1894 else if( p_sys->i_canvas_width > p_sys->i_nopadd_width )
1897 i_dst_width = p_sys->i_canvas_width & ~1;
1898 p_sys->i_dst_x_offset = ( i_dst_width - p_sys->i_nopadd_width )/2;
1899 p_sys->i_dst_x_offset = p_sys->i_dst_x_offset & ~1;
1903 if( p_sys->i_canvas_height <= 0 )
1905 /* No canvas set, add padding border */
1906 i_dst_height = p_sys->i_nopadd_height + ( p_sys->i_padd_top & ~1 ) +
1907 ( p_sys->i_padd_bottom & ~1 );
1908 p_sys->i_dst_y_offset = ( p_sys->i_padd_top & ~1 );
1912 /* Canvas set, check if we have to padd or crop */
1913 if( p_sys->i_canvas_height < p_sys->i_nopadd_height )
1915 /* need to crop more, but keep same scaling */
1916 int i_crop = 2 * (int)( ( p_sys->i_canvas_height & ~1 ) /
1917 f_scale_height / 2 + 0.5 );
1919 p_sys->i_src_y_offset += ( ( p_sys->i_crop_height - i_crop ) / 2 )
1921 p_sys->i_crop_height = i_crop;
1922 i_dst_height = p_sys->i_canvas_height & ~1;
1923 p_sys->i_nopadd_height = i_dst_height;
1925 else if( p_sys->i_canvas_height > p_sys->i_nopadd_height )
1928 i_dst_height = p_sys->i_canvas_height & ~1;
1929 p_sys->i_dst_y_offset = ( i_dst_height - p_sys->i_nopadd_height )
1931 p_sys->i_dst_y_offset = p_sys->i_dst_y_offset & ~1;
1935 /* Change aspect ratio from scaled pixel to output frame */
1936 f_aspect = f_aspect * i_dst_width / i_dst_height;
1938 /* Store calculated values */
1939 id->p_encoder->fmt_out.video.i_width = i_dst_width;
1940 id->p_encoder->fmt_out.video.i_height = i_dst_height;
1942 id->p_encoder->fmt_in.video.i_width = i_dst_width;
1943 id->p_encoder->fmt_in.video.i_height = i_dst_height;
1945 msg_Dbg( p_stream, "source %ix%i, crop %ix%i, "
1946 "destination %ix%i, padding %ix%i",
1947 i_src_width, i_src_height,
1948 p_sys->i_crop_width, p_sys->i_crop_height,
1949 p_sys->i_nopadd_width, p_sys->i_nopadd_height,
1950 i_dst_width, i_dst_height
1953 /* Handle frame rate conversion */
1954 if( !id->p_encoder->fmt_out.video.i_frame_rate ||
1955 !id->p_encoder->fmt_out.video.i_frame_rate_base )
1957 if( id->p_decoder->fmt_out.video.i_frame_rate &&
1958 id->p_decoder->fmt_out.video.i_frame_rate_base )
1960 id->p_encoder->fmt_out.video.i_frame_rate =
1961 id->p_decoder->fmt_out.video.i_frame_rate;
1962 id->p_encoder->fmt_out.video.i_frame_rate_base =
1963 id->p_decoder->fmt_out.video.i_frame_rate_base;
1967 /* Pick a sensible default value */
1968 id->p_encoder->fmt_out.video.i_frame_rate = 25;
1969 id->p_encoder->fmt_out.video.i_frame_rate_base = 1;
1973 id->p_encoder->fmt_in.video.i_frame_rate =
1974 id->p_encoder->fmt_out.video.i_frame_rate;
1975 id->p_encoder->fmt_in.video.i_frame_rate_base =
1976 id->p_encoder->fmt_out.video.i_frame_rate_base;
1978 date_Init( &id->interpolated_pts,
1979 id->p_encoder->fmt_out.video.i_frame_rate,
1980 id->p_encoder->fmt_out.video.i_frame_rate_base );
1982 /* Check whether a particular aspect ratio was requested */
1983 if( !id->p_encoder->fmt_out.video.i_aspect )
1985 id->p_encoder->fmt_out.video.i_aspect = (int)( f_aspect * VOUT_ASPECT_FACTOR + 0.5 );
1987 id->p_encoder->fmt_in.video.i_aspect =
1988 id->p_encoder->fmt_out.video.i_aspect;
1990 msg_Dbg( p_stream, "encoder aspect is %i:%i", id->p_encoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
1992 id->p_encoder->p_module =
1993 module_Need( id->p_encoder, "encoder", p_sys->psz_venc, VLC_TRUE );
1994 if( !id->p_encoder->p_module )
1996 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_venc );
1997 return VLC_EGENERIC;
2000 id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
2002 /* Hack for mp2v/mp1v transcoding support */
2003 if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','1','v') ||
2004 id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','2','v') )
2006 id->p_encoder->fmt_out.i_codec = VLC_FOURCC('m','p','g','v');
2009 id->id = p_stream->p_sys->p_out->pf_add( p_stream->p_sys->p_out,
2010 &id->p_encoder->fmt_out );
2013 msg_Err( p_stream, "cannot add this stream" );
2014 return VLC_EGENERIC;
2020 static void transcode_video_close( sout_stream_t *p_stream,
2021 sout_stream_id_t *id )
2025 if( p_stream->p_sys->i_threads >= 1 )
2027 vlc_mutex_lock( &p_stream->p_sys->lock_out );
2028 p_stream->p_sys->b_die = 1;
2029 vlc_cond_signal( &p_stream->p_sys->cond );
2030 vlc_mutex_unlock( &p_stream->p_sys->lock_out );
2031 vlc_thread_join( p_stream->p_sys );
2032 vlc_mutex_destroy( &p_stream->p_sys->lock_out );
2033 vlc_cond_destroy( &p_stream->p_sys->cond );
2037 if( id->p_decoder->p_module )
2038 module_Unneed( id->p_decoder, id->p_decoder->p_module );
2040 if( id->p_decoder->p_owner )
2042 /* Clean-up pictures ring buffer */
2043 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2045 if( id->p_decoder->p_owner->pp_pics[i] )
2046 video_del_buffer( VLC_OBJECT(id->p_decoder),
2047 id->p_decoder->p_owner->pp_pics[i] );
2049 free( id->p_decoder->p_owner );
2053 if( id->p_encoder->p_module )
2054 module_Unneed( id->p_encoder, id->p_encoder->p_module );
2057 for( i = 0; i < id->i_filter; i++ )
2059 vlc_object_detach( id->pp_filter[i] );
2060 if( id->pp_filter[i]->p_module )
2061 module_Unneed( id->pp_filter[i], id->pp_filter[i]->p_module );
2063 /* Clean-up pictures ring buffer */
2064 for( j = 0; j < PICTURE_RING_SIZE; j++ )
2066 if( id->pp_filter[i]->p_owner->pp_pics[j] )
2067 video_del_buffer( VLC_OBJECT(id->pp_filter[i]),
2068 id->pp_filter[i]->p_owner->pp_pics[j] );
2070 free( id->pp_filter[i]->p_owner );
2071 vlc_object_destroy( id->pp_filter[i] );
2072 id->pp_filter[i] = NULL;
2075 for( i = 0; i < id->i_ufilter; i++ )
2077 vlc_object_detach( id->pp_ufilter[i] );
2078 if( id->pp_ufilter[i]->p_module )
2079 module_Unneed( id->pp_ufilter[i], id->pp_ufilter[i]->p_module );
2081 /* Clean-up pictures ring buffer */
2082 for( j = 0; j < PICTURE_RING_SIZE; j++ )
2084 if( id->pp_ufilter[i]->p_owner->pp_pics[j] )
2085 video_del_buffer( VLC_OBJECT(id->pp_ufilter[i]),
2086 id->pp_ufilter[i]->p_owner->pp_pics[j] );
2088 free( id->pp_ufilter[i]->p_owner );
2089 vlc_object_destroy( id->pp_ufilter[i] );
2090 id->pp_ufilter[i] = NULL;
2094 static int transcode_video_process( sout_stream_t *p_stream,
2095 sout_stream_id_t *id,
2096 block_t *in, block_t **out )
2098 sout_stream_sys_t *p_sys = p_stream->p_sys;
2099 int i_duplicate = 1, i;
2100 picture_t *p_pic, *p_pic2 = NULL;
2102 input_thread_t *p_input = NULL;
2104 if( p_stream->p_parent->p_parent && p_stream->p_parent->p_parent->
2105 i_object_type == VLC_OBJECT_INPUT )
2106 p_input = (input_thread_t *)p_stream->p_parent->p_parent;
2108 while( (p_pic = id->p_decoder->pf_decode_video( id->p_decoder, &in )) )
2110 subpicture_t *p_subpic = 0;
2112 stats_UpdateInteger( p_input, p_input->counters.p_decoded_video,
2115 if( p_stream->p_sout->i_out_pace_nocontrol && p_sys->b_hurry_up )
2117 mtime_t current_date = mdate();
2118 if( current_date + 50000 > p_pic->date )
2120 msg_Dbg( p_stream, "late picture skipped ("I64Fd")",
2121 current_date + 50000 - p_pic->date );
2122 p_pic->pf_release( p_pic );
2127 if( p_sys->b_master_sync )
2129 mtime_t i_video_drift;
2130 mtime_t i_master_drift = p_sys->i_master_drift;
2133 i_pts = date_Get( &id->interpolated_pts ) + 1;
2134 if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2135 || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2137 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2138 date_Set( &id->interpolated_pts, p_pic->date );
2139 i_pts = p_pic->date + 1;
2141 i_video_drift = p_pic->date - i_pts;
2144 /* Set the pts of the frame being encoded */
2145 p_pic->date = i_pts;
2147 if( i_video_drift < i_master_drift - 50000 )
2150 msg_Dbg( p_stream, "dropping frame (%i)",
2151 (int)(i_video_drift - i_master_drift) );
2153 p_pic->pf_release( p_pic );
2156 else if( i_video_drift > i_master_drift + 50000 )
2159 msg_Dbg( p_stream, "adding frame (%i)",
2160 (int)(i_video_drift - i_master_drift) );
2166 if( !id->p_encoder->p_module )
2168 if( transcode_video_encoder_open( p_stream, id ) != VLC_SUCCESS )
2170 p_pic->pf_release( p_pic );
2171 transcode_video_close( p_stream, id );
2172 id->b_transcode = VLC_FALSE;
2173 return VLC_EGENERIC;
2177 if( p_stream->p_sys->b_deinterlace )
2179 id->pp_filter[id->i_filter] =
2180 vlc_object_create( p_stream, VLC_OBJECT_FILTER );
2181 vlc_object_attach( id->pp_filter[id->i_filter], p_stream );
2183 id->pp_filter[id->i_filter]->pf_vout_buffer_new =
2184 video_new_buffer_filter;
2185 id->pp_filter[id->i_filter]->pf_vout_buffer_del =
2186 video_del_buffer_filter;
2188 id->pp_filter[id->i_filter]->fmt_in = id->p_decoder->fmt_out;
2189 id->pp_filter[id->i_filter]->fmt_out = id->p_decoder->fmt_out;
2190 id->pp_filter[id->i_filter]->p_cfg = p_sys->p_deinterlace_cfg;
2191 id->pp_filter[id->i_filter]->p_module =
2192 module_Need( id->pp_filter[id->i_filter],
2193 "video filter2", p_sys->psz_deinterlace, 0 );
2194 if( id->pp_filter[id->i_filter]->p_module )
2196 id->pp_filter[id->i_filter]->p_owner =
2197 malloc( sizeof(filter_owner_sys_t) );
2198 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2199 id->pp_filter[id->i_filter]->p_owner->pp_pics[i] = 0;
2200 id->pp_filter[id->i_filter]->p_owner->p_sys = p_sys;
2206 msg_Dbg( p_stream, "no video filter found" );
2207 vlc_object_detach( id->pp_filter[id->i_filter] );
2208 vlc_object_destroy( id->pp_filter[id->i_filter] );
2212 /* Check if we need a filter for chroma conversion or resizing */
2213 if( id->p_decoder->fmt_out.video.i_chroma !=
2214 id->p_encoder->fmt_in.video.i_chroma ||
2216 (int)id->p_decoder->fmt_out.video.i_width != p_sys->i_crop_width ||
2217 p_sys->i_crop_width != p_sys->i_nopadd_width ||
2218 p_sys->i_nopadd_width != (int)id->p_encoder->fmt_out.video.i_width ||
2220 (int)id->p_decoder->fmt_out.video.i_height != p_sys->i_crop_height ||
2221 p_sys->i_crop_height != p_sys->i_nopadd_height ||
2222 p_sys->i_nopadd_height != (int)id->p_encoder->fmt_out.video.i_height)
2224 id->pp_filter[id->i_filter] =
2225 vlc_object_create( p_stream, VLC_OBJECT_FILTER );
2226 vlc_object_attach( id->pp_filter[id->i_filter], p_stream );
2228 id->pp_filter[id->i_filter]->pf_vout_buffer_new =
2229 video_new_buffer_filter;
2230 id->pp_filter[id->i_filter]->pf_vout_buffer_del =
2231 video_del_buffer_filter;
2233 id->pp_filter[id->i_filter]->fmt_in = id->p_decoder->fmt_out;
2234 id->pp_filter[id->i_filter]->fmt_out = id->p_encoder->fmt_in;
2235 id->pp_filter[id->i_filter]->p_cfg = NULL;
2237 id->pp_filter[id->i_filter]->fmt_in.video.i_x_offset = p_sys->i_src_x_offset;
2238 id->pp_filter[id->i_filter]->fmt_in.video.i_y_offset = p_sys->i_src_y_offset;
2239 id->pp_filter[id->i_filter]->fmt_in.video.i_visible_width = p_sys->i_crop_width;
2240 id->pp_filter[id->i_filter]->fmt_in.video.i_visible_height = p_sys->i_crop_height;
2242 id->pp_filter[id->i_filter]->fmt_out.video.i_x_offset = p_sys->i_dst_x_offset;
2243 id->pp_filter[id->i_filter]->fmt_out.video.i_y_offset = p_sys->i_dst_y_offset;
2244 id->pp_filter[id->i_filter]->fmt_out.video.i_visible_width = p_sys->i_nopadd_width;
2245 id->pp_filter[id->i_filter]->fmt_out.video.i_visible_height = p_sys->i_nopadd_height;
2247 id->pp_filter[id->i_filter]->p_module =
2248 module_Need( id->pp_filter[id->i_filter],
2249 "crop padd", 0, 0 );
2250 if( id->pp_filter[id->i_filter]->p_module )
2252 id->pp_filter[id->i_filter]->p_owner =
2253 malloc( sizeof(filter_owner_sys_t) );
2254 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2255 id->pp_filter[id->i_filter]->p_owner->pp_pics[i] = 0;
2256 id->pp_filter[id->i_filter]->p_owner->p_sys = p_sys;
2262 msg_Dbg( p_stream, "no video filter found" );
2263 vlc_object_detach( id->pp_filter[id->i_filter] );
2264 vlc_object_destroy( id->pp_filter[id->i_filter] );
2266 p_pic->pf_release( p_pic );
2267 transcode_video_close( p_stream, id );
2268 id->b_transcode = VLC_FALSE;
2269 return VLC_EGENERIC;
2273 for( i = 0; (i < p_sys->i_vfilters) && (id->i_ufilter < TRANSCODE_FILTERS); i++ )
2275 id->pp_ufilter[id->i_ufilter] =
2276 vlc_object_create( p_stream, VLC_OBJECT_FILTER );
2277 vlc_object_attach( id->pp_ufilter[id->i_ufilter], p_stream );
2279 id->pp_ufilter[id->i_ufilter]->pf_vout_buffer_new =
2280 video_new_buffer_filter;
2281 id->pp_ufilter[id->i_ufilter]->pf_vout_buffer_del =
2282 video_del_buffer_filter;
2284 id->pp_ufilter[id->i_ufilter]->fmt_in = id->p_encoder->fmt_in;
2285 id->pp_ufilter[id->i_ufilter]->fmt_out = id->p_encoder->fmt_in;
2286 id->pp_ufilter[id->i_ufilter]->p_cfg = p_sys->p_vfilters_cfg[i];
2287 id->pp_ufilter[id->i_ufilter]->p_module =
2288 module_Need( id->pp_ufilter[id->i_ufilter],
2289 "video filter2", p_sys->psz_vfilters[i], 0 );
2290 if( id->pp_ufilter[id->i_ufilter]->p_module )
2292 id->pp_ufilter[id->i_ufilter]->p_owner =
2293 malloc( sizeof(filter_owner_sys_t) );
2294 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2295 id->pp_ufilter[id->i_ufilter]->p_owner->pp_pics[i] = 0;
2296 id->pp_ufilter[id->i_ufilter]->p_owner->p_sys = p_sys;
2301 msg_Dbg( p_stream, "no video filter found" );
2302 vlc_object_detach( id->pp_ufilter[id->i_ufilter] );
2303 vlc_object_destroy( id->pp_ufilter[id->i_ufilter] );
2304 id->pp_ufilter[id->i_ufilter] = NULL;
2309 /* Run filter chain */
2310 for( i = 0; i < id->i_filter; i++ )
2312 p_pic = id->pp_filter[i]->pf_video_filter(id->pp_filter[i], p_pic);
2319 /* Check if we have a subpicture to overlay */
2322 p_subpic = spu_SortSubpictures( p_sys->p_spu, p_pic->date,
2323 VLC_FALSE /* Fixme: check if stream is paused */ );
2324 /* TODO: get another pic */
2327 /* Overlay subpicture */
2330 int i_scale_width, i_scale_height;
2331 video_format_t *p_fmt;
2333 i_scale_width = id->p_encoder->fmt_in.video.i_width * 1000 /
2334 id->p_decoder->fmt_out.video.i_width;
2335 i_scale_height = id->p_encoder->fmt_in.video.i_height * 1000 /
2336 id->p_decoder->fmt_out.video.i_height;
2338 if( p_pic->i_refcount && !id->i_filter )
2340 /* We can't modify the picture, we need to duplicate it */
2341 picture_t *p_tmp = video_new_buffer_decoder( id->p_decoder );
2344 vout_CopyPicture( p_stream, p_tmp, p_pic );
2345 p_pic->pf_release( p_pic );
2351 p_fmt = &id->pp_filter[id->i_filter -1]->fmt_out.video;
2353 p_fmt = &id->p_decoder->fmt_out.video;
2355 /* FIXME (shouldn't have to be done here) */
2356 p_fmt->i_sar_num = p_fmt->i_aspect *
2357 p_fmt->i_height / p_fmt->i_width;
2358 p_fmt->i_sar_den = VOUT_ASPECT_FACTOR;
2360 spu_RenderSubpictures( p_sys->p_spu, p_fmt, p_pic, p_pic, p_subpic,
2361 i_scale_width, i_scale_height );
2364 /* Run user specified filter chain */
2365 for( i = 0; i < id->i_ufilter; i++ )
2367 p_pic = id->pp_ufilter[i]->pf_video_filter(id->pp_ufilter[i], p_pic);
2370 if( p_sys->i_threads == 0 )
2373 p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
2374 block_ChainAppend( out, p_block );
2377 if( p_sys->b_master_sync )
2379 mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
2380 if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2381 || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2383 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2384 date_Set( &id->interpolated_pts, p_pic->date );
2385 i_pts = p_pic->date + 1;
2387 date_Increment( &id->interpolated_pts, 1 );
2390 if( p_sys->b_master_sync && i_duplicate > 1 )
2392 mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
2393 if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2394 || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2396 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2397 date_Set( &id->interpolated_pts, p_pic->date );
2398 i_pts = p_pic->date + 1;
2400 date_Increment( &id->interpolated_pts, 1 );
2402 if( p_sys->i_threads >= 1 )
2404 /* We can't modify the picture, we need to duplicate it */
2405 p_pic2 = video_new_buffer_decoder( id->p_decoder );
2406 if( p_pic2 != NULL )
2408 vout_CopyPicture( p_stream, p_pic2, p_pic );
2409 p_pic2->date = i_pts;
2415 p_pic->date = i_pts;
2416 p_block = id->p_encoder->pf_encode_video(id->p_encoder, p_pic);
2417 block_ChainAppend( out, p_block );
2421 if( p_sys->i_threads == 0 )
2423 p_pic->pf_release( p_pic );
2427 vlc_mutex_lock( &p_sys->lock_out );
2428 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic;
2429 p_sys->i_last_pic %= PICTURE_RING_SIZE;
2430 *out = p_sys->p_buffers;
2431 p_sys->p_buffers = NULL;
2432 if( p_pic2 != NULL )
2434 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic2;
2435 p_sys->i_last_pic %= PICTURE_RING_SIZE;
2437 vlc_cond_signal( &p_sys->cond );
2438 vlc_mutex_unlock( &p_sys->lock_out );
2445 static int EncoderThread( sout_stream_sys_t *p_sys )
2447 sout_stream_id_t *id = p_sys->id_video;
2450 while( !p_sys->b_die && !p_sys->b_error )
2454 vlc_mutex_lock( &p_sys->lock_out );
2455 while( p_sys->i_last_pic == p_sys->i_first_pic )
2457 vlc_cond_wait( &p_sys->cond, &p_sys->lock_out );
2458 if( p_sys->b_die || p_sys->b_error ) break;
2460 if( p_sys->b_die || p_sys->b_error )
2462 vlc_mutex_unlock( &p_sys->lock_out );
2466 p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2467 p_sys->i_first_pic %= PICTURE_RING_SIZE;
2468 vlc_mutex_unlock( &p_sys->lock_out );
2470 p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
2471 vlc_mutex_lock( &p_sys->lock_out );
2472 block_ChainAppend( &p_sys->p_buffers, p_block );
2474 vlc_mutex_unlock( &p_sys->lock_out );
2475 p_pic->pf_release( p_pic );
2478 while( p_sys->i_last_pic != p_sys->i_first_pic )
2480 p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2481 p_sys->i_first_pic %= PICTURE_RING_SIZE;
2482 p_pic->pf_release( p_pic );
2484 block_ChainRelease( p_sys->p_buffers );
2489 struct picture_sys_t
2491 vlc_object_t *p_owner;
2494 static void video_release_buffer( picture_t *p_pic )
2496 if( p_pic && !p_pic->i_refcount && p_pic->pf_release && p_pic->p_sys )
2498 video_del_buffer_decoder( (decoder_t *)p_pic->p_sys->p_owner, p_pic );
2500 else if( p_pic && p_pic->i_refcount > 0 ) p_pic->i_refcount--;
2503 static picture_t *video_new_buffer( vlc_object_t *p_this, picture_t **pp_ring,
2504 sout_stream_sys_t *p_sys )
2506 decoder_t *p_dec = (decoder_t *)p_this;
2510 /* Find an empty space in the picture ring buffer */
2511 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2513 if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
2515 pp_ring[i]->i_status = RESERVED_PICTURE;
2519 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2521 if( pp_ring[i] == 0 ) break;
2524 if( i == PICTURE_RING_SIZE && p_sys->i_threads >= 1 )
2526 int i_first_pic = p_sys->i_first_pic;
2528 if( p_sys->i_first_pic != p_sys->i_last_pic )
2530 /* Encoder still has stuff to encode, wait to clear-up the list */
2531 while( p_sys->i_first_pic == i_first_pic )
2535 /* Find an empty space in the picture ring buffer */
2536 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2538 if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
2540 pp_ring[i]->i_status = RESERVED_PICTURE;
2544 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2546 if( pp_ring[i] == 0 ) break;
2550 if( i == PICTURE_RING_SIZE )
2552 msg_Err( p_this, "decoder/filter is leaking pictures, "
2553 "resetting its ring buffer" );
2555 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2557 pp_ring[i]->pf_release( pp_ring[i] );
2563 p_pic = malloc( sizeof(picture_t) );
2564 p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
2565 vout_AllocatePicture( VLC_OBJECT(p_dec), p_pic,
2566 p_dec->fmt_out.video.i_chroma,
2567 p_dec->fmt_out.video.i_width,
2568 p_dec->fmt_out.video.i_height,
2569 p_dec->fmt_out.video.i_aspect );
2571 if( !p_pic->i_planes )
2577 p_pic->pf_release = video_release_buffer;
2578 p_pic->p_sys = malloc( sizeof(picture_sys_t) );
2579 p_pic->p_sys->p_owner = p_this;
2580 p_pic->i_status = RESERVED_PICTURE;
2586 static picture_t *video_new_buffer_decoder( decoder_t *p_dec )
2588 return video_new_buffer( VLC_OBJECT(p_dec),
2589 p_dec->p_owner->pp_pics, p_dec->p_owner->p_sys );
2592 static picture_t *video_new_buffer_filter( filter_t *p_filter )
2594 return video_new_buffer( VLC_OBJECT(p_filter),
2595 p_filter->p_owner->pp_pics,
2596 p_filter->p_owner->p_sys );
2599 static void video_del_buffer( vlc_object_t *p_this, picture_t *p_pic )
2601 if( p_pic && p_pic->p_data_orig ) free( p_pic->p_data_orig );
2602 if( p_pic && p_pic->p_sys ) free( p_pic->p_sys );
2603 if( p_pic ) free( p_pic );
2606 static void video_del_buffer_decoder( decoder_t *p_decoder, picture_t *p_pic )
2608 p_pic->i_refcount = 0;
2609 p_pic->i_status = DESTROYED_PICTURE;
2612 static void video_del_buffer_filter( filter_t *p_filter, picture_t *p_pic )
2614 p_pic->i_refcount = 0;
2615 p_pic->i_status = DESTROYED_PICTURE;
2618 static void video_link_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2620 p_pic->i_refcount++;
2623 static void video_unlink_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2625 video_release_buffer( p_pic );
2631 static subpicture_t *spu_new_buffer( decoder_t * );
2632 static void spu_del_buffer( decoder_t *, subpicture_t * );
2634 static int transcode_spu_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2636 sout_stream_sys_t *p_sys = p_stream->p_sys;
2642 /* Initialization of decoder structures */
2643 id->p_decoder->pf_spu_buffer_new = spu_new_buffer;
2644 id->p_decoder->pf_spu_buffer_del = spu_del_buffer;
2645 id->p_decoder->p_owner = (decoder_owner_sys_t *)p_stream;
2646 /* id->p_decoder->p_cfg = p_sys->p_spu_cfg; */
2648 id->p_decoder->p_module =
2649 module_Need( id->p_decoder, "decoder", "$codec", 0 );
2651 if( !id->p_decoder->p_module )
2653 msg_Err( p_stream, "cannot find decoder" );
2654 return VLC_EGENERIC;
2657 if( !p_sys->b_soverlay )
2660 /* Initialization of encoder format structures */
2661 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
2662 id->p_decoder->fmt_in.i_codec );
2664 id->p_encoder->p_cfg = p_sys->p_spu_cfg;
2666 id->p_encoder->p_module =
2667 module_Need( id->p_encoder, "encoder", p_sys->psz_senc, VLC_TRUE );
2669 if( !id->p_encoder->p_module )
2671 module_Unneed( id->p_decoder, id->p_decoder->p_module );
2672 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_senc );
2673 return VLC_EGENERIC;
2679 p_sys->p_spu = spu_Create( p_stream );
2680 spu_Init( p_sys->p_spu );
2686 static void transcode_spu_close( sout_stream_t *p_stream, sout_stream_id_t *id)
2689 if( id->p_decoder->p_module )
2690 module_Unneed( id->p_decoder, id->p_decoder->p_module );
2693 if( id->p_encoder->p_module )
2694 module_Unneed( id->p_encoder, id->p_encoder->p_module );
2697 static int transcode_spu_process( sout_stream_t *p_stream,
2698 sout_stream_id_t *id,
2699 block_t *in, block_t **out )
2701 sout_stream_sys_t *p_sys = p_stream->p_sys;
2702 subpicture_t *p_subpic;
2705 p_subpic = id->p_decoder->pf_decode_sub( id->p_decoder, &in );
2706 if( !p_subpic ) return VLC_EGENERIC;
2708 if( p_sys->b_master_sync && p_sys->i_master_drift )
2710 p_subpic->i_start -= p_sys->i_master_drift;
2711 if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2714 if( p_sys->b_soverlay )
2716 spu_DisplaySubpicture( p_sys->p_spu, p_subpic );
2722 p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
2723 spu_del_buffer( id->p_decoder, p_subpic );
2727 block_ChainAppend( out, p_block );
2732 return VLC_EGENERIC;
2735 static subpicture_t *spu_new_buffer( decoder_t *p_dec )
2737 sout_stream_t *p_stream = (sout_stream_t *)p_dec->p_owner;
2738 return spu_CreateSubpicture( p_stream->p_sys->p_spu );
2741 static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_subpic )
2743 sout_stream_t *p_stream = (sout_stream_t *)p_dec->p_owner;
2744 spu_DestroySubpicture( p_stream->p_sys->p_spu, p_subpic );
2750 static int transcode_osd_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2752 sout_stream_sys_t *p_sys = p_stream->p_sys;
2756 fmt.i_id = 0xbd1f; /* pid ?? */
2757 fmt.i_group = 3; /* pmt entry ?? */
2758 fmt.i_codec = VLC_FOURCC( 'Y', 'U', 'V', 'A' );
2759 fmt.psz_language = strdup( "osd" );
2761 id = malloc( sizeof( sout_stream_id_t ) );
2762 memset( id, 0, sizeof(sout_stream_id_t) );
2765 id->p_decoder = NULL;
2766 id->p_encoder = NULL;
2768 /* Create encoder object */
2769 id->p_encoder = vlc_object_create( p_stream, VLC_OBJECT_ENCODER );
2770 if( !id->p_encoder )
2772 msg_Err( p_stream, "out of memory" );
2775 vlc_object_attach( id->p_encoder, p_stream );
2776 id->p_encoder->p_module = NULL;
2778 /* Create fake destination format */
2779 es_format_Init( &id->p_encoder->fmt_out, fmt.i_cat, 0 );
2780 id->p_encoder->fmt_out.i_id = fmt.i_id;
2781 id->p_encoder->fmt_out.i_group = fmt.i_group;
2782 id->p_encoder->fmt_out.psz_language = strdup( fmt.psz_language );
2784 if( p_sys->i_osdcodec != 0 || p_sys->psz_osdenc )
2786 msg_Dbg( p_stream, "creating osdmenu transcoding from fcc=`%4.4s' "
2787 "to fcc=`%4.4s'", (char*)&fmt.i_codec,
2788 (char*)&p_sys->i_osdcodec );
2790 /* Complete destination format */
2791 id->p_encoder->fmt_out.i_codec = p_sys->i_osdcodec;
2794 /* Initialization of encoder format structures */
2795 es_format_Init( &id->p_encoder->fmt_in, fmt.i_cat, fmt.i_codec );
2796 id->p_encoder->fmt_in.psz_language = strdup( fmt.psz_language );
2798 id->p_encoder->p_cfg = p_sys->p_osd_cfg;
2800 id->p_encoder->p_module =
2801 module_Need( id->p_encoder, "encoder", p_sys->psz_osdenc, VLC_TRUE );
2803 if( !id->p_encoder->p_module )
2805 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_osdenc );
2809 /* open output stream */
2810 id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
2811 id->b_transcode = VLC_TRUE;
2813 if( !id->id ) goto error;
2817 msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
2818 (char*)&fmt.i_codec );
2819 id->id = p_sys->p_out->pf_add( p_sys->p_out, &fmt );
2820 id->b_transcode = VLC_FALSE;
2822 if( !id->id ) goto error;
2826 p_sys->b_es_osd = VLC_TRUE;
2830 p_sys->p_spu = spu_Create( p_stream );
2831 if( spu_Init( p_sys->p_spu ) != VLC_SUCCESS )
2832 msg_Err( p_sys, "spu initialisation failed" );
2835 if( fmt.psz_language )
2836 free( fmt.psz_language );
2841 msg_Err( p_stream, "starting osd encoding thread failed" );
2842 if( id->p_encoder->p_module )
2843 module_Unneed( id->p_encoder, id->p_encoder->p_module );
2846 vlc_object_detach( id->p_encoder );
2847 vlc_object_destroy( id->p_encoder );
2849 if( fmt.psz_language ) free( fmt.psz_language );
2850 if( id ) free( id );
2851 p_sys->id_osd = NULL;
2852 p_sys->b_es_osd = VLC_FALSE;
2853 return VLC_EGENERIC;
2856 static void transcode_osd_close( sout_stream_t *p_stream, sout_stream_id_t *id)
2858 sout_stream_sys_t *p_sys = p_stream->p_sys;
2861 if( p_sys->b_es_osd && id )
2863 if( id->p_encoder->p_module )
2864 module_Unneed( id->p_encoder, id->p_encoder->p_module );
2866 if( id->id ) p_sys->p_out->pf_del( p_sys->p_out, id->id );
2870 vlc_object_detach( id->p_encoder );
2871 vlc_object_destroy( id->p_encoder );
2874 p_sys->b_es_osd = VLC_FALSE;
2875 if( id ) free( id );
2878 static int transcode_osd_process( sout_stream_t *p_stream,
2879 sout_stream_id_t *id,
2880 block_t *in, block_t **out )
2882 sout_stream_sys_t *p_sys = p_stream->p_sys;
2883 subpicture_t *p_subpic = NULL;
2885 /* Check if we have a subpicture to send */
2886 if( p_sys->p_spu && in->i_dts > 0)
2888 p_subpic = spu_SortSubpictures( p_sys->p_spu, in->i_dts, VLC_FALSE );
2892 msg_Warn( p_stream, "spu channel not initialized, doing it now" );
2895 p_sys->p_spu = spu_Create( p_stream );
2896 if( spu_Init( p_sys->p_spu ) != VLC_SUCCESS )
2897 msg_Err( p_stream, "spu initialisation failed" );
2903 block_t *p_block = NULL;
2905 if( p_sys->b_master_sync && p_sys->i_master_drift )
2907 p_subpic->i_start -= p_sys->i_master_drift;
2908 if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2911 p_block = p_sys->id_osd->p_encoder->pf_encode_sub( p_sys->id_osd->p_encoder, p_subpic );
2914 p_block->i_dts = p_block->i_pts = in->i_dts;
2915 block_ChainAppend( out, p_block );
2918 if( p_sys->p_out->pf_send( p_sys->p_out, p_sys->id_osd->id, *out ) == VLC_SUCCESS )
2919 spu_DestroySubpicture( p_sys->p_spu, p_subpic );
2924 return VLC_EGENERIC;