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 coded 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_cat( SOUT_CFG_PREFIX "vfilter", SUBCAT_VIDEO_VFILTER2,
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 sout_cfg_t *p_audio_cfg;
379 char *psz_afilters[TRANSCODE_FILTERS];
380 sout_cfg_t *p_afilters_cfg[TRANSCODE_FILTERS];
384 vlc_fourcc_t i_vcodec; /* codec video (0 if not transcode) */
386 sout_cfg_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 sout_cfg_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 sout_cfg_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 sout_cfg_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 sout_cfg_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 sout_CfgParse( 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 = sout_CfgCreate( &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 )
518 if( (strncmp( (char *)&p_sys->i_acodec, "mp3", 3) == 0) &&
519 (p_sys->i_channels > 2) )
521 msg_Warn( p_stream, "%d channels invalid for mp3, forcing to 2",
523 p_sys->i_channels = 2;
526 msg_Dbg( p_stream, "codec audio=%4.4s %dHz %d channels %dKb/s",
527 (char *)&p_sys->i_acodec, p_sys->i_sample_rate,
528 p_sys->i_channels, p_sys->i_abitrate / 1000 );
531 var_Get( p_stream, SOUT_CFG_PREFIX "afilter", &val );
532 p_sys->i_afilters = 0;
533 if( val.psz_string && *val.psz_string )
535 char *psz_parser = val.psz_string;
537 while( (psz_parser != NULL) && (*psz_parser != '\0')
538 && (p_sys->i_afilters < TRANSCODE_FILTERS) )
540 psz_parser = sout_CfgCreate(
541 &p_sys->psz_afilters[p_sys->i_afilters],
542 &p_sys->p_afilters_cfg[p_sys->i_afilters],
545 if( (psz_parser != NULL) && (*psz_parser != '\0') ) psz_parser++;
548 if( val.psz_string ) free( val.psz_string );
549 if( p_sys->i_afilters < TRANSCODE_FILTERS-1 )
551 p_sys->psz_afilters[p_sys->i_afilters] = NULL;
552 p_sys->p_afilters_cfg[p_sys->i_afilters] = NULL;
555 /* Video transcoding parameters */
556 var_Get( p_stream, SOUT_CFG_PREFIX "venc", &val );
557 p_sys->psz_venc = NULL;
558 p_sys->p_video_cfg = NULL;
559 if( val.psz_string && *val.psz_string )
562 psz_next = sout_CfgCreate( &p_sys->psz_venc, &p_sys->p_video_cfg,
564 if( psz_next ) free( psz_next );
566 if( val.psz_string ) free( val.psz_string );
568 var_Get( p_stream, SOUT_CFG_PREFIX "vcodec", &val );
570 if( val.psz_string && *val.psz_string )
573 memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
574 p_sys->i_vcodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
576 if( val.psz_string ) free( val.psz_string );
578 var_Get( p_stream, SOUT_CFG_PREFIX "vb", &val );
579 p_sys->i_vbitrate = val.i_int;
580 if( p_sys->i_vbitrate < 16000 ) p_sys->i_vbitrate *= 1000;
582 var_Get( p_stream, SOUT_CFG_PREFIX "scale", &val );
583 p_sys->f_scale = val.f_float;
585 var_Get( p_stream, SOUT_CFG_PREFIX "fps", &val );
586 p_sys->f_fps = val.f_float;
588 var_Get( p_stream, SOUT_CFG_PREFIX "hurry-up", &val );
589 p_sys->b_hurry_up = val.b_bool;
591 var_Get( p_stream, SOUT_CFG_PREFIX "width", &val );
592 p_sys->i_width = val.i_int;
594 var_Get( p_stream, SOUT_CFG_PREFIX "height", &val );
595 p_sys->i_height = val.i_int;
597 var_Get( p_stream, SOUT_CFG_PREFIX "maxwidth", &val );
598 p_sys->i_maxwidth = val.i_int;
600 var_Get( p_stream, SOUT_CFG_PREFIX "maxheight", &val );
601 p_sys->i_maxheight = val.i_int;
603 var_Get( p_stream, SOUT_CFG_PREFIX "vfilter", &val );
604 p_sys->i_vfilters = 0;
605 if( val.psz_string && *val.psz_string )
607 char *psz_parser = val.psz_string;
609 while( (psz_parser != NULL) && (*psz_parser != '\0')
610 && (p_sys->i_vfilters < TRANSCODE_FILTERS) )
612 psz_parser = sout_CfgCreate(
613 &p_sys->psz_vfilters[p_sys->i_vfilters],
614 &p_sys->p_vfilters_cfg[p_sys->i_vfilters],
617 if( psz_parser != NULL && *psz_parser != '\0' ) psz_parser++;
620 if( val.psz_string ) free( val.psz_string );
621 if( p_sys->i_vfilters < TRANSCODE_FILTERS-1 )
623 p_sys->psz_vfilters[p_sys->i_vfilters] = NULL;
624 p_sys->p_vfilters_cfg[p_sys->i_vfilters] = NULL;
627 var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace", &val );
628 p_sys->b_deinterlace = val.b_bool;
630 var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace-module", &val );
631 p_sys->psz_deinterlace = NULL;
632 p_sys->p_deinterlace_cfg = NULL;
633 if( val.psz_string && *val.psz_string )
636 psz_next = sout_CfgCreate( &p_sys->psz_deinterlace,
637 &p_sys->p_deinterlace_cfg,
639 if( psz_next ) free( psz_next );
641 if( val.psz_string ) free( val.psz_string );
643 var_Get( p_stream, SOUT_CFG_PREFIX "croptop", &val );
644 p_sys->i_crop_top = val.i_int;
645 var_Get( p_stream, SOUT_CFG_PREFIX "cropbottom", &val );
646 p_sys->i_crop_bottom = val.i_int;
647 var_Get( p_stream, SOUT_CFG_PREFIX "cropleft", &val );
648 p_sys->i_crop_left = val.i_int;
649 var_Get( p_stream, SOUT_CFG_PREFIX "cropright", &val );
650 p_sys->i_crop_right = val.i_int;
652 var_Get( p_stream, SOUT_CFG_PREFIX "paddtop", &val );
653 p_sys->i_padd_top = val.i_int;
654 var_Get( p_stream, SOUT_CFG_PREFIX "paddbottom", &val );
655 p_sys->i_padd_bottom = val.i_int;
656 var_Get( p_stream, SOUT_CFG_PREFIX "paddleft", &val );
657 p_sys->i_padd_left = val.i_int;
658 var_Get( p_stream, SOUT_CFG_PREFIX "paddright", &val );
659 p_sys->i_padd_right = val.i_int;
661 var_Get( p_stream, SOUT_CFG_PREFIX "canvas-width", &val );
662 p_sys->i_canvas_width = val.i_int;
663 var_Get( p_stream, SOUT_CFG_PREFIX "canvas-height", &val );
664 p_sys->i_canvas_height = val.i_int;
666 var_Get( p_stream, SOUT_CFG_PREFIX "canvas-aspect", &val );
667 if ( val.psz_string )
669 char *psz_parser = strchr( val.psz_string, ':' );
673 *psz_parser++ = '\0';
674 p_sys->i_canvas_aspect = atoi( val.psz_string ) * VOUT_ASPECT_FACTOR
675 / atoi( psz_parser );
679 msg_Warn( p_stream, "bad aspect ratio %s", val.psz_string );
680 p_sys->i_canvas_aspect = 0;
683 free( val.psz_string );
687 p_sys->i_canvas_aspect = 0;
690 var_Get( p_stream, SOUT_CFG_PREFIX "threads", &val );
691 p_sys->i_threads = val.i_int;
692 var_Get( p_stream, SOUT_CFG_PREFIX "high-priority", &val );
693 p_sys->b_high_priority = val.b_bool;
695 if( p_sys->i_vcodec )
697 msg_Dbg( p_stream, "codec video=%4.4s %dx%d scaling: %f %dkb/s",
698 (char *)&p_sys->i_vcodec, p_sys->i_width, p_sys->i_height,
699 p_sys->f_scale, p_sys->i_vbitrate / 1000 );
702 /* Subpictures transcoding parameters */
704 p_sys->psz_senc = NULL;
705 p_sys->p_spu_cfg = NULL;
708 var_Get( p_stream, SOUT_CFG_PREFIX "senc", &val );
709 if( val.psz_string && *val.psz_string )
712 psz_next = sout_CfgCreate( &p_sys->psz_senc, &p_sys->p_spu_cfg,
714 if( psz_next ) free( psz_next );
716 if( val.psz_string ) free( val.psz_string );
718 var_Get( p_stream, SOUT_CFG_PREFIX "scodec", &val );
719 if( val.psz_string && *val.psz_string )
722 memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
723 p_sys->i_scodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
725 if( val.psz_string ) free( val.psz_string );
727 if( p_sys->i_scodec )
729 msg_Dbg( p_stream, "codec spu=%4.4s", (char *)&p_sys->i_scodec );
732 var_Get( p_stream, SOUT_CFG_PREFIX "soverlay", &val );
733 p_sys->b_soverlay = val.b_bool;
735 var_Get( p_stream, SOUT_CFG_PREFIX "sfilter", &val );
736 if( val.psz_string && *val.psz_string )
738 p_sys->p_spu = spu_Create( p_stream );
739 var_Create( p_sys->p_spu, "sub-filter", VLC_VAR_STRING );
740 var_Set( p_sys->p_spu, "sub-filter", val );
741 spu_Init( p_sys->p_spu );
743 if( val.psz_string ) free( val.psz_string );
745 /* OSD menu transcoding parameters */
746 p_sys->psz_osdenc = NULL;
747 p_sys->p_osd_cfg = NULL;
748 p_sys->i_osdcodec = 0;
749 p_sys->b_es_osd = VLC_FALSE;
751 var_Get( p_stream, SOUT_CFG_PREFIX "osd", &val );
752 p_sys->b_sout_osd = val.b_bool;
753 if( p_sys->b_sout_osd )
758 psz_next = sout_CfgCreate( &p_sys->psz_osdenc,
759 &p_sys->p_osd_cfg, strdup( "dvbsub") );
760 if( psz_next ) free( psz_next );
762 p_sys->i_osdcodec = VLC_FOURCC('Y','U','V','P' );
764 msg_Dbg( p_stream, "codec osd=%4.4s", (char *)&p_sys->i_osdcodec );
768 osd_val.psz_string = strdup("osdmenu");
769 p_sys->p_spu = spu_Create( p_stream );
770 var_Create( p_sys->p_spu, "sub-filter", VLC_VAR_STRING );
771 var_Set( p_sys->p_spu, "sub-filter", osd_val );
772 spu_Init( p_sys->p_spu );
773 if( osd_val.psz_string ) free( osd_val.psz_string );
777 osd_val.psz_string = strdup("osdmenu");
778 var_Set( p_sys->p_spu, "sub-filter", osd_val );
779 if( osd_val.psz_string ) free( osd_val.psz_string );
784 var_Get( p_stream, SOUT_CFG_PREFIX "audio-sync", &val );
785 p_sys->b_master_sync = val.b_bool;
786 if( p_sys->f_fps > 0 ) p_sys->b_master_sync = VLC_TRUE;
788 p_stream->pf_add = Add;
789 p_stream->pf_del = Del;
790 p_stream->pf_send = Send;
791 p_stream->p_sys = p_sys;
796 /*****************************************************************************
798 *****************************************************************************/
799 static void Close( vlc_object_t * p_this )
801 sout_stream_t *p_stream = (sout_stream_t*)p_this;
802 sout_stream_sys_t *p_sys = p_stream->p_sys;
804 sout_StreamDelete( p_sys->p_out );
806 while( p_sys->p_audio_cfg != NULL )
808 sout_cfg_t *p_next = p_sys->p_audio_cfg->p_next;
810 if( p_sys->p_audio_cfg->psz_name )
811 free( p_sys->p_audio_cfg->psz_name );
812 if( p_sys->p_audio_cfg->psz_value )
813 free( p_sys->p_audio_cfg->psz_value );
814 free( p_sys->p_audio_cfg );
816 p_sys->p_audio_cfg = p_next;
818 if( p_sys->psz_aenc ) free( p_sys->psz_aenc );
820 while( p_sys->p_video_cfg != NULL )
822 sout_cfg_t *p_next = p_sys->p_video_cfg->p_next;
824 if( p_sys->p_video_cfg->psz_name )
825 free( p_sys->p_video_cfg->psz_name );
826 if( p_sys->p_video_cfg->psz_value )
827 free( p_sys->p_video_cfg->psz_value );
828 free( p_sys->p_video_cfg );
830 p_sys->p_video_cfg = p_next;
832 if( p_sys->psz_venc ) free( p_sys->psz_venc );
834 while( p_sys->p_deinterlace_cfg != NULL )
836 sout_cfg_t *p_next = p_sys->p_deinterlace_cfg->p_next;
838 if( p_sys->p_deinterlace_cfg->psz_name )
839 free( p_sys->p_deinterlace_cfg->psz_name );
840 if( p_sys->p_deinterlace_cfg->psz_value )
841 free( p_sys->p_deinterlace_cfg->psz_value );
842 free( p_sys->p_deinterlace_cfg );
844 p_sys->p_deinterlace_cfg = p_next;
846 if( p_sys->psz_deinterlace ) free( p_sys->psz_deinterlace );
848 while( p_sys->p_spu_cfg != NULL )
850 sout_cfg_t *p_next = p_sys->p_spu_cfg->p_next;
852 if( p_sys->p_spu_cfg->psz_name )
853 free( p_sys->p_spu_cfg->psz_name );
854 if( p_sys->p_spu_cfg->psz_value )
855 free( p_sys->p_spu_cfg->psz_value );
856 free( p_sys->p_spu_cfg );
858 p_sys->p_spu_cfg = p_next;
860 if( p_sys->psz_senc ) free( p_sys->psz_senc );
862 if( p_sys->p_spu ) spu_Destroy( p_sys->p_spu );
864 while( p_sys->p_osd_cfg != NULL )
866 sout_cfg_t *p_next = p_sys->p_osd_cfg->p_next;
868 if( p_sys->p_osd_cfg->psz_name )
869 free( p_sys->p_osd_cfg->psz_name );
870 if( p_sys->p_osd_cfg->psz_value )
871 free( p_sys->p_osd_cfg->psz_value );
872 free( p_sys->p_osd_cfg );
874 p_sys->p_osd_cfg = p_next;
876 if( p_sys->psz_osdenc ) free( p_sys->psz_osdenc );
878 vlc_object_destroy( p_sys );
881 struct sout_stream_id_t
883 vlc_fourcc_t b_transcode;
885 /* id of the out stream */
889 decoder_t *p_decoder;
892 filter_t *pp_filter[TRANSCODE_FILTERS];
894 /* User specified filters */
895 filter_t *pp_ufilter[TRANSCODE_FILTERS];
899 encoder_t *p_encoder;
902 date_t interpolated_pts;
905 static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
907 sout_stream_sys_t *p_sys = p_stream->p_sys;
908 sout_stream_id_t *id;
910 id = malloc( sizeof( sout_stream_id_t ) );
911 memset( id, 0, sizeof(sout_stream_id_t) );
914 id->p_decoder = NULL;
915 id->p_encoder = NULL;
917 /* Create decoder object */
918 id->p_decoder = vlc_object_create( p_stream, VLC_OBJECT_DECODER );
921 msg_Err( p_stream, "out of memory" );
924 vlc_object_attach( id->p_decoder, p_stream );
925 id->p_decoder->p_module = NULL;
926 id->p_decoder->fmt_in = *p_fmt;
927 id->p_decoder->b_pace_control = VLC_TRUE;
929 /* Create encoder object */
930 id->p_encoder = vlc_object_create( p_stream, VLC_OBJECT_ENCODER );
933 msg_Err( p_stream, "out of memory" );
936 vlc_object_attach( id->p_encoder, p_stream );
937 id->p_encoder->p_module = NULL;
939 /* Create destination format */
940 es_format_Init( &id->p_encoder->fmt_out, p_fmt->i_cat, 0 );
941 id->p_encoder->fmt_out.i_id = p_fmt->i_id;
942 id->p_encoder->fmt_out.i_group = p_fmt->i_group;
943 if( p_fmt->psz_language )
944 id->p_encoder->fmt_out.psz_language = strdup( p_fmt->psz_language );
946 if( p_fmt->i_cat == AUDIO_ES && (p_sys->i_acodec || p_sys->psz_aenc) )
949 "creating audio transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
950 (char*)&p_fmt->i_codec, (char*)&p_sys->i_acodec );
952 /* Complete destination format */
953 id->p_encoder->fmt_out.i_codec = p_sys->i_acodec;
954 id->p_encoder->fmt_out.audio.i_rate = p_sys->i_sample_rate > 0 ?
955 p_sys->i_sample_rate : (int)p_fmt->audio.i_rate;
956 id->p_encoder->fmt_out.i_bitrate = p_sys->i_abitrate;
957 id->p_encoder->fmt_out.audio.i_bitspersample =
958 p_fmt->audio.i_bitspersample;
959 id->p_encoder->fmt_out.audio.i_channels = p_sys->i_channels > 0 ?
960 p_sys->i_channels : p_fmt->audio.i_channels;
961 /* Sanity check for audio channels */
962 id->p_encoder->fmt_out.audio.i_channels =
963 __MIN( id->p_encoder->fmt_out.audio.i_channels,
964 id->p_decoder->fmt_in.audio.i_channels );
965 id->p_encoder->fmt_out.audio.i_original_channels =
966 id->p_decoder->fmt_in.audio.i_physical_channels;
967 if( id->p_decoder->fmt_in.audio.i_channels ==
968 id->p_encoder->fmt_out.audio.i_channels )
970 id->p_encoder->fmt_out.audio.i_physical_channels =
971 id->p_decoder->fmt_in.audio.i_physical_channels;
975 id->p_encoder->fmt_out.audio.i_physical_channels =
976 pi_channels_maps[id->p_encoder->fmt_out.audio.i_channels];
979 /* Build decoder -> filter -> encoder chain */
980 if( transcode_audio_new( p_stream, id ) )
982 msg_Err( p_stream, "cannot create audio chain" );
986 /* Open output stream */
987 id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
988 id->b_transcode = VLC_TRUE;
992 transcode_audio_close( p_stream, id );
996 date_Init( &id->interpolated_pts, p_fmt->audio.i_rate, 1 );
998 else if( p_fmt->i_cat == VIDEO_ES &&
999 (p_sys->i_vcodec != 0 || p_sys->psz_venc) )
1002 "creating video transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
1003 (char*)&p_fmt->i_codec, (char*)&p_sys->i_vcodec );
1005 /* Complete destination format */
1006 id->p_encoder->fmt_out.i_codec = p_sys->i_vcodec;
1007 id->p_encoder->fmt_out.video.i_width = p_sys->i_width & ~1;
1008 id->p_encoder->fmt_out.video.i_height = p_sys->i_height & ~1;
1009 id->p_encoder->fmt_out.i_bitrate = p_sys->i_vbitrate;
1011 /* Build decoder -> filter -> encoder chain */
1012 if( transcode_video_new( p_stream, id ) )
1014 msg_Err( p_stream, "cannot create video chain" );
1018 /* Stream will be added later on because we don't know
1019 * all the characteristics of the decoded stream yet */
1020 id->b_transcode = VLC_TRUE;
1022 if( p_sys->f_fps > 0 )
1024 id->p_encoder->fmt_out.video.i_frame_rate =
1025 (p_sys->f_fps * 1001) + 0.5;
1026 id->p_encoder->fmt_out.video.i_frame_rate_base = 1001;
1029 else if( p_fmt->i_cat == SPU_ES && (p_sys->i_scodec || p_sys->psz_senc) )
1031 msg_Dbg( p_stream, "creating subtitles transcoding from fcc=`%4.4s' "
1032 "to fcc=`%4.4s'", (char*)&p_fmt->i_codec,
1033 (char*)&p_sys->i_scodec );
1035 /* Complete destination format */
1036 id->p_encoder->fmt_out.i_codec = p_sys->i_scodec;
1038 /* build decoder -> filter -> encoder */
1039 if( transcode_spu_new( p_stream, id ) )
1041 msg_Err( p_stream, "cannot create subtitles chain" );
1045 /* open output stream */
1046 id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
1047 id->b_transcode = VLC_TRUE;
1051 transcode_spu_close( p_stream, id );
1055 else if( p_fmt->i_cat == SPU_ES && p_sys->b_soverlay )
1057 msg_Dbg( p_stream, "subtitles (fcc=`%4.4s') overlaying",
1058 (char*)&p_fmt->i_codec );
1060 id->b_transcode = VLC_TRUE;
1062 /* Build decoder -> filter -> overlaying chain */
1063 if( transcode_spu_new( p_stream, id ) )
1065 msg_Err( p_stream, "cannot create subtitles chain" );
1071 msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
1072 (char*)&p_fmt->i_codec );
1073 id->id = p_sys->p_out->pf_add( p_sys->p_out, p_fmt );
1074 id->b_transcode = VLC_FALSE;
1076 if( !id->id ) goto error;
1079 if( p_sys->b_sout_osd )
1081 /* Create a fake OSD menu elementary stream */
1082 if( !p_sys->b_es_osd && (p_sys->i_osdcodec != 0 || p_sys->psz_osdenc) )
1084 if( transcode_osd_new( p_stream, p_sys->id_osd ) )
1086 msg_Err( p_stream, "cannot create osd chain" );
1089 p_sys->b_es_osd = VLC_TRUE;
1097 vlc_object_detach( id->p_decoder );
1098 vlc_object_destroy( id->p_decoder );
1103 vlc_object_detach( id->p_encoder );
1104 es_format_Clean( &id->p_encoder->fmt_out );
1105 vlc_object_destroy( id->p_encoder );
1112 static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
1114 sout_stream_sys_t *p_sys = p_stream->p_sys;
1116 if( p_sys->b_es_osd )
1117 transcode_osd_close( p_stream, p_sys->id_osd );
1119 if( id->b_transcode )
1121 switch( id->p_decoder->fmt_in.i_cat )
1124 transcode_audio_close( p_stream, id );
1127 transcode_video_close( p_stream, id );
1130 transcode_spu_close( p_stream, id );
1135 if( id->id ) p_sys->p_out->pf_del( p_sys->p_out, id->id );
1139 vlc_object_detach( id->p_decoder );
1140 vlc_object_destroy( id->p_decoder );
1145 vlc_object_detach( id->p_encoder );
1146 es_format_Clean( &id->p_encoder->fmt_out );
1147 vlc_object_destroy( id->p_encoder );
1155 static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
1158 sout_stream_sys_t *p_sys = p_stream->p_sys;
1159 block_t *p_out = NULL;
1161 if( !id->b_transcode && id->id )
1163 /* Transcode OSD menu pictures. */
1164 if( p_sys->b_es_osd )
1166 transcode_osd_process( p_stream, id, p_buffer, &p_out );
1168 return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_buffer );
1170 else if( !id->b_transcode )
1172 block_Release( p_buffer );
1173 return VLC_EGENERIC;
1176 switch( id->p_decoder->fmt_in.i_cat )
1179 transcode_audio_process( p_stream, id, p_buffer, &p_out );
1183 if( transcode_video_process( p_stream, id, p_buffer, &p_out )
1186 return VLC_EGENERIC;
1191 if( transcode_spu_process( p_stream, id, p_buffer, &p_out ) !=
1194 return VLC_EGENERIC;
1200 block_Release( p_buffer );
1204 if( p_out ) return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_out );
1208 /****************************************************************************
1209 * decoder reencoder part
1210 ****************************************************************************/
1211 int audio_BitsPerSample( vlc_fourcc_t i_format )
1215 case VLC_FOURCC('u','8',' ',' '):
1216 case VLC_FOURCC('s','8',' ',' '):
1219 case VLC_FOURCC('u','1','6','l'):
1220 case VLC_FOURCC('s','1','6','l'):
1221 case VLC_FOURCC('u','1','6','b'):
1222 case VLC_FOURCC('s','1','6','b'):
1225 case VLC_FOURCC('u','2','4','l'):
1226 case VLC_FOURCC('s','2','4','l'):
1227 case VLC_FOURCC('u','2','4','b'):
1228 case VLC_FOURCC('s','2','4','b'):
1231 case VLC_FOURCC('u','3','2','l'):
1232 case VLC_FOURCC('s','3','2','l'):
1233 case VLC_FOURCC('u','3','2','b'):
1234 case VLC_FOURCC('s','3','2','b'):
1235 case VLC_FOURCC('f','l','3','2'):
1236 case VLC_FOURCC('f','i','3','2'):
1239 case VLC_FOURCC('f','l','6','4'):
1246 static filter_t *transcode_audio_filter_new( sout_stream_t *p_stream,
1247 sout_stream_id_t *id,
1248 es_format_t *p_fmt_in,
1249 es_format_t *p_fmt_out,
1252 sout_stream_sys_t *p_sys = p_stream->p_sys;
1253 filter_t *p_filter = vlc_object_create( p_stream, VLC_OBJECT_FILTER );
1255 vlc_object_attach( p_filter, p_stream );
1256 p_filter->pf_audio_buffer_new = (block_t* (*) (filter_t*, int))__block_New;
1258 p_filter->fmt_in = *p_fmt_in;
1259 p_filter->fmt_out = *p_fmt_out;
1261 p_filter->p_cfg = p_sys->p_afilters_cfg[id->i_ufilter];
1263 p_filter->p_module = module_Need( p_filter, "audio filter2", psz_name, 0 );
1264 if( p_filter->p_module )
1266 p_filter->fmt_out.audio.i_bitspersample =
1267 audio_BitsPerSample( p_filter->fmt_out.i_codec );
1268 *p_fmt_in = p_filter->fmt_out;
1272 vlc_object_detach( p_filter );
1273 vlc_object_destroy( p_filter );
1280 static int transcode_audio_new( sout_stream_t *p_stream,
1281 sout_stream_id_t *id )
1283 sout_stream_sys_t *p_sys = p_stream->p_sys;
1284 es_format_t fmt_last;
1291 /* Initialization of decoder structures */
1292 id->p_decoder->fmt_out = id->p_decoder->fmt_in;
1293 id->p_decoder->fmt_out.i_extra = 0;
1294 id->p_decoder->fmt_out.p_extra = 0;
1295 id->p_decoder->pf_decode_audio = 0;
1296 id->p_decoder->pf_aout_buffer_new = audio_new_buffer;
1297 id->p_decoder->pf_aout_buffer_del = audio_del_buffer;
1298 /* id->p_decoder->p_cfg = p_sys->p_audio_cfg; */
1300 id->p_decoder->p_module =
1301 module_Need( id->p_decoder, "decoder", "$codec", 0 );
1303 if( !id->p_decoder->p_module )
1305 msg_Err( p_stream, "cannot find decoder" );
1306 return VLC_EGENERIC;
1308 id->p_decoder->fmt_out.audio.i_bitspersample =
1309 audio_BitsPerSample( id->p_decoder->fmt_out.i_codec );
1310 fmt_last = id->p_decoder->fmt_out;
1311 /* FIX decoders so we don't have to do this */
1312 fmt_last.audio.i_rate = id->p_decoder->fmt_in.audio.i_rate;
1318 /* Initialization of encoder format structures */
1319 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1320 id->p_decoder->fmt_out.i_codec );
1321 id->p_encoder->fmt_in.audio.i_format = id->p_decoder->fmt_out.i_codec;
1323 /* Initialization of encoder format structures */
1324 es_format_Init( &id->p_encoder->fmt_in, AUDIO_ES, AOUT_FMT_S16_NE );
1325 id->p_encoder->fmt_in.audio.i_format = AOUT_FMT_S16_NE;
1326 id->p_encoder->fmt_in.audio.i_rate = id->p_encoder->fmt_out.audio.i_rate;
1327 id->p_encoder->fmt_in.audio.i_physical_channels =
1328 id->p_encoder->fmt_out.audio.i_physical_channels;
1329 id->p_encoder->fmt_in.audio.i_original_channels =
1330 id->p_encoder->fmt_out.audio.i_original_channels;
1331 id->p_encoder->fmt_in.audio.i_channels =
1332 id->p_encoder->fmt_out.audio.i_channels;
1333 id->p_encoder->fmt_in.audio.i_bitspersample =
1334 audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1336 id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
1338 id->p_encoder->p_module =
1339 module_Need( id->p_encoder, "encoder", p_sys->psz_aenc, VLC_TRUE );
1340 if( !id->p_encoder->p_module )
1342 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_aenc );
1343 module_Unneed( id->p_decoder, id->p_decoder->p_module );
1344 id->p_decoder->p_module = 0;
1345 return VLC_EGENERIC;
1347 id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
1348 id->p_encoder->fmt_in.audio.i_bitspersample =
1349 audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1351 /* Load conversion filters */
1352 if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels ||
1353 fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate )
1355 /* We'll have to go through fl32 first */
1356 es_format_t fmt_out = id->p_encoder->fmt_in;
1357 fmt_out.i_codec = fmt_out.audio.i_format = VLC_FOURCC('f','l','3','2');
1359 id->pp_filter[id->i_filter] =
1360 transcode_audio_filter_new( p_stream, id, &fmt_last, &fmt_out, NULL );
1362 if( id->pp_filter[id->i_filter] ) id->i_filter++;
1365 for( i = 0; i < TRANSCODE_FILTERS; i++ )
1367 if( (fmt_last.audio.i_channels !=
1368 id->p_encoder->fmt_in.audio.i_channels) ||
1369 (fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate) ||
1370 (fmt_last.i_codec != id->p_encoder->fmt_in.i_codec) )
1372 id->pp_filter[id->i_filter] =
1373 transcode_audio_filter_new( p_stream, id, &fmt_last,
1374 &id->p_encoder->fmt_in, NULL );
1376 if( id->pp_filter[id->i_filter] )
1383 /* Final checks to see if conversions were successful */
1384 if( fmt_last.i_codec != id->p_encoder->fmt_in.i_codec )
1386 msg_Err( p_stream, "no audio filter found (%4.4s->%4.4s)",
1387 (char *)&fmt_last.i_codec,
1388 (char *)&id->p_encoder->fmt_in.i_codec );
1389 transcode_audio_close( p_stream, id );
1390 return VLC_EGENERIC;
1393 /* Load user specified audio filters now */
1394 for( i = 0; (i < p_sys->i_afilters) &&
1395 (id->i_ufilter < TRANSCODE_FILTERS); i++ )
1397 id->pp_ufilter[id->i_ufilter] =
1398 transcode_audio_filter_new( p_stream, id, &fmt_last,
1399 &id->p_encoder->fmt_in,
1400 p_sys->psz_afilters[i] );
1402 if( id->pp_ufilter[id->i_ufilter] )
1408 if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels )
1410 msg_Err( p_stream, "no audio filter found for mixing from"
1411 " %i to %i channels", fmt_last.audio.i_channels,
1412 id->p_encoder->fmt_in.audio.i_channels );
1414 /* FIXME : this might work, but only if the encoder is restarted */
1415 id->p_encoder->fmt_in.audio.i_channels = fmt_last.audio.i_channels;
1416 id->p_encoder->fmt_out.audio.i_channels = fmt_last.audio.i_channels;
1418 id->p_encoder->fmt_in.audio.i_physical_channels =
1419 id->p_encoder->fmt_in.audio.i_original_channels =
1420 fmt_last.audio.i_physical_channels;
1421 id->p_encoder->fmt_out.audio.i_physical_channels =
1422 id->p_encoder->fmt_out.audio.i_original_channels =
1423 fmt_last.audio.i_physical_channels;
1425 transcode_audio_close( p_stream, id );
1426 return VLC_EGENERIC;
1430 if( fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate )
1432 msg_Err( p_stream, "no audio filter found for resampling from"
1433 " %iHz to %iHz", fmt_last.audio.i_rate,
1434 id->p_encoder->fmt_in.audio.i_rate );
1436 /* FIXME : this might work, but only if the encoder is restarted */
1437 id->p_encoder->fmt_in.audio.i_rate = fmt_last.audio.i_rate;
1438 id->p_encoder->fmt_out.audio.i_rate = fmt_last.audio.i_rate;
1440 transcode_audio_close( p_stream, id );
1441 return VLC_EGENERIC;
1445 /* FIXME: Hack for mp3 transcoding support */
1446 if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC( 'm','p','3',' ' ) )
1447 id->p_encoder->fmt_out.i_codec = VLC_FOURCC( 'm','p','g','a' );
1452 static void transcode_audio_close( sout_stream_t *p_stream,
1453 sout_stream_id_t *id )
1458 if( id->p_decoder->p_module )
1459 module_Unneed( id->p_decoder, id->p_decoder->p_module );
1460 id->p_decoder->p_module = 0;
1463 if( id->p_encoder->p_module )
1464 module_Unneed( id->p_encoder, id->p_encoder->p_module );
1465 id->p_encoder->p_module = 0;
1468 for( i = 0; i < id->i_filter; i++ )
1470 vlc_object_detach( id->pp_filter[i] );
1471 if( id->pp_filter[i]->p_module )
1472 module_Unneed( id->pp_filter[i], id->pp_filter[i]->p_module );
1473 vlc_object_destroy( id->pp_filter[i] );
1475 for( i = 0; i < id->i_ufilter; i++ )
1477 vlc_object_detach( id->pp_ufilter[i] );
1478 if( id->pp_ufilter[i]->p_module )
1479 module_Unneed( id->pp_ufilter[i], id->pp_ufilter[i]->p_module );
1480 vlc_object_destroy( id->pp_ufilter[i] );
1484 static int transcode_audio_process( sout_stream_t *p_stream,
1485 sout_stream_id_t *id,
1486 block_t *in, block_t **out )
1488 sout_stream_sys_t *p_sys = p_stream->p_sys;
1489 aout_buffer_t *p_audio_buf;
1490 block_t *p_block, *p_audio_block;
1493 input_thread_t *p_input = NULL;
1495 if( p_stream->p_parent->p_parent && p_stream->p_parent->p_parent->
1496 i_object_type == VLC_OBJECT_INPUT )
1497 p_input = (input_thread_t *)p_stream->p_parent->p_parent;
1499 while( (p_audio_buf = id->p_decoder->pf_decode_audio( id->p_decoder,
1503 stats_UpdateInteger( p_input, p_input->counters.p_decoded_audio,
1505 if( p_sys->b_master_sync )
1507 mtime_t i_dts = date_Get( &id->interpolated_pts ) + 1;
1508 if ( p_audio_buf->start_date - i_dts > MASTER_SYNC_MAX_DRIFT
1509 || p_audio_buf->start_date - i_dts < -MASTER_SYNC_MAX_DRIFT )
1511 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
1512 date_Set( &id->interpolated_pts, p_audio_buf->start_date );
1513 i_dts = p_audio_buf->start_date + 1;
1515 p_sys->i_master_drift = p_audio_buf->start_date - i_dts;
1516 date_Increment( &id->interpolated_pts, p_audio_buf->i_nb_samples );
1517 p_audio_buf->start_date -= p_sys->i_master_drift;
1518 p_audio_buf->end_date -= p_sys->i_master_drift;
1521 p_audio_block = p_audio_buf->p_sys;
1522 p_audio_block->i_buffer = p_audio_buf->i_nb_bytes;
1523 p_audio_block->i_dts = p_audio_block->i_pts =
1524 p_audio_buf->start_date;
1525 p_audio_block->i_length = p_audio_buf->end_date -
1526 p_audio_buf->start_date;
1527 p_audio_block->i_samples = p_audio_buf->i_nb_samples;
1529 /* Run filter chain */
1530 for( i = 0; i < id->i_filter; i++ )
1533 id->pp_filter[i]->pf_audio_filter( id->pp_filter[i],
1537 /* Run user specified filter chain */
1538 for( i = 0; i < id->i_ufilter; i++ )
1541 id->pp_ufilter[i]->pf_audio_filter( id->pp_ufilter[i],
1545 p_audio_buf->p_buffer = p_audio_block->p_buffer;
1546 p_audio_buf->i_nb_bytes = p_audio_block->i_buffer;
1547 p_audio_buf->i_nb_samples = p_audio_block->i_samples;
1548 p_audio_buf->start_date = p_audio_block->i_dts;
1549 p_audio_buf->end_date = p_audio_block->i_dts + p_audio_block->i_length;
1551 p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf );
1552 block_ChainAppend( out, p_block );
1553 block_Release( p_audio_block );
1554 free( p_audio_buf );
1560 static void audio_release_buffer( aout_buffer_t *p_buffer )
1562 if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
1563 if( p_buffer ) free( p_buffer );
1566 static aout_buffer_t *audio_new_buffer( decoder_t *p_dec, int i_samples )
1568 aout_buffer_t *p_buffer;
1572 if( p_dec->fmt_out.audio.i_bitspersample )
1574 i_size = i_samples * p_dec->fmt_out.audio.i_bitspersample / 8 *
1575 p_dec->fmt_out.audio.i_channels;
1577 else if( p_dec->fmt_out.audio.i_bytes_per_frame &&
1578 p_dec->fmt_out.audio.i_frame_length )
1580 i_size = i_samples * p_dec->fmt_out.audio.i_bytes_per_frame /
1581 p_dec->fmt_out.audio.i_frame_length;
1585 i_size = i_samples * 4 * p_dec->fmt_out.audio.i_channels;
1588 p_buffer = malloc( sizeof(aout_buffer_t) );
1589 p_buffer->pf_release = audio_release_buffer;
1590 p_buffer->p_sys = p_block = block_New( p_dec, i_size );
1592 p_buffer->p_buffer = p_block->p_buffer;
1593 p_buffer->i_size = p_buffer->i_nb_bytes = p_block->i_buffer;
1594 p_buffer->i_nb_samples = i_samples;
1595 p_block->i_samples = i_samples;
1600 static void audio_del_buffer( decoder_t *p_dec, aout_buffer_t *p_buffer )
1602 if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
1603 if( p_buffer ) free( p_buffer );
1609 static int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_t *id )
1611 sout_stream_sys_t *p_sys = p_stream->p_sys;
1615 * Initialization of decoder structures
1617 id->p_decoder->fmt_out = id->p_decoder->fmt_in;
1618 id->p_decoder->fmt_out.i_extra = 0;
1619 id->p_decoder->fmt_out.p_extra = 0;
1620 id->p_decoder->pf_decode_video = 0;
1621 id->p_decoder->pf_vout_buffer_new = video_new_buffer_decoder;
1622 id->p_decoder->pf_vout_buffer_del = video_del_buffer_decoder;
1623 id->p_decoder->pf_picture_link = video_link_picture_decoder;
1624 id->p_decoder->pf_picture_unlink = video_unlink_picture_decoder;
1625 id->p_decoder->p_owner = malloc( sizeof(decoder_owner_sys_t) );
1626 for( i = 0; i < PICTURE_RING_SIZE; i++ )
1627 id->p_decoder->p_owner->pp_pics[i] = 0;
1628 id->p_decoder->p_owner->p_sys = p_sys;
1629 /* id->p_decoder->p_cfg = p_sys->p_video_cfg; */
1631 id->p_decoder->p_module =
1632 module_Need( id->p_decoder, "decoder", "$codec", 0 );
1634 if( !id->p_decoder->p_module )
1636 msg_Err( p_stream, "cannot find decoder" );
1637 return VLC_EGENERIC;
1642 * Because some info about the decoded input will only be available
1643 * once the first frame is decoded, we actually only test the availability
1644 * of the encoder here.
1647 /* Initialization of encoder format structures */
1648 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1649 id->p_decoder->fmt_out.i_codec );
1650 id->p_encoder->fmt_in.video.i_chroma = id->p_decoder->fmt_out.i_codec;
1652 /* The dimensions will be set properly later on.
1653 * Just put sensible values so we can test an encoder is available. */
1654 id->p_encoder->fmt_in.video.i_width =
1655 id->p_encoder->fmt_out.video.i_width ?
1656 id->p_encoder->fmt_out.video.i_width :
1657 id->p_decoder->fmt_in.video.i_width ?
1658 id->p_decoder->fmt_in.video.i_width : 16;
1659 id->p_encoder->fmt_in.video.i_height =
1660 id->p_encoder->fmt_out.video.i_height ?
1661 id->p_encoder->fmt_out.video.i_height :
1662 id->p_decoder->fmt_in.video.i_height ?
1663 id->p_decoder->fmt_in.video.i_height : 16;
1664 id->p_encoder->fmt_in.video.i_frame_rate = 25;
1665 id->p_encoder->fmt_in.video.i_frame_rate_base = 1;
1667 id->p_encoder->i_threads = p_sys->i_threads;
1668 id->p_encoder->p_cfg = p_sys->p_video_cfg;
1670 id->p_encoder->p_module =
1671 module_Need( id->p_encoder, "encoder", p_sys->psz_venc, VLC_TRUE );
1672 if( !id->p_encoder->p_module )
1674 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_venc );
1675 module_Unneed( id->p_decoder, id->p_decoder->p_module );
1676 id->p_decoder->p_module = 0;
1677 return VLC_EGENERIC;
1680 /* Close the encoder.
1681 * We'll open it only when we have the first frame. */
1682 module_Unneed( id->p_encoder, id->p_encoder->p_module );
1683 if( id->p_encoder->fmt_out.p_extra )
1684 free( id->p_encoder->fmt_out.p_extra );
1685 id->p_encoder->p_module = NULL;
1687 if( p_sys->i_threads >= 1 )
1689 int i_priority = p_sys->b_high_priority ? VLC_THREAD_PRIORITY_OUTPUT :
1690 VLC_THREAD_PRIORITY_VIDEO;
1691 p_sys->id_video = id;
1692 vlc_mutex_init( p_stream, &p_sys->lock_out );
1693 vlc_cond_init( p_stream, &p_sys->cond );
1694 memset( p_sys->pp_pics, 0, sizeof(p_sys->pp_pics) );
1695 p_sys->i_first_pic = 0;
1696 p_sys->i_last_pic = 0;
1697 p_sys->p_buffers = NULL;
1698 p_sys->b_die = p_sys->b_error = 0;
1699 if( vlc_thread_create( p_sys, "encoder", EncoderThread, i_priority,
1702 msg_Err( p_stream, "cannot spawn encoder thread" );
1703 module_Unneed( id->p_decoder, id->p_decoder->p_module );
1704 id->p_decoder->p_module = 0;
1705 return VLC_EGENERIC;
1712 static int transcode_video_encoder_open( sout_stream_t *p_stream,
1713 sout_stream_id_t *id )
1715 sout_stream_sys_t *p_sys = p_stream->p_sys;
1717 /* Calculate scaling, padding, cropping etc. */
1718 /* width/height of source */
1719 int i_src_width = id->p_decoder->fmt_out.video.i_width;
1720 int i_src_height = id->p_decoder->fmt_out.video.i_height;
1722 /* with/height scaling */
1723 float f_scale_width = 1;
1724 float f_scale_height = 1;
1726 /* width/height of output stream */
1731 float f_aspect = (float)id->p_decoder->fmt_out.video.i_aspect /
1734 msg_Dbg( p_stream, "decoder aspect is %i:%i",
1735 id->p_decoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
1737 /* Change f_aspect from source frame to source pixel */
1738 f_aspect = f_aspect * i_src_height / i_src_width;
1739 msg_Dbg( p_stream, "source pixel aspect is %f:1", f_aspect );
1741 /* width/height after cropping */
1742 p_sys->i_src_x_offset = p_sys->i_crop_left & ~1;
1743 p_sys->i_src_y_offset = p_sys->i_crop_top & ~1;
1744 p_sys->i_crop_width = i_src_width - ( p_sys->i_crop_left & ~1 ) -
1745 ( p_sys->i_crop_right & ~1 );
1746 p_sys->i_crop_height = i_src_height - ( p_sys->i_crop_top & ~1 ) -
1747 ( p_sys->i_crop_bottom & ~1 );
1749 /* Calculate scaling factor for specified parameters */
1750 if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1751 id->p_encoder->fmt_out.video.i_height <= 0 && p_sys->f_scale )
1753 /* Global scaling. Make sure width will remain a factor of 16 */
1756 int i_new_width = i_src_width * p_sys->f_scale;
1758 if( i_new_width % 16 <= 7 && i_new_width >= 16 )
1759 i_new_width -= i_new_width % 16;
1761 i_new_width += 16 - i_new_width % 16;
1763 f_real_scale = (float)( i_new_width ) / (float) i_src_width;
1765 i_new_height = __MAX( 16, i_src_height * (float)f_real_scale );
1767 f_scale_width = f_real_scale;
1768 f_scale_height = (float) i_new_height / (float) i_src_height;
1770 else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1771 id->p_encoder->fmt_out.video.i_height <= 0 )
1773 /* Only width specified */
1774 f_scale_width = (float)id->p_encoder->fmt_out.video.i_width /
1775 p_sys->i_crop_width;
1776 f_scale_height = f_scale_width;
1778 else if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1779 id->p_encoder->fmt_out.video.i_height > 0 )
1781 /* Only height specified */
1782 f_scale_height = (float)id->p_encoder->fmt_out.video.i_height /
1783 p_sys->i_crop_height;
1784 f_scale_width = f_scale_height;
1786 else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1787 id->p_encoder->fmt_out.video.i_height > 0 )
1789 /* Width and height specified */
1790 f_scale_width = (float)id->p_encoder->fmt_out.video.i_width
1791 / p_sys->i_crop_width;
1792 f_scale_height = (float)id->p_encoder->fmt_out.video.i_height
1793 / p_sys->i_crop_height;
1796 /* check maxwidth and maxheight
1797 * note: maxwidth and maxheight currently does not handle
1798 * canvas and padding, just scaling and cropping.
1800 if( p_sys->i_maxwidth && f_scale_width > (float)p_sys->i_maxwidth /
1801 p_sys->i_crop_width )
1803 f_scale_width = (float)p_sys->i_maxwidth / p_sys->i_crop_width;
1805 if( p_sys->i_maxheight && f_scale_height > (float)p_sys->i_maxheight /
1806 p_sys->i_crop_height )
1808 f_scale_height = (float)p_sys->i_maxheight / p_sys->i_crop_height;
1811 /* Change aspect ratio from source pixel to scaled pixel */
1812 f_aspect = f_aspect * f_scale_height / f_scale_width;
1813 msg_Dbg( p_stream, "scaled pixel aspect is %f:1", f_aspect );
1815 /* Correct scaling for target aspect ratio
1816 * Shrink video if necessary
1818 if ( p_sys->i_canvas_aspect > 0 )
1820 float f_target_aspect = (float)p_sys->i_canvas_aspect /
1823 if( p_sys->i_canvas_width > 0 && p_sys->i_canvas_height > 0)
1825 /* Calculate pixel aspect of canvas */
1826 f_target_aspect = f_target_aspect / p_sys->i_canvas_width *
1827 p_sys->i_canvas_height;
1829 if( f_target_aspect > f_aspect )
1831 /* Reduce width scale to increase aspect */
1832 f_scale_width = f_scale_width * f_aspect / f_target_aspect;
1836 /* Reduce height scale to decrease aspect */
1837 f_scale_height = f_scale_height * f_target_aspect / f_aspect;
1839 f_aspect = f_target_aspect;
1840 msg_Dbg( p_stream, "canvas scaled pixel aspect is %f:1", f_aspect );
1843 /* f_scale_width and f_scale_height are now final */
1844 /* Calculate width, height from scaling
1845 * Make sure its multiple of 2
1847 i_dst_width = 2 * (int)( p_sys->i_crop_width * f_scale_width / 2 + 0.5 );
1849 (int)( p_sys->i_crop_height * f_scale_height / 2 + 0.5 );
1851 p_sys->i_nopadd_width = i_dst_width;
1852 p_sys->i_nopadd_height = i_dst_height;
1853 p_sys->i_dst_x_offset = 0;
1854 p_sys->i_dst_y_offset = 0;
1856 /* Handle canvas and padding */
1857 if( p_sys->i_canvas_width <= 0 )
1859 /* No canvas width set, add explicit padding border */
1860 i_dst_width = p_sys->i_nopadd_width + ( p_sys->i_padd_left & ~1 ) +
1861 ( p_sys->i_padd_right & ~1 );
1862 p_sys->i_dst_x_offset = ( p_sys->i_padd_left & ~1 );
1866 /* Canvas set, check if we have to padd or crop */
1867 if( p_sys->i_canvas_width < p_sys->i_nopadd_width )
1869 /* need to crop more, but keep same scaling */
1870 int i_crop = 2 * (int)( ( p_sys->i_canvas_width & ~1 ) /
1871 f_scale_width / 2 + 0.5 );
1873 p_sys->i_src_x_offset += ( ( p_sys->i_crop_width - i_crop ) / 2 )
1875 p_sys->i_crop_width = i_crop;
1876 i_dst_width = p_sys->i_canvas_width & ~1;
1877 p_sys->i_nopadd_width = i_dst_width;
1879 else if( p_sys->i_canvas_width > p_sys->i_nopadd_width )
1882 i_dst_width = p_sys->i_canvas_width & ~1;
1883 p_sys->i_dst_x_offset = ( i_dst_width - p_sys->i_nopadd_width )/2;
1884 p_sys->i_dst_x_offset = p_sys->i_dst_x_offset & ~1;
1888 if( p_sys->i_canvas_height <= 0 )
1890 /* No canvas set, add padding border */
1891 i_dst_height = p_sys->i_nopadd_height + ( p_sys->i_padd_top & ~1 ) +
1892 ( p_sys->i_padd_bottom & ~1 );
1893 p_sys->i_dst_y_offset = ( p_sys->i_padd_top & ~1 );
1897 /* Canvas set, check if we have to padd or crop */
1898 if( p_sys->i_canvas_height < p_sys->i_nopadd_height )
1900 /* need to crop more, but keep same scaling */
1901 int i_crop = 2 * (int)( ( p_sys->i_canvas_height & ~1 ) /
1902 f_scale_height / 2 + 0.5 );
1904 p_sys->i_src_y_offset += ( ( p_sys->i_crop_height - i_crop ) / 2 )
1906 p_sys->i_crop_height = i_crop;
1907 i_dst_height = p_sys->i_canvas_height & ~1;
1908 p_sys->i_nopadd_height = i_dst_height;
1910 else if( p_sys->i_canvas_height > p_sys->i_nopadd_height )
1913 i_dst_height = p_sys->i_canvas_height & ~1;
1914 p_sys->i_dst_y_offset = ( i_dst_height - p_sys->i_nopadd_height )
1916 p_sys->i_dst_y_offset = p_sys->i_dst_y_offset & ~1;
1920 /* Change aspect ratio from scaled pixel to output frame */
1921 f_aspect = f_aspect * i_dst_width / i_dst_height;
1923 /* Store calculated values */
1924 id->p_encoder->fmt_out.video.i_width = i_dst_width;
1925 id->p_encoder->fmt_out.video.i_height = i_dst_height;
1927 id->p_encoder->fmt_in.video.i_width = i_dst_width;
1928 id->p_encoder->fmt_in.video.i_height = i_dst_height;
1930 msg_Dbg( p_stream, "source %ix%i, crop %ix%i, "
1931 "destination %ix%i, padding %ix%i",
1932 i_src_width, i_src_height,
1933 p_sys->i_crop_width, p_sys->i_crop_height,
1934 p_sys->i_nopadd_width, p_sys->i_nopadd_height,
1935 i_dst_width, i_dst_height
1938 /* Handle frame rate conversion */
1939 if( !id->p_encoder->fmt_out.video.i_frame_rate ||
1940 !id->p_encoder->fmt_out.video.i_frame_rate_base )
1942 if( id->p_decoder->fmt_out.video.i_frame_rate &&
1943 id->p_decoder->fmt_out.video.i_frame_rate_base )
1945 id->p_encoder->fmt_out.video.i_frame_rate =
1946 id->p_decoder->fmt_out.video.i_frame_rate;
1947 id->p_encoder->fmt_out.video.i_frame_rate_base =
1948 id->p_decoder->fmt_out.video.i_frame_rate_base;
1952 /* Pick a sensible default value */
1953 id->p_encoder->fmt_out.video.i_frame_rate = 25;
1954 id->p_encoder->fmt_out.video.i_frame_rate_base = 1;
1958 id->p_encoder->fmt_in.video.i_frame_rate =
1959 id->p_encoder->fmt_out.video.i_frame_rate;
1960 id->p_encoder->fmt_in.video.i_frame_rate_base =
1961 id->p_encoder->fmt_out.video.i_frame_rate_base;
1963 date_Init( &id->interpolated_pts,
1964 id->p_encoder->fmt_out.video.i_frame_rate,
1965 id->p_encoder->fmt_out.video.i_frame_rate_base );
1967 /* Check whether a particular aspect ratio was requested */
1968 if( !id->p_encoder->fmt_out.video.i_aspect )
1970 id->p_encoder->fmt_out.video.i_aspect = (int)( f_aspect * VOUT_ASPECT_FACTOR + 0.5 );
1972 id->p_encoder->fmt_in.video.i_aspect =
1973 id->p_encoder->fmt_out.video.i_aspect;
1975 msg_Dbg( p_stream, "encoder aspect is %i:%i", id->p_encoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
1977 id->p_encoder->p_module =
1978 module_Need( id->p_encoder, "encoder", p_sys->psz_venc, VLC_TRUE );
1979 if( !id->p_encoder->p_module )
1981 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_venc );
1982 return VLC_EGENERIC;
1985 id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
1987 /* Hack for mp2v/mp1v transcoding support */
1988 if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','1','v') ||
1989 id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','2','v') )
1991 id->p_encoder->fmt_out.i_codec = VLC_FOURCC('m','p','g','v');
1994 id->id = p_stream->p_sys->p_out->pf_add( p_stream->p_sys->p_out,
1995 &id->p_encoder->fmt_out );
1998 msg_Err( p_stream, "cannot add this stream" );
1999 return VLC_EGENERIC;
2005 static void transcode_video_close( sout_stream_t *p_stream,
2006 sout_stream_id_t *id )
2010 if( p_stream->p_sys->i_threads >= 1 )
2012 vlc_mutex_lock( &p_stream->p_sys->lock_out );
2013 p_stream->p_sys->b_die = 1;
2014 vlc_cond_signal( &p_stream->p_sys->cond );
2015 vlc_mutex_unlock( &p_stream->p_sys->lock_out );
2016 vlc_thread_join( p_stream->p_sys );
2017 vlc_mutex_destroy( &p_stream->p_sys->lock_out );
2018 vlc_cond_destroy( &p_stream->p_sys->cond );
2022 if( id->p_decoder->p_module )
2023 module_Unneed( id->p_decoder, id->p_decoder->p_module );
2025 if( id->p_decoder->p_owner )
2027 /* Clean-up pictures ring buffer */
2028 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2030 if( id->p_decoder->p_owner->pp_pics[i] )
2031 video_del_buffer( VLC_OBJECT(id->p_decoder),
2032 id->p_decoder->p_owner->pp_pics[i] );
2034 free( id->p_decoder->p_owner );
2038 if( id->p_encoder->p_module )
2039 module_Unneed( id->p_encoder, id->p_encoder->p_module );
2042 for( i = 0; i < id->i_filter; i++ )
2044 vlc_object_detach( id->pp_filter[i] );
2045 if( id->pp_filter[i]->p_module )
2046 module_Unneed( id->pp_filter[i], id->pp_filter[i]->p_module );
2048 /* Clean-up pictures ring buffer */
2049 for( j = 0; j < PICTURE_RING_SIZE; j++ )
2051 if( id->pp_filter[i]->p_owner->pp_pics[j] )
2052 video_del_buffer( VLC_OBJECT(id->pp_filter[i]),
2053 id->pp_filter[i]->p_owner->pp_pics[j] );
2055 free( id->pp_filter[i]->p_owner );
2056 vlc_object_destroy( id->pp_filter[i] );
2057 id->pp_filter[i] = NULL;
2060 for( i = 0; i < id->i_ufilter; i++ )
2062 vlc_object_detach( id->pp_ufilter[i] );
2063 if( id->pp_ufilter[i]->p_module )
2064 module_Unneed( id->pp_ufilter[i], id->pp_ufilter[i]->p_module );
2066 /* Clean-up pictures ring buffer */
2067 for( j = 0; j < PICTURE_RING_SIZE; j++ )
2069 if( id->pp_ufilter[i]->p_owner->pp_pics[j] )
2070 video_del_buffer( VLC_OBJECT(id->pp_ufilter[i]),
2071 id->pp_ufilter[i]->p_owner->pp_pics[j] );
2073 free( id->pp_ufilter[i]->p_owner );
2074 vlc_object_destroy( id->pp_ufilter[i] );
2075 id->pp_ufilter[i] = NULL;
2079 static int transcode_video_process( sout_stream_t *p_stream,
2080 sout_stream_id_t *id,
2081 block_t *in, block_t **out )
2083 sout_stream_sys_t *p_sys = p_stream->p_sys;
2084 int i_duplicate = 1, i;
2085 picture_t *p_pic, *p_pic2 = NULL;
2087 input_thread_t *p_input = NULL;
2089 if( p_stream->p_parent->p_parent && p_stream->p_parent->p_parent->
2090 i_object_type == VLC_OBJECT_INPUT )
2091 p_input = (input_thread_t *)p_stream->p_parent->p_parent;
2093 while( (p_pic = id->p_decoder->pf_decode_video( id->p_decoder, &in )) )
2095 subpicture_t *p_subpic = 0;
2097 stats_UpdateInteger( p_input, p_input->counters.p_decoded_video,
2100 if( p_stream->p_sout->i_out_pace_nocontrol && p_sys->b_hurry_up )
2102 mtime_t current_date = mdate();
2103 if( current_date + 50000 > p_pic->date )
2105 msg_Dbg( p_stream, "late picture skipped ("I64Fd")",
2106 current_date + 50000 - p_pic->date );
2107 p_pic->pf_release( p_pic );
2112 if( p_sys->b_master_sync )
2114 mtime_t i_video_drift;
2115 mtime_t i_master_drift = p_sys->i_master_drift;
2118 i_pts = date_Get( &id->interpolated_pts ) + 1;
2119 if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2120 || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2122 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2123 date_Set( &id->interpolated_pts, p_pic->date );
2124 i_pts = p_pic->date + 1;
2126 i_video_drift = p_pic->date - i_pts;
2129 /* Set the pts of the frame being encoded */
2130 p_pic->date = i_pts;
2132 if( i_video_drift < i_master_drift - 50000 )
2135 msg_Dbg( p_stream, "dropping frame (%i)",
2136 (int)(i_video_drift - i_master_drift) );
2138 p_pic->pf_release( p_pic );
2141 else if( i_video_drift > i_master_drift + 50000 )
2144 msg_Dbg( p_stream, "adding frame (%i)",
2145 (int)(i_video_drift - i_master_drift) );
2151 if( !id->p_encoder->p_module )
2153 if( transcode_video_encoder_open( p_stream, id ) != VLC_SUCCESS )
2155 p_pic->pf_release( p_pic );
2156 transcode_video_close( p_stream, id );
2157 id->b_transcode = VLC_FALSE;
2158 return VLC_EGENERIC;
2162 if( p_stream->p_sys->b_deinterlace )
2164 id->pp_filter[id->i_filter] =
2165 vlc_object_create( p_stream, VLC_OBJECT_FILTER );
2166 vlc_object_attach( id->pp_filter[id->i_filter], p_stream );
2168 id->pp_filter[id->i_filter]->pf_vout_buffer_new =
2169 video_new_buffer_filter;
2170 id->pp_filter[id->i_filter]->pf_vout_buffer_del =
2171 video_del_buffer_filter;
2173 id->pp_filter[id->i_filter]->fmt_in = id->p_decoder->fmt_out;
2174 id->pp_filter[id->i_filter]->fmt_out = id->p_decoder->fmt_out;
2175 id->pp_filter[id->i_filter]->p_cfg = p_sys->p_deinterlace_cfg;
2176 id->pp_filter[id->i_filter]->p_module =
2177 module_Need( id->pp_filter[id->i_filter],
2178 "video filter2", p_sys->psz_deinterlace, 0 );
2179 if( id->pp_filter[id->i_filter]->p_module )
2181 id->pp_filter[id->i_filter]->p_owner =
2182 malloc( sizeof(filter_owner_sys_t) );
2183 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2184 id->pp_filter[id->i_filter]->p_owner->pp_pics[i] = 0;
2185 id->pp_filter[id->i_filter]->p_owner->p_sys = p_sys;
2191 msg_Dbg( p_stream, "no video filter found" );
2192 vlc_object_detach( id->pp_filter[id->i_filter] );
2193 vlc_object_destroy( id->pp_filter[id->i_filter] );
2197 /* Check if we need a filter for chroma conversion or resizing */
2198 if( id->p_decoder->fmt_out.video.i_chroma !=
2199 id->p_encoder->fmt_in.video.i_chroma ||
2201 (int)id->p_decoder->fmt_out.video.i_width != p_sys->i_crop_width ||
2202 p_sys->i_crop_width != p_sys->i_nopadd_width ||
2203 p_sys->i_nopadd_width != (int)id->p_encoder->fmt_out.video.i_width ||
2205 (int)id->p_decoder->fmt_out.video.i_height != p_sys->i_crop_height ||
2206 p_sys->i_crop_height != p_sys->i_nopadd_height ||
2207 p_sys->i_nopadd_height != (int)id->p_encoder->fmt_out.video.i_height)
2209 id->pp_filter[id->i_filter] =
2210 vlc_object_create( p_stream, VLC_OBJECT_FILTER );
2211 vlc_object_attach( id->pp_filter[id->i_filter], p_stream );
2213 id->pp_filter[id->i_filter]->pf_vout_buffer_new =
2214 video_new_buffer_filter;
2215 id->pp_filter[id->i_filter]->pf_vout_buffer_del =
2216 video_del_buffer_filter;
2218 id->pp_filter[id->i_filter]->fmt_in = id->p_decoder->fmt_out;
2219 id->pp_filter[id->i_filter]->fmt_out = id->p_encoder->fmt_in;
2220 id->pp_filter[id->i_filter]->p_cfg = NULL;
2222 id->pp_filter[id->i_filter]->fmt_in.video.i_x_offset = p_sys->i_src_x_offset;
2223 id->pp_filter[id->i_filter]->fmt_in.video.i_y_offset = p_sys->i_src_y_offset;
2224 id->pp_filter[id->i_filter]->fmt_in.video.i_visible_width = p_sys->i_crop_width;
2225 id->pp_filter[id->i_filter]->fmt_in.video.i_visible_height = p_sys->i_crop_height;
2227 id->pp_filter[id->i_filter]->fmt_out.video.i_x_offset = p_sys->i_dst_x_offset;
2228 id->pp_filter[id->i_filter]->fmt_out.video.i_y_offset = p_sys->i_dst_y_offset;
2229 id->pp_filter[id->i_filter]->fmt_out.video.i_visible_width = p_sys->i_nopadd_width;
2230 id->pp_filter[id->i_filter]->fmt_out.video.i_visible_height = p_sys->i_nopadd_height;
2232 id->pp_filter[id->i_filter]->p_module =
2233 module_Need( id->pp_filter[id->i_filter],
2234 "crop padd", 0, 0 );
2235 if( id->pp_filter[id->i_filter]->p_module )
2237 id->pp_filter[id->i_filter]->p_owner =
2238 malloc( sizeof(filter_owner_sys_t) );
2239 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2240 id->pp_filter[id->i_filter]->p_owner->pp_pics[i] = 0;
2241 id->pp_filter[id->i_filter]->p_owner->p_sys = p_sys;
2247 msg_Dbg( p_stream, "no video filter found" );
2248 vlc_object_detach( id->pp_filter[id->i_filter] );
2249 vlc_object_destroy( id->pp_filter[id->i_filter] );
2251 p_pic->pf_release( p_pic );
2252 transcode_video_close( p_stream, id );
2253 id->b_transcode = VLC_FALSE;
2254 return VLC_EGENERIC;
2258 for( i = 0; (i < p_sys->i_vfilters) && (id->i_ufilter < TRANSCODE_FILTERS); i++ )
2260 id->pp_ufilter[id->i_ufilter] =
2261 vlc_object_create( p_stream, VLC_OBJECT_FILTER );
2262 vlc_object_attach( id->pp_ufilter[id->i_ufilter], p_stream );
2264 id->pp_ufilter[id->i_ufilter]->pf_vout_buffer_new =
2265 video_new_buffer_filter;
2266 id->pp_ufilter[id->i_ufilter]->pf_vout_buffer_del =
2267 video_del_buffer_filter;
2269 id->pp_ufilter[id->i_ufilter]->fmt_in = id->p_encoder->fmt_in;
2270 id->pp_ufilter[id->i_ufilter]->fmt_out = id->p_encoder->fmt_in;
2271 id->pp_ufilter[id->i_ufilter]->p_cfg = p_sys->p_vfilters_cfg[i];
2272 id->pp_ufilter[id->i_ufilter]->p_module =
2273 module_Need( id->pp_ufilter[id->i_ufilter],
2274 "video filter2", p_sys->psz_vfilters[i], 0 );
2275 if( id->pp_ufilter[id->i_ufilter]->p_module )
2277 id->pp_ufilter[id->i_ufilter]->p_owner =
2278 malloc( sizeof(filter_owner_sys_t) );
2279 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2280 id->pp_ufilter[id->i_ufilter]->p_owner->pp_pics[i] = 0;
2281 id->pp_ufilter[id->i_ufilter]->p_owner->p_sys = p_sys;
2286 msg_Dbg( p_stream, "no video filter found" );
2287 vlc_object_detach( id->pp_ufilter[id->i_ufilter] );
2288 vlc_object_destroy( id->pp_ufilter[id->i_ufilter] );
2293 /* Run filter chain */
2294 for( i = 0; i < id->i_filter; i++ )
2296 p_pic = id->pp_filter[i]->pf_video_filter(id->pp_filter[i], p_pic);
2303 /* Check if we have a subpicture to overlay */
2306 p_subpic = spu_SortSubpictures( p_sys->p_spu, p_pic->date );
2307 /* TODO: get another pic */
2310 /* Overlay subpicture */
2313 int i_scale_width, i_scale_height;
2314 video_format_t *p_fmt;
2316 i_scale_width = id->p_encoder->fmt_in.video.i_width * 1000 /
2317 id->p_decoder->fmt_out.video.i_width;
2318 i_scale_height = id->p_encoder->fmt_in.video.i_height * 1000 /
2319 id->p_decoder->fmt_out.video.i_height;
2321 if( p_pic->i_refcount && !id->i_filter )
2323 /* We can't modify the picture, we need to duplicate it */
2324 picture_t *p_tmp = video_new_buffer_decoder( id->p_decoder );
2327 vout_CopyPicture( p_stream, p_tmp, p_pic );
2328 p_pic->pf_release( p_pic );
2334 p_fmt = &id->pp_filter[id->i_filter -1]->fmt_out.video;
2336 p_fmt = &id->p_decoder->fmt_out.video;
2338 /* FIXME (shouldn't have to be done here) */
2339 p_fmt->i_sar_num = p_fmt->i_aspect *
2340 p_fmt->i_height / p_fmt->i_width;
2341 p_fmt->i_sar_den = VOUT_ASPECT_FACTOR;
2343 spu_RenderSubpictures( p_sys->p_spu, p_fmt, p_pic, p_pic, p_subpic,
2344 i_scale_width, i_scale_height );
2347 /* Run user specified filter chain */
2348 for( i = 0; i < id->i_ufilter; i++ )
2350 p_pic = id->pp_ufilter[i]->pf_video_filter(id->pp_ufilter[i], p_pic);
2353 if( p_sys->i_threads == 0 )
2356 p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
2357 block_ChainAppend( out, p_block );
2360 if( p_sys->b_master_sync )
2362 mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
2363 if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2364 || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2366 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2367 date_Set( &id->interpolated_pts, p_pic->date );
2368 i_pts = p_pic->date + 1;
2370 date_Increment( &id->interpolated_pts, 1 );
2373 if( p_sys->b_master_sync && i_duplicate > 1 )
2375 mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
2376 if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2377 || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2379 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2380 date_Set( &id->interpolated_pts, p_pic->date );
2381 i_pts = p_pic->date + 1;
2383 date_Increment( &id->interpolated_pts, 1 );
2385 if( p_sys->i_threads >= 1 )
2387 /* We can't modify the picture, we need to duplicate it */
2388 p_pic2 = video_new_buffer_decoder( id->p_decoder );
2389 if( p_pic2 != NULL )
2391 vout_CopyPicture( p_stream, p_pic2, p_pic );
2392 p_pic2->date = i_pts;
2398 p_pic->date = i_pts;
2399 p_block = id->p_encoder->pf_encode_video(id->p_encoder, p_pic);
2400 block_ChainAppend( out, p_block );
2404 if( p_sys->i_threads == 0 )
2406 p_pic->pf_release( p_pic );
2410 vlc_mutex_lock( &p_sys->lock_out );
2411 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic;
2412 p_sys->i_last_pic %= PICTURE_RING_SIZE;
2413 *out = p_sys->p_buffers;
2414 p_sys->p_buffers = NULL;
2415 if( p_pic2 != NULL )
2417 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic2;
2418 p_sys->i_last_pic %= PICTURE_RING_SIZE;
2420 vlc_cond_signal( &p_sys->cond );
2421 vlc_mutex_unlock( &p_sys->lock_out );
2428 static int EncoderThread( sout_stream_sys_t *p_sys )
2430 sout_stream_id_t *id = p_sys->id_video;
2433 while( !p_sys->b_die && !p_sys->b_error )
2437 vlc_mutex_lock( &p_sys->lock_out );
2438 while( p_sys->i_last_pic == p_sys->i_first_pic )
2440 vlc_cond_wait( &p_sys->cond, &p_sys->lock_out );
2441 if( p_sys->b_die || p_sys->b_error ) break;
2443 if( p_sys->b_die || p_sys->b_error )
2445 vlc_mutex_unlock( &p_sys->lock_out );
2449 p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2450 p_sys->i_first_pic %= PICTURE_RING_SIZE;
2451 vlc_mutex_unlock( &p_sys->lock_out );
2453 p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
2454 vlc_mutex_lock( &p_sys->lock_out );
2455 block_ChainAppend( &p_sys->p_buffers, p_block );
2457 vlc_mutex_unlock( &p_sys->lock_out );
2458 p_pic->pf_release( p_pic );
2461 while( p_sys->i_last_pic != p_sys->i_first_pic )
2463 p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2464 p_sys->i_first_pic %= PICTURE_RING_SIZE;
2465 p_pic->pf_release( p_pic );
2467 block_ChainRelease( p_sys->p_buffers );
2472 struct picture_sys_t
2474 vlc_object_t *p_owner;
2477 static void video_release_buffer( picture_t *p_pic )
2479 if( p_pic && !p_pic->i_refcount && p_pic->pf_release && p_pic->p_sys )
2481 video_del_buffer_decoder( (decoder_t *)p_pic->p_sys->p_owner, p_pic );
2483 else if( p_pic && p_pic->i_refcount > 0 ) p_pic->i_refcount--;
2486 static picture_t *video_new_buffer( vlc_object_t *p_this, picture_t **pp_ring,
2487 sout_stream_sys_t *p_sys )
2489 decoder_t *p_dec = (decoder_t *)p_this;
2493 /* Find an empty space in the picture ring buffer */
2494 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2496 if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
2498 pp_ring[i]->i_status = RESERVED_PICTURE;
2502 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2504 if( pp_ring[i] == 0 ) break;
2507 if( i == PICTURE_RING_SIZE && p_sys->i_threads >= 1 )
2509 int i_first_pic = p_sys->i_first_pic;
2511 if( p_sys->i_first_pic != p_sys->i_last_pic )
2513 /* Encoder still has stuff to encode, wait to clear-up the list */
2514 while( p_sys->i_first_pic == i_first_pic )
2518 /* Find an empty space in the picture ring buffer */
2519 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2521 if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
2523 pp_ring[i]->i_status = RESERVED_PICTURE;
2527 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2529 if( pp_ring[i] == 0 ) break;
2533 if( i == PICTURE_RING_SIZE )
2535 msg_Err( p_this, "decoder/filter is leaking pictures, "
2536 "resetting its ring buffer" );
2538 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2540 pp_ring[i]->pf_release( pp_ring[i] );
2546 p_pic = malloc( sizeof(picture_t) );
2547 p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
2548 vout_AllocatePicture( VLC_OBJECT(p_dec), p_pic,
2549 p_dec->fmt_out.video.i_chroma,
2550 p_dec->fmt_out.video.i_width,
2551 p_dec->fmt_out.video.i_height,
2552 p_dec->fmt_out.video.i_aspect );
2554 if( !p_pic->i_planes )
2560 p_pic->pf_release = video_release_buffer;
2561 p_pic->p_sys = malloc( sizeof(picture_sys_t) );
2562 p_pic->p_sys->p_owner = p_this;
2563 p_pic->i_status = RESERVED_PICTURE;
2569 static picture_t *video_new_buffer_decoder( decoder_t *p_dec )
2571 return video_new_buffer( VLC_OBJECT(p_dec),
2572 p_dec->p_owner->pp_pics, p_dec->p_owner->p_sys );
2575 static picture_t *video_new_buffer_filter( filter_t *p_filter )
2577 return video_new_buffer( VLC_OBJECT(p_filter),
2578 p_filter->p_owner->pp_pics,
2579 p_filter->p_owner->p_sys );
2582 static void video_del_buffer( vlc_object_t *p_this, picture_t *p_pic )
2584 if( p_pic && p_pic->p_data_orig ) free( p_pic->p_data_orig );
2585 if( p_pic && p_pic->p_sys ) free( p_pic->p_sys );
2586 if( p_pic ) free( p_pic );
2589 static void video_del_buffer_decoder( decoder_t *p_decoder, picture_t *p_pic )
2591 p_pic->i_refcount = 0;
2592 p_pic->i_status = DESTROYED_PICTURE;
2595 static void video_del_buffer_filter( filter_t *p_filter, picture_t *p_pic )
2597 p_pic->i_refcount = 0;
2598 p_pic->i_status = DESTROYED_PICTURE;
2601 static void video_link_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2603 p_pic->i_refcount++;
2606 static void video_unlink_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2608 video_release_buffer( p_pic );
2614 static subpicture_t *spu_new_buffer( decoder_t * );
2615 static void spu_del_buffer( decoder_t *, subpicture_t * );
2617 static int transcode_spu_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2619 sout_stream_sys_t *p_sys = p_stream->p_sys;
2625 /* Initialization of decoder structures */
2626 id->p_decoder->pf_spu_buffer_new = spu_new_buffer;
2627 id->p_decoder->pf_spu_buffer_del = spu_del_buffer;
2628 id->p_decoder->p_owner = (decoder_owner_sys_t *)p_stream;
2629 /* id->p_decoder->p_cfg = p_sys->p_spu_cfg; */
2631 id->p_decoder->p_module =
2632 module_Need( id->p_decoder, "decoder", "$codec", 0 );
2634 if( !id->p_decoder->p_module )
2636 msg_Err( p_stream, "cannot find decoder" );
2637 return VLC_EGENERIC;
2640 if( !p_sys->b_soverlay )
2643 /* Initialization of encoder format structures */
2644 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
2645 id->p_decoder->fmt_in.i_codec );
2647 id->p_encoder->p_cfg = p_sys->p_spu_cfg;
2649 id->p_encoder->p_module =
2650 module_Need( id->p_encoder, "encoder", p_sys->psz_senc, VLC_TRUE );
2652 if( !id->p_encoder->p_module )
2654 module_Unneed( id->p_decoder, id->p_decoder->p_module );
2655 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_senc );
2656 return VLC_EGENERIC;
2662 p_sys->p_spu = spu_Create( p_stream );
2663 spu_Init( p_sys->p_spu );
2669 static void transcode_spu_close( sout_stream_t *p_stream, sout_stream_id_t *id)
2672 if( id->p_decoder->p_module )
2673 module_Unneed( id->p_decoder, id->p_decoder->p_module );
2676 if( id->p_encoder->p_module )
2677 module_Unneed( id->p_encoder, id->p_encoder->p_module );
2680 static int transcode_spu_process( sout_stream_t *p_stream,
2681 sout_stream_id_t *id,
2682 block_t *in, block_t **out )
2684 sout_stream_sys_t *p_sys = p_stream->p_sys;
2685 subpicture_t *p_subpic;
2688 p_subpic = id->p_decoder->pf_decode_sub( id->p_decoder, &in );
2689 if( !p_subpic ) return VLC_EGENERIC;
2691 if( p_sys->b_master_sync && p_sys->i_master_drift )
2693 p_subpic->i_start -= p_sys->i_master_drift;
2694 if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2697 if( p_sys->b_soverlay )
2699 spu_DisplaySubpicture( p_sys->p_spu, p_subpic );
2705 p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
2706 spu_del_buffer( id->p_decoder, p_subpic );
2710 block_ChainAppend( out, p_block );
2715 return VLC_EGENERIC;
2718 static subpicture_t *spu_new_buffer( decoder_t *p_dec )
2720 sout_stream_t *p_stream = (sout_stream_t *)p_dec->p_owner;
2721 return spu_CreateSubpicture( p_stream->p_sys->p_spu );
2724 static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_subpic )
2726 sout_stream_t *p_stream = (sout_stream_t *)p_dec->p_owner;
2727 spu_DestroySubpicture( p_stream->p_sys->p_spu, p_subpic );
2733 static int transcode_osd_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2735 sout_stream_sys_t *p_sys = p_stream->p_sys;
2739 fmt.i_id = 0xbd1f; /* pid ?? */
2740 fmt.i_group = 3; /* pmt entry ?? */
2741 fmt.i_codec = VLC_FOURCC( 'Y', 'U', 'V', 'A' );
2742 fmt.psz_language = strdup( "osd" );
2744 id = malloc( sizeof( sout_stream_id_t ) );
2745 memset( id, 0, sizeof(sout_stream_id_t) );
2748 id->p_decoder = NULL;
2749 id->p_encoder = NULL;
2751 /* Create encoder object */
2752 id->p_encoder = vlc_object_create( p_stream, VLC_OBJECT_ENCODER );
2753 if( !id->p_encoder )
2755 msg_Err( p_stream, "out of memory" );
2758 vlc_object_attach( id->p_encoder, p_stream );
2759 id->p_encoder->p_module = NULL;
2761 /* Create fake destination format */
2762 es_format_Init( &id->p_encoder->fmt_out, fmt.i_cat, 0 );
2763 id->p_encoder->fmt_out.i_id = fmt.i_id;
2764 id->p_encoder->fmt_out.i_group = fmt.i_group;
2765 id->p_encoder->fmt_out.psz_language = strdup( fmt.psz_language );
2767 if( p_sys->i_osdcodec != 0 || p_sys->psz_osdenc )
2769 msg_Dbg( p_stream, "creating osdmenu transcoding from fcc=`%4.4s' "
2770 "to fcc=`%4.4s'", (char*)&fmt.i_codec,
2771 (char*)&p_sys->i_osdcodec );
2773 /* Complete destination format */
2774 id->p_encoder->fmt_out.i_codec = p_sys->i_osdcodec;
2777 /* Initialization of encoder format structures */
2778 es_format_Init( &id->p_encoder->fmt_in, fmt.i_cat, fmt.i_codec );
2779 id->p_encoder->fmt_in.psz_language = strdup( fmt.psz_language );
2781 id->p_encoder->p_cfg = p_sys->p_osd_cfg;
2783 id->p_encoder->p_module =
2784 module_Need( id->p_encoder, "encoder", p_sys->psz_osdenc, VLC_TRUE );
2786 if( !id->p_encoder->p_module )
2788 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_osdenc );
2792 /* open output stream */
2793 id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
2794 id->b_transcode = VLC_TRUE;
2796 if( !id->id ) goto error;
2800 msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
2801 (char*)&fmt.i_codec );
2802 id->id = p_sys->p_out->pf_add( p_sys->p_out, &fmt );
2803 id->b_transcode = VLC_FALSE;
2805 if( !id->id ) goto error;
2809 p_sys->b_es_osd = VLC_TRUE;
2813 p_sys->p_spu = spu_Create( p_stream );
2814 if( spu_Init( p_sys->p_spu ) != VLC_SUCCESS )
2815 msg_Err( p_sys, "spu initialisation failed" );
2818 if( fmt.psz_language )
2819 free( fmt.psz_language );
2824 msg_Err( p_stream, "starting osd encoding thread failed" );
2825 if( id->p_encoder->p_module )
2826 module_Unneed( id->p_encoder, id->p_encoder->p_module );
2829 vlc_object_detach( id->p_encoder );
2830 vlc_object_destroy( id->p_encoder );
2832 if( fmt.psz_language ) free( fmt.psz_language );
2833 if( id ) free( id );
2834 p_sys->id_osd = NULL;
2835 p_sys->b_es_osd = VLC_FALSE;
2836 return VLC_EGENERIC;
2839 static void transcode_osd_close( sout_stream_t *p_stream, sout_stream_id_t *id)
2841 sout_stream_sys_t *p_sys = p_stream->p_sys;
2844 if( p_sys->b_es_osd && id )
2846 if( id->p_encoder->p_module )
2847 module_Unneed( id->p_encoder, id->p_encoder->p_module );
2849 if( id->id ) p_sys->p_out->pf_del( p_sys->p_out, id->id );
2853 vlc_object_detach( id->p_encoder );
2854 vlc_object_destroy( id->p_encoder );
2857 p_sys->b_es_osd = VLC_FALSE;
2858 if( id ) free( id );
2861 static int transcode_osd_process( sout_stream_t *p_stream,
2862 sout_stream_id_t *id,
2863 block_t *in, block_t **out )
2865 sout_stream_sys_t *p_sys = p_stream->p_sys;
2866 subpicture_t *p_subpic = NULL;
2868 /* Check if we have a subpicture to send */
2869 if( p_sys->p_spu && in->i_dts > 0)
2871 p_subpic = spu_SortSubpictures( p_sys->p_spu, in->i_dts );
2875 msg_Warn( p_stream, "spu channel not initialized, doing it now" );
2878 p_sys->p_spu = spu_Create( p_stream );
2879 if( spu_Init( p_sys->p_spu ) != VLC_SUCCESS )
2880 msg_Err( p_stream, "spu initialisation failed" );
2886 block_t *p_block = NULL;
2888 if( p_sys->b_master_sync && p_sys->i_master_drift )
2890 p_subpic->i_start -= p_sys->i_master_drift;
2891 if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2894 p_block = p_sys->id_osd->p_encoder->pf_encode_sub( p_sys->id_osd->p_encoder, p_subpic );
2897 p_block->i_dts = p_block->i_pts = in->i_dts;
2898 block_ChainAppend( out, p_block );
2901 if( p_sys->p_out->pf_send( p_sys->p_out, p_sys->id_osd->id, *out ) == VLC_SUCCESS )
2902 spu_DestroySubpicture( p_sys->p_spu, p_subpic );
2907 return VLC_EGENERIC;