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 )
517 if( (strncmp( (char *)&p_sys->i_acodec, "mp3", 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 = sout_CfgCreate(
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 = sout_CfgCreate( &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 = sout_CfgCreate(
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 = sout_CfgCreate( &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 if ( val.psz_string )
667 char *psz_parser = strchr( val.psz_string, ':' );
671 *psz_parser++ = '\0';
672 p_sys->i_canvas_aspect = atoi( val.psz_string ) * VOUT_ASPECT_FACTOR
673 / atoi( psz_parser );
677 msg_Warn( p_stream, "bad aspect ratio %s", val.psz_string );
678 p_sys->i_canvas_aspect = 0;
681 free( val.psz_string );
685 p_sys->i_canvas_aspect = 0;
688 var_Get( p_stream, SOUT_CFG_PREFIX "threads", &val );
689 p_sys->i_threads = val.i_int;
690 var_Get( p_stream, SOUT_CFG_PREFIX "high-priority", &val );
691 p_sys->b_high_priority = val.b_bool;
693 if( p_sys->i_vcodec )
695 msg_Dbg( p_stream, "codec video=%4.4s %dx%d scaling: %f %dkb/s",
696 (char *)&p_sys->i_vcodec, p_sys->i_width, p_sys->i_height,
697 p_sys->f_scale, p_sys->i_vbitrate / 1000 );
700 /* Subpictures transcoding parameters */
702 p_sys->psz_senc = NULL;
703 p_sys->p_spu_cfg = NULL;
706 var_Get( p_stream, SOUT_CFG_PREFIX "senc", &val );
707 if( val.psz_string && *val.psz_string )
710 psz_next = sout_CfgCreate( &p_sys->psz_senc, &p_sys->p_spu_cfg,
712 if( psz_next ) free( psz_next );
714 if( val.psz_string ) free( val.psz_string );
716 var_Get( p_stream, SOUT_CFG_PREFIX "scodec", &val );
717 if( val.psz_string && *val.psz_string )
720 memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
721 p_sys->i_scodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
723 if( val.psz_string ) free( val.psz_string );
725 if( p_sys->i_scodec )
727 msg_Dbg( p_stream, "codec spu=%4.4s", (char *)&p_sys->i_scodec );
730 var_Get( p_stream, SOUT_CFG_PREFIX "soverlay", &val );
731 p_sys->b_soverlay = val.b_bool;
733 var_Get( p_stream, SOUT_CFG_PREFIX "sfilter", &val );
734 if( val.psz_string && *val.psz_string )
736 p_sys->p_spu = spu_Create( p_stream );
737 var_Create( p_sys->p_spu, "sub-filter", VLC_VAR_STRING );
738 var_Set( p_sys->p_spu, "sub-filter", val );
739 spu_Init( p_sys->p_spu );
741 if( val.psz_string ) free( val.psz_string );
743 /* OSD menu transcoding parameters */
744 p_sys->psz_osdenc = NULL;
745 p_sys->p_osd_cfg = NULL;
746 p_sys->i_osdcodec = 0;
747 p_sys->b_es_osd = VLC_FALSE;
749 var_Get( p_stream, SOUT_CFG_PREFIX "osd", &val );
750 p_sys->b_sout_osd = val.b_bool;
751 if( p_sys->b_sout_osd )
756 psz_next = sout_CfgCreate( &p_sys->psz_osdenc,
757 &p_sys->p_osd_cfg, strdup( "dvbsub") );
758 if( psz_next ) free( psz_next );
760 p_sys->i_osdcodec = VLC_FOURCC('Y','U','V','P' );
762 msg_Dbg( p_stream, "codec osd=%4.4s", (char *)&p_sys->i_osdcodec );
766 osd_val.psz_string = strdup("osdmenu");
767 p_sys->p_spu = spu_Create( p_stream );
768 var_Create( p_sys->p_spu, "sub-filter", VLC_VAR_STRING );
769 var_Set( p_sys->p_spu, "sub-filter", osd_val );
770 spu_Init( p_sys->p_spu );
771 if( osd_val.psz_string ) free( osd_val.psz_string );
775 osd_val.psz_string = strdup("osdmenu");
776 var_Set( p_sys->p_spu, "sub-filter", osd_val );
777 if( osd_val.psz_string ) free( osd_val.psz_string );
782 var_Get( p_stream, SOUT_CFG_PREFIX "audio-sync", &val );
783 p_sys->b_master_sync = val.b_bool;
784 if( p_sys->f_fps > 0 ) p_sys->b_master_sync = VLC_TRUE;
786 p_stream->pf_add = Add;
787 p_stream->pf_del = Del;
788 p_stream->pf_send = Send;
789 p_stream->p_sys = p_sys;
794 /*****************************************************************************
796 *****************************************************************************/
797 static void Close( vlc_object_t * p_this )
799 sout_stream_t *p_stream = (sout_stream_t*)p_this;
800 sout_stream_sys_t *p_sys = p_stream->p_sys;
802 sout_StreamDelete( p_sys->p_out );
804 while( p_sys->p_audio_cfg != NULL )
806 sout_cfg_t *p_next = p_sys->p_audio_cfg->p_next;
808 if( p_sys->p_audio_cfg->psz_name )
809 free( p_sys->p_audio_cfg->psz_name );
810 if( p_sys->p_audio_cfg->psz_value )
811 free( p_sys->p_audio_cfg->psz_value );
812 free( p_sys->p_audio_cfg );
814 p_sys->p_audio_cfg = p_next;
816 if( p_sys->psz_aenc ) free( p_sys->psz_aenc );
818 while( p_sys->p_video_cfg != NULL )
820 sout_cfg_t *p_next = p_sys->p_video_cfg->p_next;
822 if( p_sys->p_video_cfg->psz_name )
823 free( p_sys->p_video_cfg->psz_name );
824 if( p_sys->p_video_cfg->psz_value )
825 free( p_sys->p_video_cfg->psz_value );
826 free( p_sys->p_video_cfg );
828 p_sys->p_video_cfg = p_next;
830 if( p_sys->psz_venc ) free( p_sys->psz_venc );
832 while( p_sys->p_deinterlace_cfg != NULL )
834 sout_cfg_t *p_next = p_sys->p_deinterlace_cfg->p_next;
836 if( p_sys->p_deinterlace_cfg->psz_name )
837 free( p_sys->p_deinterlace_cfg->psz_name );
838 if( p_sys->p_deinterlace_cfg->psz_value )
839 free( p_sys->p_deinterlace_cfg->psz_value );
840 free( p_sys->p_deinterlace_cfg );
842 p_sys->p_deinterlace_cfg = p_next;
844 if( p_sys->psz_deinterlace ) free( p_sys->psz_deinterlace );
846 while( p_sys->p_spu_cfg != NULL )
848 sout_cfg_t *p_next = p_sys->p_spu_cfg->p_next;
850 if( p_sys->p_spu_cfg->psz_name )
851 free( p_sys->p_spu_cfg->psz_name );
852 if( p_sys->p_spu_cfg->psz_value )
853 free( p_sys->p_spu_cfg->psz_value );
854 free( p_sys->p_spu_cfg );
856 p_sys->p_spu_cfg = p_next;
858 if( p_sys->psz_senc ) free( p_sys->psz_senc );
860 if( p_sys->p_spu ) spu_Destroy( p_sys->p_spu );
862 while( p_sys->p_osd_cfg != NULL )
864 sout_cfg_t *p_next = p_sys->p_osd_cfg->p_next;
866 if( p_sys->p_osd_cfg->psz_name )
867 free( p_sys->p_osd_cfg->psz_name );
868 if( p_sys->p_osd_cfg->psz_value )
869 free( p_sys->p_osd_cfg->psz_value );
870 free( p_sys->p_osd_cfg );
872 p_sys->p_osd_cfg = p_next;
874 if( p_sys->psz_osdenc ) free( p_sys->psz_osdenc );
876 vlc_object_destroy( p_sys );
879 struct sout_stream_id_t
881 vlc_fourcc_t b_transcode;
883 /* id of the out stream */
887 decoder_t *p_decoder;
890 filter_t *pp_filter[TRANSCODE_FILTERS];
892 /* User specified filters */
893 filter_t *pp_ufilter[TRANSCODE_FILTERS];
897 encoder_t *p_encoder;
900 date_t interpolated_pts;
903 static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
905 sout_stream_sys_t *p_sys = p_stream->p_sys;
906 sout_stream_id_t *id;
908 id = malloc( sizeof( sout_stream_id_t ) );
909 memset( id, 0, sizeof(sout_stream_id_t) );
912 id->p_decoder = NULL;
913 id->p_encoder = NULL;
915 /* Create decoder object */
916 id->p_decoder = vlc_object_create( p_stream, VLC_OBJECT_DECODER );
919 msg_Err( p_stream, "out of memory" );
922 vlc_object_attach( id->p_decoder, p_stream );
923 id->p_decoder->p_module = NULL;
924 id->p_decoder->fmt_in = *p_fmt;
925 id->p_decoder->b_pace_control = VLC_TRUE;
927 /* Create encoder object */
928 id->p_encoder = vlc_object_create( p_stream, VLC_OBJECT_ENCODER );
931 msg_Err( p_stream, "out of memory" );
934 vlc_object_attach( id->p_encoder, p_stream );
935 id->p_encoder->p_module = NULL;
937 /* Create destination format */
938 es_format_Init( &id->p_encoder->fmt_out, p_fmt->i_cat, 0 );
939 id->p_encoder->fmt_out.i_id = p_fmt->i_id;
940 id->p_encoder->fmt_out.i_group = p_fmt->i_group;
941 if( p_fmt->psz_language )
942 id->p_encoder->fmt_out.psz_language = strdup( p_fmt->psz_language );
944 if( p_fmt->i_cat == AUDIO_ES && (p_sys->i_acodec || p_sys->psz_aenc) )
947 "creating audio transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
948 (char*)&p_fmt->i_codec, (char*)&p_sys->i_acodec );
950 /* Complete destination format */
951 id->p_encoder->fmt_out.i_codec = p_sys->i_acodec;
952 id->p_encoder->fmt_out.audio.i_rate = p_sys->i_sample_rate > 0 ?
953 p_sys->i_sample_rate : (int)p_fmt->audio.i_rate;
954 id->p_encoder->fmt_out.i_bitrate = p_sys->i_abitrate;
955 id->p_encoder->fmt_out.audio.i_bitspersample =
956 p_fmt->audio.i_bitspersample;
957 id->p_encoder->fmt_out.audio.i_channels = p_sys->i_channels > 0 ?
958 p_sys->i_channels : p_fmt->audio.i_channels;
959 /* Sanity check for audio channels */
960 id->p_encoder->fmt_out.audio.i_channels =
961 __MIN( id->p_encoder->fmt_out.audio.i_channels,
962 id->p_decoder->fmt_in.audio.i_channels );
963 id->p_encoder->fmt_out.audio.i_original_channels =
964 id->p_decoder->fmt_in.audio.i_physical_channels;
965 if( id->p_decoder->fmt_in.audio.i_channels ==
966 id->p_encoder->fmt_out.audio.i_channels )
968 id->p_encoder->fmt_out.audio.i_physical_channels =
969 id->p_decoder->fmt_in.audio.i_physical_channels;
973 id->p_encoder->fmt_out.audio.i_physical_channels =
974 pi_channels_maps[id->p_encoder->fmt_out.audio.i_channels];
977 /* Build decoder -> filter -> encoder chain */
978 if( transcode_audio_new( p_stream, id ) )
980 msg_Err( p_stream, "cannot create audio chain" );
984 /* Open output stream */
985 id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
986 id->b_transcode = VLC_TRUE;
990 transcode_audio_close( p_stream, id );
994 date_Init( &id->interpolated_pts, p_fmt->audio.i_rate, 1 );
996 else if( p_fmt->i_cat == VIDEO_ES &&
997 (p_sys->i_vcodec != 0 || p_sys->psz_venc) )
1000 "creating video transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
1001 (char*)&p_fmt->i_codec, (char*)&p_sys->i_vcodec );
1003 /* Complete destination format */
1004 id->p_encoder->fmt_out.i_codec = p_sys->i_vcodec;
1005 id->p_encoder->fmt_out.video.i_width = p_sys->i_width & ~1;
1006 id->p_encoder->fmt_out.video.i_height = p_sys->i_height & ~1;
1007 id->p_encoder->fmt_out.i_bitrate = p_sys->i_vbitrate;
1009 /* Build decoder -> filter -> encoder chain */
1010 if( transcode_video_new( p_stream, id ) )
1012 msg_Err( p_stream, "cannot create video chain" );
1016 /* Stream will be added later on because we don't know
1017 * all the characteristics of the decoded stream yet */
1018 id->b_transcode = VLC_TRUE;
1020 if( p_sys->f_fps > 0 )
1022 id->p_encoder->fmt_out.video.i_frame_rate =
1023 (p_sys->f_fps * 1001) + 0.5;
1024 id->p_encoder->fmt_out.video.i_frame_rate_base = 1001;
1027 else if( p_fmt->i_cat == SPU_ES && (p_sys->i_scodec || p_sys->psz_senc) )
1029 msg_Dbg( p_stream, "creating subtitles transcoding from fcc=`%4.4s' "
1030 "to fcc=`%4.4s'", (char*)&p_fmt->i_codec,
1031 (char*)&p_sys->i_scodec );
1033 /* Complete destination format */
1034 id->p_encoder->fmt_out.i_codec = p_sys->i_scodec;
1036 /* build decoder -> filter -> encoder */
1037 if( transcode_spu_new( p_stream, id ) )
1039 msg_Err( p_stream, "cannot create subtitles chain" );
1043 /* open output stream */
1044 id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
1045 id->b_transcode = VLC_TRUE;
1049 transcode_spu_close( p_stream, id );
1053 else if( p_fmt->i_cat == SPU_ES && p_sys->b_soverlay )
1055 msg_Dbg( p_stream, "subtitles (fcc=`%4.4s') overlaying",
1056 (char*)&p_fmt->i_codec );
1058 id->b_transcode = VLC_TRUE;
1060 /* Build decoder -> filter -> overlaying chain */
1061 if( transcode_spu_new( p_stream, id ) )
1063 msg_Err( p_stream, "cannot create subtitles chain" );
1069 msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
1070 (char*)&p_fmt->i_codec );
1071 id->id = p_sys->p_out->pf_add( p_sys->p_out, p_fmt );
1072 id->b_transcode = VLC_FALSE;
1074 if( !id->id ) goto error;
1077 if( p_sys->b_sout_osd )
1079 /* Create a fake OSD menu elementary stream */
1080 if( !p_sys->b_es_osd && (p_sys->i_osdcodec != 0 || p_sys->psz_osdenc) )
1082 if( transcode_osd_new( p_stream, p_sys->id_osd ) )
1084 msg_Err( p_stream, "cannot create osd chain" );
1087 p_sys->b_es_osd = VLC_TRUE;
1095 vlc_object_detach( id->p_decoder );
1096 vlc_object_destroy( id->p_decoder );
1101 vlc_object_detach( id->p_encoder );
1102 es_format_Clean( &id->p_encoder->fmt_out );
1103 vlc_object_destroy( id->p_encoder );
1110 static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
1112 sout_stream_sys_t *p_sys = p_stream->p_sys;
1114 if( p_sys->b_es_osd )
1115 transcode_osd_close( p_stream, p_sys->id_osd );
1117 if( id->b_transcode )
1119 switch( id->p_decoder->fmt_in.i_cat )
1122 transcode_audio_close( p_stream, id );
1125 transcode_video_close( p_stream, id );
1128 transcode_spu_close( p_stream, id );
1133 if( id->id ) p_sys->p_out->pf_del( p_sys->p_out, id->id );
1137 vlc_object_detach( id->p_decoder );
1138 vlc_object_destroy( id->p_decoder );
1143 vlc_object_detach( id->p_encoder );
1144 es_format_Clean( &id->p_encoder->fmt_out );
1145 vlc_object_destroy( id->p_encoder );
1153 static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
1156 sout_stream_sys_t *p_sys = p_stream->p_sys;
1157 block_t *p_out = NULL;
1159 if( !id->b_transcode && id->id )
1161 /* Transcode OSD menu pictures. */
1162 if( p_sys->b_es_osd )
1164 transcode_osd_process( p_stream, id, p_buffer, &p_out );
1166 return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_buffer );
1168 else if( !id->b_transcode )
1170 block_Release( p_buffer );
1171 return VLC_EGENERIC;
1174 switch( id->p_decoder->fmt_in.i_cat )
1177 transcode_audio_process( p_stream, id, p_buffer, &p_out );
1181 if( transcode_video_process( p_stream, id, p_buffer, &p_out )
1184 return VLC_EGENERIC;
1189 if( transcode_spu_process( p_stream, id, p_buffer, &p_out ) !=
1192 return VLC_EGENERIC;
1198 block_Release( p_buffer );
1202 if( p_out ) return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_out );
1206 /****************************************************************************
1207 * decoder reencoder part
1208 ****************************************************************************/
1209 int audio_BitsPerSample( vlc_fourcc_t i_format )
1213 case VLC_FOURCC('u','8',' ',' '):
1214 case VLC_FOURCC('s','8',' ',' '):
1217 case VLC_FOURCC('u','1','6','l'):
1218 case VLC_FOURCC('s','1','6','l'):
1219 case VLC_FOURCC('u','1','6','b'):
1220 case VLC_FOURCC('s','1','6','b'):
1223 case VLC_FOURCC('u','2','4','l'):
1224 case VLC_FOURCC('s','2','4','l'):
1225 case VLC_FOURCC('u','2','4','b'):
1226 case VLC_FOURCC('s','2','4','b'):
1229 case VLC_FOURCC('u','3','2','l'):
1230 case VLC_FOURCC('s','3','2','l'):
1231 case VLC_FOURCC('u','3','2','b'):
1232 case VLC_FOURCC('s','3','2','b'):
1233 case VLC_FOURCC('f','l','3','2'):
1234 case VLC_FOURCC('f','i','3','2'):
1237 case VLC_FOURCC('f','l','6','4'):
1244 static filter_t *transcode_audio_filter_new( sout_stream_t *p_stream,
1245 sout_stream_id_t *id,
1246 es_format_t *p_fmt_in,
1247 es_format_t *p_fmt_out,
1250 sout_stream_sys_t *p_sys = p_stream->p_sys;
1251 filter_t *p_filter = vlc_object_create( p_stream, VLC_OBJECT_FILTER );
1253 vlc_object_attach( p_filter, p_stream );
1254 p_filter->pf_audio_buffer_new = (block_t* (*) (filter_t*, int))__block_New;
1256 p_filter->fmt_in = *p_fmt_in;
1257 p_filter->fmt_out = *p_fmt_out;
1259 p_filter->p_cfg = p_sys->p_afilters_cfg[id->i_ufilter];
1261 p_filter->p_module = module_Need( p_filter, "audio filter2", psz_name, 0 );
1262 if( p_filter->p_module )
1264 p_filter->fmt_out.audio.i_bitspersample =
1265 audio_BitsPerSample( p_filter->fmt_out.i_codec );
1266 *p_fmt_in = p_filter->fmt_out;
1270 vlc_object_detach( p_filter );
1271 vlc_object_destroy( p_filter );
1278 static int transcode_audio_new( sout_stream_t *p_stream,
1279 sout_stream_id_t *id )
1281 sout_stream_sys_t *p_sys = p_stream->p_sys;
1282 es_format_t fmt_last;
1289 /* Initialization of decoder structures */
1290 id->p_decoder->fmt_out = id->p_decoder->fmt_in;
1291 id->p_decoder->fmt_out.i_extra = 0;
1292 id->p_decoder->fmt_out.p_extra = 0;
1293 id->p_decoder->pf_decode_audio = 0;
1294 id->p_decoder->pf_aout_buffer_new = audio_new_buffer;
1295 id->p_decoder->pf_aout_buffer_del = audio_del_buffer;
1296 /* id->p_decoder->p_cfg = p_sys->p_audio_cfg; */
1298 id->p_decoder->p_module =
1299 module_Need( id->p_decoder, "decoder", "$codec", 0 );
1301 if( !id->p_decoder->p_module )
1303 msg_Err( p_stream, "cannot find decoder" );
1304 return VLC_EGENERIC;
1306 id->p_decoder->fmt_out.audio.i_bitspersample =
1307 audio_BitsPerSample( id->p_decoder->fmt_out.i_codec );
1308 fmt_last = id->p_decoder->fmt_out;
1309 /* FIX decoders so we don't have to do this */
1310 fmt_last.audio.i_rate = id->p_decoder->fmt_in.audio.i_rate;
1316 /* Initialization of encoder format structures */
1317 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1318 id->p_decoder->fmt_out.i_codec );
1319 id->p_encoder->fmt_in.audio.i_format = id->p_decoder->fmt_out.i_codec;
1321 /* Initialization of encoder format structures */
1322 es_format_Init( &id->p_encoder->fmt_in, AUDIO_ES, AOUT_FMT_S16_NE );
1323 id->p_encoder->fmt_in.audio.i_format = AOUT_FMT_S16_NE;
1324 id->p_encoder->fmt_in.audio.i_rate = id->p_encoder->fmt_out.audio.i_rate;
1325 id->p_encoder->fmt_in.audio.i_physical_channels =
1326 id->p_encoder->fmt_out.audio.i_physical_channels;
1327 id->p_encoder->fmt_in.audio.i_original_channels =
1328 id->p_encoder->fmt_out.audio.i_original_channels;
1329 id->p_encoder->fmt_in.audio.i_channels =
1330 id->p_encoder->fmt_out.audio.i_channels;
1331 id->p_encoder->fmt_in.audio.i_bitspersample =
1332 audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1334 id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
1336 id->p_encoder->p_module =
1337 module_Need( id->p_encoder, "encoder", p_sys->psz_aenc, VLC_TRUE );
1338 if( !id->p_encoder->p_module )
1340 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_aenc );
1341 module_Unneed( id->p_decoder, id->p_decoder->p_module );
1342 id->p_decoder->p_module = 0;
1343 return VLC_EGENERIC;
1345 id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
1346 id->p_encoder->fmt_in.audio.i_bitspersample =
1347 audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1349 /* Load conversion filters */
1350 if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels ||
1351 fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate )
1353 /* We'll have to go through fl32 first */
1354 es_format_t fmt_out = id->p_encoder->fmt_in;
1355 fmt_out.i_codec = fmt_out.audio.i_format = VLC_FOURCC('f','l','3','2');
1357 id->pp_filter[id->i_filter] =
1358 transcode_audio_filter_new( p_stream, id, &fmt_last, &fmt_out, NULL );
1360 if( id->pp_filter[id->i_filter] ) id->i_filter++;
1363 for( i = 0; i < TRANSCODE_FILTERS; i++ )
1365 if( (fmt_last.audio.i_channels !=
1366 id->p_encoder->fmt_in.audio.i_channels) ||
1367 (fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate) ||
1368 (fmt_last.i_codec != id->p_encoder->fmt_in.i_codec) )
1370 id->pp_filter[id->i_filter] =
1371 transcode_audio_filter_new( p_stream, id, &fmt_last,
1372 &id->p_encoder->fmt_in, NULL );
1374 if( id->pp_filter[id->i_filter] )
1381 /* Final checks to see if conversions were successful */
1382 if( fmt_last.i_codec != id->p_encoder->fmt_in.i_codec )
1384 msg_Err( p_stream, "no audio filter found (%4.4s->%4.4s)",
1385 (char *)&fmt_last.i_codec,
1386 (char *)&id->p_encoder->fmt_in.i_codec );
1387 transcode_audio_close( p_stream, id );
1388 return VLC_EGENERIC;
1391 /* Load user specified audio filters now */
1392 for( i = 0; (i < p_sys->i_afilters) &&
1393 (id->i_ufilter < TRANSCODE_FILTERS); i++ )
1395 id->pp_ufilter[id->i_ufilter] =
1396 transcode_audio_filter_new( p_stream, id, &fmt_last,
1397 &id->p_encoder->fmt_in,
1398 p_sys->psz_afilters[i] );
1400 if( id->pp_ufilter[id->i_ufilter] )
1406 if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels )
1408 msg_Err( p_stream, "no audio filter found for mixing from"
1409 " %i to %i channels", fmt_last.audio.i_channels,
1410 id->p_encoder->fmt_in.audio.i_channels );
1412 /* FIXME : this might work, but only if the encoder is restarted */
1413 id->p_encoder->fmt_in.audio.i_channels = fmt_last.audio.i_channels;
1414 id->p_encoder->fmt_out.audio.i_channels = fmt_last.audio.i_channels;
1416 id->p_encoder->fmt_in.audio.i_physical_channels =
1417 id->p_encoder->fmt_in.audio.i_original_channels =
1418 fmt_last.audio.i_physical_channels;
1419 id->p_encoder->fmt_out.audio.i_physical_channels =
1420 id->p_encoder->fmt_out.audio.i_original_channels =
1421 fmt_last.audio.i_physical_channels;
1423 transcode_audio_close( p_stream, id );
1424 return VLC_EGENERIC;
1428 if( fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate )
1430 msg_Err( p_stream, "no audio filter found for resampling from"
1431 " %iHz to %iHz", fmt_last.audio.i_rate,
1432 id->p_encoder->fmt_in.audio.i_rate );
1434 /* FIXME : this might work, but only if the encoder is restarted */
1435 id->p_encoder->fmt_in.audio.i_rate = fmt_last.audio.i_rate;
1436 id->p_encoder->fmt_out.audio.i_rate = fmt_last.audio.i_rate;
1438 transcode_audio_close( p_stream, id );
1439 return VLC_EGENERIC;
1443 /* FIXME: Hack for mp3 transcoding support */
1444 if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC( 'm','p','3',' ' ) )
1445 id->p_encoder->fmt_out.i_codec = VLC_FOURCC( 'm','p','g','a' );
1450 static void transcode_audio_close( sout_stream_t *p_stream,
1451 sout_stream_id_t *id )
1456 if( id->p_decoder->p_module )
1457 module_Unneed( id->p_decoder, id->p_decoder->p_module );
1458 id->p_decoder->p_module = 0;
1461 if( id->p_encoder->p_module )
1462 module_Unneed( id->p_encoder, id->p_encoder->p_module );
1463 id->p_encoder->p_module = 0;
1466 for( i = 0; i < id->i_filter; i++ )
1468 vlc_object_detach( id->pp_filter[i] );
1469 if( id->pp_filter[i]->p_module )
1470 module_Unneed( id->pp_filter[i], id->pp_filter[i]->p_module );
1471 vlc_object_destroy( id->pp_filter[i] );
1473 for( i = 0; i < id->i_ufilter; i++ )
1475 vlc_object_detach( id->pp_ufilter[i] );
1476 if( id->pp_ufilter[i]->p_module )
1477 module_Unneed( id->pp_ufilter[i], id->pp_ufilter[i]->p_module );
1478 vlc_object_destroy( id->pp_ufilter[i] );
1482 static int transcode_audio_process( sout_stream_t *p_stream,
1483 sout_stream_id_t *id,
1484 block_t *in, block_t **out )
1486 sout_stream_sys_t *p_sys = p_stream->p_sys;
1487 aout_buffer_t *p_audio_buf;
1488 block_t *p_block, *p_audio_block;
1491 input_thread_t *p_input = NULL;
1493 if( p_stream->p_parent->p_parent && p_stream->p_parent->p_parent->
1494 i_object_type == VLC_OBJECT_INPUT )
1495 p_input = (input_thread_t *)p_stream->p_parent->p_parent;
1497 while( (p_audio_buf = id->p_decoder->pf_decode_audio( id->p_decoder,
1501 stats_UpdateInteger( p_input, p_input->counters.p_decoded_audio,
1503 if( p_sys->b_master_sync )
1505 mtime_t i_dts = date_Get( &id->interpolated_pts ) + 1;
1506 if ( p_audio_buf->start_date - i_dts > MASTER_SYNC_MAX_DRIFT
1507 || p_audio_buf->start_date - i_dts < -MASTER_SYNC_MAX_DRIFT )
1509 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
1510 date_Set( &id->interpolated_pts, p_audio_buf->start_date );
1511 i_dts = p_audio_buf->start_date + 1;
1513 p_sys->i_master_drift = p_audio_buf->start_date - i_dts;
1514 date_Increment( &id->interpolated_pts, p_audio_buf->i_nb_samples );
1515 p_audio_buf->start_date -= p_sys->i_master_drift;
1516 p_audio_buf->end_date -= p_sys->i_master_drift;
1519 p_audio_block = p_audio_buf->p_sys;
1520 p_audio_block->i_buffer = p_audio_buf->i_nb_bytes;
1521 p_audio_block->i_dts = p_audio_block->i_pts =
1522 p_audio_buf->start_date;
1523 p_audio_block->i_length = p_audio_buf->end_date -
1524 p_audio_buf->start_date;
1525 p_audio_block->i_samples = p_audio_buf->i_nb_samples;
1527 /* Run filter chain */
1528 for( i = 0; i < id->i_filter; i++ )
1531 id->pp_filter[i]->pf_audio_filter( id->pp_filter[i],
1535 /* Run user specified filter chain */
1536 for( i = 0; i < id->i_ufilter; i++ )
1539 id->pp_ufilter[i]->pf_audio_filter( id->pp_ufilter[i],
1543 p_audio_buf->p_buffer = p_audio_block->p_buffer;
1544 p_audio_buf->i_nb_bytes = p_audio_block->i_buffer;
1545 p_audio_buf->i_nb_samples = p_audio_block->i_samples;
1546 p_audio_buf->start_date = p_audio_block->i_dts;
1547 p_audio_buf->end_date = p_audio_block->i_dts + p_audio_block->i_length;
1549 p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf );
1550 block_ChainAppend( out, p_block );
1551 block_Release( p_audio_block );
1552 free( p_audio_buf );
1558 static void audio_release_buffer( aout_buffer_t *p_buffer )
1560 if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
1561 if( p_buffer ) free( p_buffer );
1564 static aout_buffer_t *audio_new_buffer( decoder_t *p_dec, int i_samples )
1566 aout_buffer_t *p_buffer;
1570 if( p_dec->fmt_out.audio.i_bitspersample )
1572 i_size = i_samples * p_dec->fmt_out.audio.i_bitspersample / 8 *
1573 p_dec->fmt_out.audio.i_channels;
1575 else if( p_dec->fmt_out.audio.i_bytes_per_frame &&
1576 p_dec->fmt_out.audio.i_frame_length )
1578 i_size = i_samples * p_dec->fmt_out.audio.i_bytes_per_frame /
1579 p_dec->fmt_out.audio.i_frame_length;
1583 i_size = i_samples * 4 * p_dec->fmt_out.audio.i_channels;
1586 p_buffer = malloc( sizeof(aout_buffer_t) );
1587 p_buffer->pf_release = audio_release_buffer;
1588 p_buffer->p_sys = p_block = block_New( p_dec, i_size );
1590 p_buffer->p_buffer = p_block->p_buffer;
1591 p_buffer->i_size = p_buffer->i_nb_bytes = p_block->i_buffer;
1592 p_buffer->i_nb_samples = i_samples;
1593 p_block->i_samples = i_samples;
1598 static void audio_del_buffer( decoder_t *p_dec, aout_buffer_t *p_buffer )
1600 if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
1601 if( p_buffer ) free( p_buffer );
1607 static int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_t *id )
1609 sout_stream_sys_t *p_sys = p_stream->p_sys;
1613 * Initialization of decoder structures
1615 id->p_decoder->fmt_out = id->p_decoder->fmt_in;
1616 id->p_decoder->fmt_out.i_extra = 0;
1617 id->p_decoder->fmt_out.p_extra = 0;
1618 id->p_decoder->pf_decode_video = 0;
1619 id->p_decoder->pf_vout_buffer_new = video_new_buffer_decoder;
1620 id->p_decoder->pf_vout_buffer_del = video_del_buffer_decoder;
1621 id->p_decoder->pf_picture_link = video_link_picture_decoder;
1622 id->p_decoder->pf_picture_unlink = video_unlink_picture_decoder;
1623 id->p_decoder->p_owner = malloc( sizeof(decoder_owner_sys_t) );
1624 for( i = 0; i < PICTURE_RING_SIZE; i++ )
1625 id->p_decoder->p_owner->pp_pics[i] = 0;
1626 id->p_decoder->p_owner->p_sys = p_sys;
1627 /* id->p_decoder->p_cfg = p_sys->p_video_cfg; */
1629 id->p_decoder->p_module =
1630 module_Need( id->p_decoder, "decoder", "$codec", 0 );
1632 if( !id->p_decoder->p_module )
1634 msg_Err( p_stream, "cannot find decoder" );
1635 return VLC_EGENERIC;
1640 * Because some info about the decoded input will only be available
1641 * once the first frame is decoded, we actually only test the availability
1642 * of the encoder here.
1645 /* Initialization of encoder format structures */
1646 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1647 id->p_decoder->fmt_out.i_codec );
1648 id->p_encoder->fmt_in.video.i_chroma = id->p_decoder->fmt_out.i_codec;
1650 /* The dimensions will be set properly later on.
1651 * Just put sensible values so we can test an encoder is available. */
1652 id->p_encoder->fmt_in.video.i_width =
1653 id->p_encoder->fmt_out.video.i_width ?
1654 id->p_encoder->fmt_out.video.i_width :
1655 id->p_decoder->fmt_in.video.i_width ?
1656 id->p_decoder->fmt_in.video.i_width : 16;
1657 id->p_encoder->fmt_in.video.i_height =
1658 id->p_encoder->fmt_out.video.i_height ?
1659 id->p_encoder->fmt_out.video.i_height :
1660 id->p_decoder->fmt_in.video.i_height ?
1661 id->p_decoder->fmt_in.video.i_height : 16;
1662 id->p_encoder->fmt_in.video.i_frame_rate = 25;
1663 id->p_encoder->fmt_in.video.i_frame_rate_base = 1;
1665 id->p_encoder->i_threads = p_sys->i_threads;
1666 id->p_encoder->p_cfg = p_sys->p_video_cfg;
1668 id->p_encoder->p_module =
1669 module_Need( id->p_encoder, "encoder", p_sys->psz_venc, VLC_TRUE );
1670 if( !id->p_encoder->p_module )
1672 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_venc );
1673 module_Unneed( id->p_decoder, id->p_decoder->p_module );
1674 id->p_decoder->p_module = 0;
1675 return VLC_EGENERIC;
1678 /* Close the encoder.
1679 * We'll open it only when we have the first frame. */
1680 module_Unneed( id->p_encoder, id->p_encoder->p_module );
1681 if( id->p_encoder->fmt_out.p_extra )
1682 free( id->p_encoder->fmt_out.p_extra );
1683 id->p_encoder->p_module = NULL;
1685 if( p_sys->i_threads >= 1 )
1687 int i_priority = p_sys->b_high_priority ? VLC_THREAD_PRIORITY_OUTPUT :
1688 VLC_THREAD_PRIORITY_VIDEO;
1689 p_sys->id_video = id;
1690 vlc_mutex_init( p_stream, &p_sys->lock_out );
1691 vlc_cond_init( p_stream, &p_sys->cond );
1692 memset( p_sys->pp_pics, 0, sizeof(p_sys->pp_pics) );
1693 p_sys->i_first_pic = 0;
1694 p_sys->i_last_pic = 0;
1695 p_sys->p_buffers = NULL;
1696 p_sys->b_die = p_sys->b_error = 0;
1697 if( vlc_thread_create( p_sys, "encoder", EncoderThread, i_priority,
1700 msg_Err( p_stream, "cannot spawn encoder thread" );
1701 module_Unneed( id->p_decoder, id->p_decoder->p_module );
1702 id->p_decoder->p_module = 0;
1703 return VLC_EGENERIC;
1710 static int transcode_video_encoder_open( sout_stream_t *p_stream,
1711 sout_stream_id_t *id )
1713 sout_stream_sys_t *p_sys = p_stream->p_sys;
1715 /* Calculate scaling, padding, cropping etc. */
1716 /* width/height of source */
1717 int i_src_width = id->p_decoder->fmt_out.video.i_width;
1718 int i_src_height = id->p_decoder->fmt_out.video.i_height;
1720 /* with/height scaling */
1721 float f_scale_width = 1;
1722 float f_scale_height = 1;
1724 /* width/height of output stream */
1729 float f_aspect = (float)id->p_decoder->fmt_out.video.i_aspect /
1732 msg_Dbg( p_stream, "decoder aspect is %i:%i",
1733 id->p_decoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
1735 /* Change f_aspect from source frame to source pixel */
1736 f_aspect = f_aspect * i_src_height / i_src_width;
1737 msg_Dbg( p_stream, "source pixel aspect is %f:1", f_aspect );
1739 /* width/height after cropping */
1740 p_sys->i_src_x_offset = p_sys->i_crop_left & ~1;
1741 p_sys->i_src_y_offset = p_sys->i_crop_top & ~1;
1742 p_sys->i_crop_width = i_src_width - ( p_sys->i_crop_left & ~1 ) -
1743 ( p_sys->i_crop_right & ~1 );
1744 p_sys->i_crop_height = i_src_height - ( p_sys->i_crop_top & ~1 ) -
1745 ( p_sys->i_crop_bottom & ~1 );
1747 /* Calculate scaling factor for specified parameters */
1748 if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1749 id->p_encoder->fmt_out.video.i_height <= 0 && p_sys->f_scale )
1751 /* Global scaling. Make sure width will remain a factor of 16 */
1754 int i_new_width = i_src_width * p_sys->f_scale;
1756 if( i_new_width % 16 <= 7 && i_new_width >= 16 )
1757 i_new_width -= i_new_width % 16;
1759 i_new_width += 16 - i_new_width % 16;
1761 f_real_scale = (float)( i_new_width ) / (float) i_src_width;
1763 i_new_height = __MAX( 16, i_src_height * (float)f_real_scale );
1765 f_scale_width = f_real_scale;
1766 f_scale_height = (float) i_new_height / (float) i_src_height;
1768 else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1769 id->p_encoder->fmt_out.video.i_height <= 0 )
1771 /* Only width specified */
1772 f_scale_width = (float)id->p_encoder->fmt_out.video.i_width /
1773 p_sys->i_crop_width;
1774 f_scale_height = f_scale_width;
1776 else if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1777 id->p_encoder->fmt_out.video.i_height > 0 )
1779 /* Only height specified */
1780 f_scale_height = (float)id->p_encoder->fmt_out.video.i_height /
1781 p_sys->i_crop_height;
1782 f_scale_width = f_scale_height;
1784 else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1785 id->p_encoder->fmt_out.video.i_height > 0 )
1787 /* Width and height specified */
1788 f_scale_width = (float)id->p_encoder->fmt_out.video.i_width
1789 / p_sys->i_crop_width;
1790 f_scale_height = (float)id->p_encoder->fmt_out.video.i_height
1791 / p_sys->i_crop_height;
1794 /* check maxwidth and maxheight
1795 * note: maxwidth and maxheight currently does not handle
1796 * canvas and padding, just scaling and cropping.
1798 if( p_sys->i_maxwidth && f_scale_width > (float)p_sys->i_maxwidth /
1799 p_sys->i_crop_width )
1801 f_scale_width = (float)p_sys->i_maxwidth / p_sys->i_crop_width;
1803 if( p_sys->i_maxheight && f_scale_height > (float)p_sys->i_maxheight /
1804 p_sys->i_crop_height )
1806 f_scale_height = (float)p_sys->i_maxheight / p_sys->i_crop_height;
1809 /* Change aspect ratio from source pixel to scaled pixel */
1810 f_aspect = f_aspect * f_scale_height / f_scale_width;
1811 msg_Dbg( p_stream, "scaled pixel aspect is %f:1", f_aspect );
1813 /* Correct scaling for target aspect ratio
1814 * Shrink video if necessary
1816 if ( p_sys->i_canvas_aspect > 0 )
1818 float f_target_aspect = (float)p_sys->i_canvas_aspect /
1821 if( p_sys->i_canvas_width > 0 && p_sys->i_canvas_height > 0)
1823 /* Calculate pixel aspect of canvas */
1824 f_target_aspect = f_target_aspect / p_sys->i_canvas_width *
1825 p_sys->i_canvas_height;
1827 if( f_target_aspect > f_aspect )
1829 /* Reduce width scale to increase aspect */
1830 f_scale_width = f_scale_width * f_aspect / f_target_aspect;
1834 /* Reduce height scale to decrease aspect */
1835 f_scale_height = f_scale_height * f_target_aspect / f_aspect;
1837 f_aspect = f_target_aspect;
1838 msg_Dbg( p_stream, "canvas scaled pixel aspect is %f:1", f_aspect );
1841 /* f_scale_width and f_scale_height are now final */
1842 /* Calculate width, height from scaling
1843 * Make sure its multiple of 2
1845 i_dst_width = 2 * (int)( p_sys->i_crop_width * f_scale_width / 2 + 0.5 );
1847 (int)( p_sys->i_crop_height * f_scale_height / 2 + 0.5 );
1849 p_sys->i_nopadd_width = i_dst_width;
1850 p_sys->i_nopadd_height = i_dst_height;
1851 p_sys->i_dst_x_offset = 0;
1852 p_sys->i_dst_y_offset = 0;
1854 /* Handle canvas and padding */
1855 if( p_sys->i_canvas_width <= 0 )
1857 /* No canvas width set, add explicit padding border */
1858 i_dst_width = p_sys->i_nopadd_width + ( p_sys->i_padd_left & ~1 ) +
1859 ( p_sys->i_padd_right & ~1 );
1860 p_sys->i_dst_x_offset = ( p_sys->i_padd_left & ~1 );
1864 /* Canvas set, check if we have to padd or crop */
1865 if( p_sys->i_canvas_width < p_sys->i_nopadd_width )
1867 /* need to crop more, but keep same scaling */
1868 int i_crop = 2 * (int)( ( p_sys->i_canvas_width & ~1 ) /
1869 f_scale_width / 2 + 0.5 );
1871 p_sys->i_src_x_offset += ( ( p_sys->i_crop_width - i_crop ) / 2 )
1873 p_sys->i_crop_width = i_crop;
1874 i_dst_width = p_sys->i_canvas_width & ~1;
1875 p_sys->i_nopadd_width = i_dst_width;
1877 else if( p_sys->i_canvas_width > p_sys->i_nopadd_width )
1880 i_dst_width = p_sys->i_canvas_width & ~1;
1881 p_sys->i_dst_x_offset = ( i_dst_width - p_sys->i_nopadd_width )/2;
1882 p_sys->i_dst_x_offset = p_sys->i_dst_x_offset & ~1;
1886 if( p_sys->i_canvas_height <= 0 )
1888 /* No canvas set, add padding border */
1889 i_dst_height = p_sys->i_nopadd_height + ( p_sys->i_padd_top & ~1 ) +
1890 ( p_sys->i_padd_bottom & ~1 );
1891 p_sys->i_dst_y_offset = ( p_sys->i_padd_top & ~1 );
1895 /* Canvas set, check if we have to padd or crop */
1896 if( p_sys->i_canvas_height < p_sys->i_nopadd_height )
1898 /* need to crop more, but keep same scaling */
1899 int i_crop = 2 * (int)( ( p_sys->i_canvas_height & ~1 ) /
1900 f_scale_height / 2 + 0.5 );
1902 p_sys->i_src_y_offset += ( ( p_sys->i_crop_height - i_crop ) / 2 )
1904 p_sys->i_crop_height = i_crop;
1905 i_dst_height = p_sys->i_canvas_height & ~1;
1906 p_sys->i_nopadd_height = i_dst_height;
1908 else if( p_sys->i_canvas_height > p_sys->i_nopadd_height )
1911 i_dst_height = p_sys->i_canvas_height & ~1;
1912 p_sys->i_dst_y_offset = ( i_dst_height - p_sys->i_nopadd_height )
1914 p_sys->i_dst_y_offset = p_sys->i_dst_y_offset & ~1;
1918 /* Change aspect ratio from scaled pixel to output frame */
1919 f_aspect = f_aspect * i_dst_width / i_dst_height;
1921 /* Store calculated values */
1922 id->p_encoder->fmt_out.video.i_width = i_dst_width;
1923 id->p_encoder->fmt_out.video.i_height = i_dst_height;
1925 id->p_encoder->fmt_in.video.i_width = i_dst_width;
1926 id->p_encoder->fmt_in.video.i_height = i_dst_height;
1928 msg_Dbg( p_stream, "source %ix%i, crop %ix%i, "
1929 "destination %ix%i, padding %ix%i",
1930 i_src_width, i_src_height,
1931 p_sys->i_crop_width, p_sys->i_crop_height,
1932 p_sys->i_nopadd_width, p_sys->i_nopadd_height,
1933 i_dst_width, i_dst_height
1936 /* Handle frame rate conversion */
1937 if( !id->p_encoder->fmt_out.video.i_frame_rate ||
1938 !id->p_encoder->fmt_out.video.i_frame_rate_base )
1940 if( id->p_decoder->fmt_out.video.i_frame_rate &&
1941 id->p_decoder->fmt_out.video.i_frame_rate_base )
1943 id->p_encoder->fmt_out.video.i_frame_rate =
1944 id->p_decoder->fmt_out.video.i_frame_rate;
1945 id->p_encoder->fmt_out.video.i_frame_rate_base =
1946 id->p_decoder->fmt_out.video.i_frame_rate_base;
1950 /* Pick a sensible default value */
1951 id->p_encoder->fmt_out.video.i_frame_rate = 25;
1952 id->p_encoder->fmt_out.video.i_frame_rate_base = 1;
1956 id->p_encoder->fmt_in.video.i_frame_rate =
1957 id->p_encoder->fmt_out.video.i_frame_rate;
1958 id->p_encoder->fmt_in.video.i_frame_rate_base =
1959 id->p_encoder->fmt_out.video.i_frame_rate_base;
1961 date_Init( &id->interpolated_pts,
1962 id->p_encoder->fmt_out.video.i_frame_rate,
1963 id->p_encoder->fmt_out.video.i_frame_rate_base );
1965 /* Check whether a particular aspect ratio was requested */
1966 if( !id->p_encoder->fmt_out.video.i_aspect )
1968 id->p_encoder->fmt_out.video.i_aspect = (int)( f_aspect * VOUT_ASPECT_FACTOR + 0.5 );
1970 id->p_encoder->fmt_in.video.i_aspect =
1971 id->p_encoder->fmt_out.video.i_aspect;
1973 msg_Dbg( p_stream, "encoder aspect is %i:%i", id->p_encoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
1975 id->p_encoder->p_module =
1976 module_Need( id->p_encoder, "encoder", p_sys->psz_venc, VLC_TRUE );
1977 if( !id->p_encoder->p_module )
1979 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_venc );
1980 return VLC_EGENERIC;
1983 id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
1985 /* Hack for mp2v/mp1v transcoding support */
1986 if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','1','v') ||
1987 id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','2','v') )
1989 id->p_encoder->fmt_out.i_codec = VLC_FOURCC('m','p','g','v');
1992 id->id = p_stream->p_sys->p_out->pf_add( p_stream->p_sys->p_out,
1993 &id->p_encoder->fmt_out );
1996 msg_Err( p_stream, "cannot add this stream" );
1997 return VLC_EGENERIC;
2003 static void transcode_video_close( sout_stream_t *p_stream,
2004 sout_stream_id_t *id )
2008 if( p_stream->p_sys->i_threads >= 1 )
2010 vlc_mutex_lock( &p_stream->p_sys->lock_out );
2011 p_stream->p_sys->b_die = 1;
2012 vlc_cond_signal( &p_stream->p_sys->cond );
2013 vlc_mutex_unlock( &p_stream->p_sys->lock_out );
2014 vlc_thread_join( p_stream->p_sys );
2015 vlc_mutex_destroy( &p_stream->p_sys->lock_out );
2016 vlc_cond_destroy( &p_stream->p_sys->cond );
2020 if( id->p_decoder->p_module )
2021 module_Unneed( id->p_decoder, id->p_decoder->p_module );
2023 if( id->p_decoder->p_owner )
2025 /* Clean-up pictures ring buffer */
2026 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2028 if( id->p_decoder->p_owner->pp_pics[i] )
2029 video_del_buffer( VLC_OBJECT(id->p_decoder),
2030 id->p_decoder->p_owner->pp_pics[i] );
2032 free( id->p_decoder->p_owner );
2036 if( id->p_encoder->p_module )
2037 module_Unneed( id->p_encoder, id->p_encoder->p_module );
2040 for( i = 0; i < id->i_filter; i++ )
2042 vlc_object_detach( id->pp_filter[i] );
2043 if( id->pp_filter[i]->p_module )
2044 module_Unneed( id->pp_filter[i], id->pp_filter[i]->p_module );
2046 /* Clean-up pictures ring buffer */
2047 for( j = 0; j < PICTURE_RING_SIZE; j++ )
2049 if( id->pp_filter[i]->p_owner->pp_pics[j] )
2050 video_del_buffer( VLC_OBJECT(id->pp_filter[i]),
2051 id->pp_filter[i]->p_owner->pp_pics[j] );
2053 free( id->pp_filter[i]->p_owner );
2054 vlc_object_destroy( id->pp_filter[i] );
2055 id->pp_filter[i] = NULL;
2058 for( i = 0; i < id->i_ufilter; i++ )
2060 vlc_object_detach( id->pp_ufilter[i] );
2061 if( id->pp_ufilter[i]->p_module )
2062 module_Unneed( id->pp_ufilter[i], id->pp_ufilter[i]->p_module );
2064 /* Clean-up pictures ring buffer */
2065 for( j = 0; j < PICTURE_RING_SIZE; j++ )
2067 if( id->pp_ufilter[i]->p_owner->pp_pics[j] )
2068 video_del_buffer( VLC_OBJECT(id->pp_ufilter[i]),
2069 id->pp_ufilter[i]->p_owner->pp_pics[j] );
2071 free( id->pp_ufilter[i]->p_owner );
2072 vlc_object_destroy( id->pp_ufilter[i] );
2073 id->pp_ufilter[i] = NULL;
2077 static int transcode_video_process( sout_stream_t *p_stream,
2078 sout_stream_id_t *id,
2079 block_t *in, block_t **out )
2081 sout_stream_sys_t *p_sys = p_stream->p_sys;
2082 int i_duplicate = 1, i;
2083 picture_t *p_pic, *p_pic2 = NULL;
2085 input_thread_t *p_input = NULL;
2087 if( p_stream->p_parent->p_parent && p_stream->p_parent->p_parent->
2088 i_object_type == VLC_OBJECT_INPUT )
2089 p_input = (input_thread_t *)p_stream->p_parent->p_parent;
2091 while( (p_pic = id->p_decoder->pf_decode_video( id->p_decoder, &in )) )
2093 subpicture_t *p_subpic = 0;
2095 stats_UpdateInteger( p_input, p_input->counters.p_decoded_video,
2098 if( p_stream->p_sout->i_out_pace_nocontrol && p_sys->b_hurry_up )
2100 mtime_t current_date = mdate();
2101 if( current_date + 50000 > p_pic->date )
2103 msg_Dbg( p_stream, "late picture skipped ("I64Fd")",
2104 current_date + 50000 - p_pic->date );
2105 p_pic->pf_release( p_pic );
2110 if( p_sys->b_master_sync )
2112 mtime_t i_video_drift;
2113 mtime_t i_master_drift = p_sys->i_master_drift;
2116 i_pts = date_Get( &id->interpolated_pts ) + 1;
2117 if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2118 || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2120 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2121 date_Set( &id->interpolated_pts, p_pic->date );
2122 i_pts = p_pic->date + 1;
2124 i_video_drift = p_pic->date - i_pts;
2127 /* Set the pts of the frame being encoded */
2128 p_pic->date = i_pts;
2130 if( i_video_drift < i_master_drift - 50000 )
2133 msg_Dbg( p_stream, "dropping frame (%i)",
2134 (int)(i_video_drift - i_master_drift) );
2136 p_pic->pf_release( p_pic );
2139 else if( i_video_drift > i_master_drift + 50000 )
2142 msg_Dbg( p_stream, "adding frame (%i)",
2143 (int)(i_video_drift - i_master_drift) );
2149 if( !id->p_encoder->p_module )
2151 if( transcode_video_encoder_open( p_stream, id ) != VLC_SUCCESS )
2153 p_pic->pf_release( p_pic );
2154 transcode_video_close( p_stream, id );
2155 id->b_transcode = VLC_FALSE;
2156 return VLC_EGENERIC;
2160 if( p_stream->p_sys->b_deinterlace )
2162 id->pp_filter[id->i_filter] =
2163 vlc_object_create( p_stream, VLC_OBJECT_FILTER );
2164 vlc_object_attach( id->pp_filter[id->i_filter], p_stream );
2166 id->pp_filter[id->i_filter]->pf_vout_buffer_new =
2167 video_new_buffer_filter;
2168 id->pp_filter[id->i_filter]->pf_vout_buffer_del =
2169 video_del_buffer_filter;
2171 id->pp_filter[id->i_filter]->fmt_in = id->p_decoder->fmt_out;
2172 id->pp_filter[id->i_filter]->fmt_out = id->p_decoder->fmt_out;
2173 id->pp_filter[id->i_filter]->p_cfg = p_sys->p_deinterlace_cfg;
2174 id->pp_filter[id->i_filter]->p_module =
2175 module_Need( id->pp_filter[id->i_filter],
2176 "video filter2", p_sys->psz_deinterlace, 0 );
2177 if( id->pp_filter[id->i_filter]->p_module )
2179 id->pp_filter[id->i_filter]->p_owner =
2180 malloc( sizeof(filter_owner_sys_t) );
2181 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2182 id->pp_filter[id->i_filter]->p_owner->pp_pics[i] = 0;
2183 id->pp_filter[id->i_filter]->p_owner->p_sys = p_sys;
2189 msg_Dbg( p_stream, "no video filter found" );
2190 vlc_object_detach( id->pp_filter[id->i_filter] );
2191 vlc_object_destroy( id->pp_filter[id->i_filter] );
2195 /* Check if we need a filter for chroma conversion or resizing */
2196 if( id->p_decoder->fmt_out.video.i_chroma !=
2197 id->p_encoder->fmt_in.video.i_chroma ||
2199 (int)id->p_decoder->fmt_out.video.i_width != p_sys->i_crop_width ||
2200 p_sys->i_crop_width != p_sys->i_nopadd_width ||
2201 p_sys->i_nopadd_width != (int)id->p_encoder->fmt_out.video.i_width ||
2203 (int)id->p_decoder->fmt_out.video.i_height != p_sys->i_crop_height ||
2204 p_sys->i_crop_height != p_sys->i_nopadd_height ||
2205 p_sys->i_nopadd_height != (int)id->p_encoder->fmt_out.video.i_height)
2207 id->pp_filter[id->i_filter] =
2208 vlc_object_create( p_stream, VLC_OBJECT_FILTER );
2209 vlc_object_attach( id->pp_filter[id->i_filter], p_stream );
2211 id->pp_filter[id->i_filter]->pf_vout_buffer_new =
2212 video_new_buffer_filter;
2213 id->pp_filter[id->i_filter]->pf_vout_buffer_del =
2214 video_del_buffer_filter;
2216 id->pp_filter[id->i_filter]->fmt_in = id->p_decoder->fmt_out;
2217 id->pp_filter[id->i_filter]->fmt_out = id->p_encoder->fmt_in;
2218 id->pp_filter[id->i_filter]->p_cfg = NULL;
2220 id->pp_filter[id->i_filter]->fmt_in.video.i_x_offset = p_sys->i_src_x_offset;
2221 id->pp_filter[id->i_filter]->fmt_in.video.i_y_offset = p_sys->i_src_y_offset;
2222 id->pp_filter[id->i_filter]->fmt_in.video.i_visible_width = p_sys->i_crop_width;
2223 id->pp_filter[id->i_filter]->fmt_in.video.i_visible_height = p_sys->i_crop_height;
2225 id->pp_filter[id->i_filter]->fmt_out.video.i_x_offset = p_sys->i_dst_x_offset;
2226 id->pp_filter[id->i_filter]->fmt_out.video.i_y_offset = p_sys->i_dst_y_offset;
2227 id->pp_filter[id->i_filter]->fmt_out.video.i_visible_width = p_sys->i_nopadd_width;
2228 id->pp_filter[id->i_filter]->fmt_out.video.i_visible_height = p_sys->i_nopadd_height;
2230 id->pp_filter[id->i_filter]->p_module =
2231 module_Need( id->pp_filter[id->i_filter],
2232 "crop padd", 0, 0 );
2233 if( id->pp_filter[id->i_filter]->p_module )
2235 id->pp_filter[id->i_filter]->p_owner =
2236 malloc( sizeof(filter_owner_sys_t) );
2237 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2238 id->pp_filter[id->i_filter]->p_owner->pp_pics[i] = 0;
2239 id->pp_filter[id->i_filter]->p_owner->p_sys = p_sys;
2245 msg_Dbg( p_stream, "no video filter found" );
2246 vlc_object_detach( id->pp_filter[id->i_filter] );
2247 vlc_object_destroy( id->pp_filter[id->i_filter] );
2249 p_pic->pf_release( p_pic );
2250 transcode_video_close( p_stream, id );
2251 id->b_transcode = VLC_FALSE;
2252 return VLC_EGENERIC;
2256 for( i = 0; (i < p_sys->i_vfilters) && (id->i_ufilter < TRANSCODE_FILTERS); i++ )
2258 id->pp_ufilter[id->i_ufilter] =
2259 vlc_object_create( p_stream, VLC_OBJECT_FILTER );
2260 vlc_object_attach( id->pp_ufilter[id->i_ufilter], p_stream );
2262 id->pp_ufilter[id->i_ufilter]->pf_vout_buffer_new =
2263 video_new_buffer_filter;
2264 id->pp_ufilter[id->i_ufilter]->pf_vout_buffer_del =
2265 video_del_buffer_filter;
2267 id->pp_ufilter[id->i_ufilter]->fmt_in = id->p_encoder->fmt_in;
2268 id->pp_ufilter[id->i_ufilter]->fmt_out = id->p_encoder->fmt_in;
2269 id->pp_ufilter[id->i_ufilter]->p_cfg = p_sys->p_vfilters_cfg[i];
2270 id->pp_ufilter[id->i_ufilter]->p_module =
2271 module_Need( id->pp_ufilter[id->i_ufilter],
2272 "video filter2", p_sys->psz_vfilters[i], 0 );
2273 if( id->pp_ufilter[id->i_ufilter]->p_module )
2275 id->pp_ufilter[id->i_ufilter]->p_owner =
2276 malloc( sizeof(filter_owner_sys_t) );
2277 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2278 id->pp_ufilter[id->i_ufilter]->p_owner->pp_pics[i] = 0;
2279 id->pp_ufilter[id->i_ufilter]->p_owner->p_sys = p_sys;
2284 msg_Dbg( p_stream, "no video filter found" );
2285 vlc_object_detach( id->pp_ufilter[id->i_ufilter] );
2286 vlc_object_destroy( id->pp_ufilter[id->i_ufilter] );
2291 /* Run filter chain */
2292 for( i = 0; i < id->i_filter; i++ )
2294 p_pic = id->pp_filter[i]->pf_video_filter(id->pp_filter[i], p_pic);
2301 /* Check if we have a subpicture to overlay */
2304 p_subpic = spu_SortSubpictures( p_sys->p_spu, p_pic->date );
2305 /* TODO: get another pic */
2308 /* Overlay subpicture */
2311 int i_scale_width, i_scale_height;
2312 video_format_t *p_fmt;
2314 i_scale_width = id->p_encoder->fmt_in.video.i_width * 1000 /
2315 id->p_decoder->fmt_out.video.i_width;
2316 i_scale_height = id->p_encoder->fmt_in.video.i_height * 1000 /
2317 id->p_decoder->fmt_out.video.i_height;
2319 if( p_pic->i_refcount && !id->i_filter )
2321 /* We can't modify the picture, we need to duplicate it */
2322 picture_t *p_tmp = video_new_buffer_decoder( id->p_decoder );
2325 vout_CopyPicture( p_stream, p_tmp, p_pic );
2326 p_pic->pf_release( p_pic );
2332 p_fmt = &id->pp_filter[id->i_filter -1]->fmt_out.video;
2334 p_fmt = &id->p_decoder->fmt_out.video;
2336 /* FIXME (shouldn't have to be done here) */
2337 p_fmt->i_sar_num = p_fmt->i_aspect *
2338 p_fmt->i_height / p_fmt->i_width;
2339 p_fmt->i_sar_den = VOUT_ASPECT_FACTOR;
2341 spu_RenderSubpictures( p_sys->p_spu, p_fmt, p_pic, p_pic, p_subpic,
2342 i_scale_width, i_scale_height );
2345 /* Run user specified filter chain */
2346 for( i = 0; i < id->i_ufilter; i++ )
2348 p_pic = id->pp_ufilter[i]->pf_video_filter(id->pp_ufilter[i], p_pic);
2351 if( p_sys->i_threads == 0 )
2354 p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
2355 block_ChainAppend( out, p_block );
2358 if( p_sys->b_master_sync )
2360 mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
2361 if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2362 || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2364 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2365 date_Set( &id->interpolated_pts, p_pic->date );
2366 i_pts = p_pic->date + 1;
2368 date_Increment( &id->interpolated_pts, 1 );
2371 if( p_sys->b_master_sync && i_duplicate > 1 )
2373 mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
2374 if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2375 || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2377 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2378 date_Set( &id->interpolated_pts, p_pic->date );
2379 i_pts = p_pic->date + 1;
2381 date_Increment( &id->interpolated_pts, 1 );
2383 if( p_sys->i_threads >= 1 )
2385 /* We can't modify the picture, we need to duplicate it */
2386 p_pic2 = video_new_buffer_decoder( id->p_decoder );
2387 if( p_pic2 != NULL )
2389 vout_CopyPicture( p_stream, p_pic2, p_pic );
2390 p_pic2->date = i_pts;
2396 p_pic->date = i_pts;
2397 p_block = id->p_encoder->pf_encode_video(id->p_encoder, p_pic);
2398 block_ChainAppend( out, p_block );
2402 if( p_sys->i_threads == 0 )
2404 p_pic->pf_release( p_pic );
2408 vlc_mutex_lock( &p_sys->lock_out );
2409 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic;
2410 p_sys->i_last_pic %= PICTURE_RING_SIZE;
2411 *out = p_sys->p_buffers;
2412 p_sys->p_buffers = NULL;
2413 if( p_pic2 != NULL )
2415 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic2;
2416 p_sys->i_last_pic %= PICTURE_RING_SIZE;
2418 vlc_cond_signal( &p_sys->cond );
2419 vlc_mutex_unlock( &p_sys->lock_out );
2426 static int EncoderThread( sout_stream_sys_t *p_sys )
2428 sout_stream_id_t *id = p_sys->id_video;
2431 while( !p_sys->b_die && !p_sys->b_error )
2435 vlc_mutex_lock( &p_sys->lock_out );
2436 while( p_sys->i_last_pic == p_sys->i_first_pic )
2438 vlc_cond_wait( &p_sys->cond, &p_sys->lock_out );
2439 if( p_sys->b_die || p_sys->b_error ) break;
2441 if( p_sys->b_die || p_sys->b_error )
2443 vlc_mutex_unlock( &p_sys->lock_out );
2447 p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2448 p_sys->i_first_pic %= PICTURE_RING_SIZE;
2449 vlc_mutex_unlock( &p_sys->lock_out );
2451 p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
2452 vlc_mutex_lock( &p_sys->lock_out );
2453 block_ChainAppend( &p_sys->p_buffers, p_block );
2455 vlc_mutex_unlock( &p_sys->lock_out );
2456 p_pic->pf_release( p_pic );
2459 while( p_sys->i_last_pic != p_sys->i_first_pic )
2461 p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2462 p_sys->i_first_pic %= PICTURE_RING_SIZE;
2463 p_pic->pf_release( p_pic );
2465 block_ChainRelease( p_sys->p_buffers );
2470 struct picture_sys_t
2472 vlc_object_t *p_owner;
2475 static void video_release_buffer( picture_t *p_pic )
2477 if( p_pic && !p_pic->i_refcount && p_pic->pf_release && p_pic->p_sys )
2479 video_del_buffer_decoder( (decoder_t *)p_pic->p_sys->p_owner, p_pic );
2481 else if( p_pic && p_pic->i_refcount > 0 ) p_pic->i_refcount--;
2484 static picture_t *video_new_buffer( vlc_object_t *p_this, picture_t **pp_ring,
2485 sout_stream_sys_t *p_sys )
2487 decoder_t *p_dec = (decoder_t *)p_this;
2491 /* Find an empty space in the picture ring buffer */
2492 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2494 if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
2496 pp_ring[i]->i_status = RESERVED_PICTURE;
2500 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2502 if( pp_ring[i] == 0 ) break;
2505 if( i == PICTURE_RING_SIZE && p_sys->i_threads >= 1 )
2507 int i_first_pic = p_sys->i_first_pic;
2509 if( p_sys->i_first_pic != p_sys->i_last_pic )
2511 /* Encoder still has stuff to encode, wait to clear-up the list */
2512 while( p_sys->i_first_pic == i_first_pic )
2516 /* Find an empty space in the picture ring buffer */
2517 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2519 if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
2521 pp_ring[i]->i_status = RESERVED_PICTURE;
2525 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2527 if( pp_ring[i] == 0 ) break;
2531 if( i == PICTURE_RING_SIZE )
2533 msg_Err( p_this, "decoder/filter is leaking pictures, "
2534 "resetting its ring buffer" );
2536 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2538 pp_ring[i]->pf_release( pp_ring[i] );
2544 p_pic = malloc( sizeof(picture_t) );
2545 p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
2546 vout_AllocatePicture( VLC_OBJECT(p_dec), p_pic,
2547 p_dec->fmt_out.video.i_chroma,
2548 p_dec->fmt_out.video.i_width,
2549 p_dec->fmt_out.video.i_height,
2550 p_dec->fmt_out.video.i_aspect );
2552 if( !p_pic->i_planes )
2558 p_pic->pf_release = video_release_buffer;
2559 p_pic->p_sys = malloc( sizeof(picture_sys_t) );
2560 p_pic->p_sys->p_owner = p_this;
2561 p_pic->i_status = RESERVED_PICTURE;
2567 static picture_t *video_new_buffer_decoder( decoder_t *p_dec )
2569 return video_new_buffer( VLC_OBJECT(p_dec),
2570 p_dec->p_owner->pp_pics, p_dec->p_owner->p_sys );
2573 static picture_t *video_new_buffer_filter( filter_t *p_filter )
2575 return video_new_buffer( VLC_OBJECT(p_filter),
2576 p_filter->p_owner->pp_pics,
2577 p_filter->p_owner->p_sys );
2580 static void video_del_buffer( vlc_object_t *p_this, picture_t *p_pic )
2582 if( p_pic && p_pic->p_data_orig ) free( p_pic->p_data_orig );
2583 if( p_pic && p_pic->p_sys ) free( p_pic->p_sys );
2584 if( p_pic ) free( p_pic );
2587 static void video_del_buffer_decoder( decoder_t *p_decoder, picture_t *p_pic )
2589 p_pic->i_refcount = 0;
2590 p_pic->i_status = DESTROYED_PICTURE;
2593 static void video_del_buffer_filter( filter_t *p_filter, picture_t *p_pic )
2595 p_pic->i_refcount = 0;
2596 p_pic->i_status = DESTROYED_PICTURE;
2599 static void video_link_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2601 p_pic->i_refcount++;
2604 static void video_unlink_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2606 video_release_buffer( p_pic );
2612 static subpicture_t *spu_new_buffer( decoder_t * );
2613 static void spu_del_buffer( decoder_t *, subpicture_t * );
2615 static int transcode_spu_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2617 sout_stream_sys_t *p_sys = p_stream->p_sys;
2623 /* Initialization of decoder structures */
2624 id->p_decoder->pf_spu_buffer_new = spu_new_buffer;
2625 id->p_decoder->pf_spu_buffer_del = spu_del_buffer;
2626 id->p_decoder->p_owner = (decoder_owner_sys_t *)p_stream;
2627 /* id->p_decoder->p_cfg = p_sys->p_spu_cfg; */
2629 id->p_decoder->p_module =
2630 module_Need( id->p_decoder, "decoder", "$codec", 0 );
2632 if( !id->p_decoder->p_module )
2634 msg_Err( p_stream, "cannot find decoder" );
2635 return VLC_EGENERIC;
2638 if( !p_sys->b_soverlay )
2641 /* Initialization of encoder format structures */
2642 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
2643 id->p_decoder->fmt_in.i_codec );
2645 id->p_encoder->p_cfg = p_sys->p_spu_cfg;
2647 id->p_encoder->p_module =
2648 module_Need( id->p_encoder, "encoder", p_sys->psz_senc, VLC_TRUE );
2650 if( !id->p_encoder->p_module )
2652 module_Unneed( id->p_decoder, id->p_decoder->p_module );
2653 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_senc );
2654 return VLC_EGENERIC;
2660 p_sys->p_spu = spu_Create( p_stream );
2661 spu_Init( p_sys->p_spu );
2667 static void transcode_spu_close( sout_stream_t *p_stream, sout_stream_id_t *id)
2670 if( id->p_decoder->p_module )
2671 module_Unneed( id->p_decoder, id->p_decoder->p_module );
2674 if( id->p_encoder->p_module )
2675 module_Unneed( id->p_encoder, id->p_encoder->p_module );
2678 static int transcode_spu_process( sout_stream_t *p_stream,
2679 sout_stream_id_t *id,
2680 block_t *in, block_t **out )
2682 sout_stream_sys_t *p_sys = p_stream->p_sys;
2683 subpicture_t *p_subpic;
2686 p_subpic = id->p_decoder->pf_decode_sub( id->p_decoder, &in );
2687 if( !p_subpic ) return VLC_EGENERIC;
2689 if( p_sys->b_master_sync && p_sys->i_master_drift )
2691 p_subpic->i_start -= p_sys->i_master_drift;
2692 if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2695 if( p_sys->b_soverlay )
2697 spu_DisplaySubpicture( p_sys->p_spu, p_subpic );
2703 p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
2704 spu_del_buffer( id->p_decoder, p_subpic );
2708 block_ChainAppend( out, p_block );
2713 return VLC_EGENERIC;
2716 static subpicture_t *spu_new_buffer( decoder_t *p_dec )
2718 sout_stream_t *p_stream = (sout_stream_t *)p_dec->p_owner;
2719 return spu_CreateSubpicture( p_stream->p_sys->p_spu );
2722 static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_subpic )
2724 sout_stream_t *p_stream = (sout_stream_t *)p_dec->p_owner;
2725 spu_DestroySubpicture( p_stream->p_sys->p_spu, p_subpic );
2731 static int transcode_osd_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2733 sout_stream_sys_t *p_sys = p_stream->p_sys;
2737 fmt.i_id = 0xbd1f; /* pid ?? */
2738 fmt.i_group = 3; /* pmt entry ?? */
2739 fmt.i_codec = VLC_FOURCC( 'Y', 'U', 'V', 'A' );
2740 fmt.psz_language = strdup( "osd" );
2742 id = malloc( sizeof( sout_stream_id_t ) );
2743 memset( id, 0, sizeof(sout_stream_id_t) );
2746 id->p_decoder = NULL;
2747 id->p_encoder = NULL;
2749 /* Create encoder object */
2750 id->p_encoder = vlc_object_create( p_stream, VLC_OBJECT_ENCODER );
2751 if( !id->p_encoder )
2753 msg_Err( p_stream, "out of memory" );
2756 vlc_object_attach( id->p_encoder, p_stream );
2757 id->p_encoder->p_module = NULL;
2759 /* Create fake destination format */
2760 es_format_Init( &id->p_encoder->fmt_out, fmt.i_cat, 0 );
2761 id->p_encoder->fmt_out.i_id = fmt.i_id;
2762 id->p_encoder->fmt_out.i_group = fmt.i_group;
2763 id->p_encoder->fmt_out.psz_language = strdup( fmt.psz_language );
2765 if( p_sys->i_osdcodec != 0 || p_sys->psz_osdenc )
2767 msg_Dbg( p_stream, "creating osdmenu transcoding from fcc=`%4.4s' "
2768 "to fcc=`%4.4s'", (char*)&fmt.i_codec,
2769 (char*)&p_sys->i_osdcodec );
2771 /* Complete destination format */
2772 id->p_encoder->fmt_out.i_codec = p_sys->i_osdcodec;
2775 /* Initialization of encoder format structures */
2776 es_format_Init( &id->p_encoder->fmt_in, fmt.i_cat, fmt.i_codec );
2777 id->p_encoder->fmt_in.psz_language = strdup( fmt.psz_language );
2779 id->p_encoder->p_cfg = p_sys->p_osd_cfg;
2781 id->p_encoder->p_module =
2782 module_Need( id->p_encoder, "encoder", p_sys->psz_osdenc, VLC_TRUE );
2784 if( !id->p_encoder->p_module )
2786 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_osdenc );
2790 /* open output stream */
2791 id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
2792 id->b_transcode = VLC_TRUE;
2794 if( !id->id ) goto error;
2798 msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
2799 (char*)&fmt.i_codec );
2800 id->id = p_sys->p_out->pf_add( p_sys->p_out, &fmt );
2801 id->b_transcode = VLC_FALSE;
2803 if( !id->id ) goto error;
2807 p_sys->b_es_osd = VLC_TRUE;
2811 p_sys->p_spu = spu_Create( p_stream );
2812 if( spu_Init( p_sys->p_spu ) != VLC_SUCCESS )
2813 msg_Err( p_sys, "spu initialisation failed" );
2816 if( fmt.psz_language )
2817 free( fmt.psz_language );
2822 msg_Err( p_stream, "starting osd encoding thread failed" );
2823 if( id->p_encoder->p_module )
2824 module_Unneed( id->p_encoder, id->p_encoder->p_module );
2827 vlc_object_detach( id->p_encoder );
2828 vlc_object_destroy( id->p_encoder );
2830 if( fmt.psz_language ) free( fmt.psz_language );
2831 if( id ) free( id );
2832 p_sys->id_osd = NULL;
2833 p_sys->b_es_osd = VLC_FALSE;
2834 return VLC_EGENERIC;
2837 static void transcode_osd_close( sout_stream_t *p_stream, sout_stream_id_t *id)
2839 sout_stream_sys_t *p_sys = p_stream->p_sys;
2842 if( p_sys->b_es_osd && id )
2844 if( id->p_encoder->p_module )
2845 module_Unneed( id->p_encoder, id->p_encoder->p_module );
2847 if( id->id ) p_sys->p_out->pf_del( p_sys->p_out, id->id );
2851 vlc_object_detach( id->p_encoder );
2852 vlc_object_destroy( id->p_encoder );
2855 p_sys->b_es_osd = VLC_FALSE;
2856 if( id ) free( id );
2859 static int transcode_osd_process( sout_stream_t *p_stream,
2860 sout_stream_id_t *id,
2861 block_t *in, block_t **out )
2863 sout_stream_sys_t *p_sys = p_stream->p_sys;
2864 subpicture_t *p_subpic = NULL;
2866 /* Check if we have a subpicture to send */
2867 if( p_sys->p_spu && in->i_dts > 0)
2869 p_subpic = spu_SortSubpictures( p_sys->p_spu, in->i_dts );
2873 msg_Warn( p_stream, "spu channel not initialized, doing it now" );
2876 p_sys->p_spu = spu_Create( p_stream );
2877 if( spu_Init( p_sys->p_spu ) != VLC_SUCCESS )
2878 msg_Err( p_stream, "spu initialisation failed" );
2884 block_t *p_block = NULL;
2886 if( p_sys->b_master_sync && p_sys->i_master_drift )
2888 p_subpic->i_start -= p_sys->i_master_drift;
2889 if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2892 p_block = p_sys->id_osd->p_encoder->pf_encode_sub( p_sys->id_osd->p_encoder, p_subpic );
2895 p_block->i_dts = p_block->i_pts = in->i_dts;
2896 block_ChainAppend( out, p_block );
2899 if( p_sys->p_out->pf_send( p_sys->p_out, p_sys->id_osd->id, *out ) == VLC_SUCCESS )
2900 spu_DestroySubpicture( p_sys->p_spu, p_subpic );
2905 return VLC_EGENERIC;