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( p_sys->i_acodec == VLC_FOURCC('m','p','3',0) &&
518 p_sys->i_channels > 2 )
520 msg_Warn( p_stream, "%d channels invalid for mp3, forcing to 2",
522 p_sys->i_channels = 2;
524 msg_Dbg( p_stream, "codec audio=%4.4s %dHz %d channels %dKb/s",
525 (char *)&p_sys->i_acodec, p_sys->i_sample_rate,
526 p_sys->i_channels, p_sys->i_abitrate / 1000 );
529 var_Get( p_stream, SOUT_CFG_PREFIX "afilter", &val );
530 p_sys->i_afilters = 0;
531 if( val.psz_string && *val.psz_string )
533 char *psz_parser = val.psz_string;
535 while( (psz_parser != NULL) && (*psz_parser != '\0')
536 && (p_sys->i_afilters < TRANSCODE_FILTERS) )
538 psz_parser = 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 p_sys->i_canvas_aspect = 0;
666 if( val.psz_string && *val.psz_string )
668 char *psz_parser = strchr( val.psz_string, ':' );
671 *psz_parser++ = '\0';
672 p_sys->i_canvas_aspect = atoi( val.psz_string ) *
673 VOUT_ASPECT_FACTOR / atoi( psz_parser );
675 else msg_Warn( p_stream, "bad aspect ratio %s", val.psz_string );
678 if( val.psz_string ) free( val.psz_string );
680 var_Get( p_stream, SOUT_CFG_PREFIX "threads", &val );
681 p_sys->i_threads = val.i_int;
682 var_Get( p_stream, SOUT_CFG_PREFIX "high-priority", &val );
683 p_sys->b_high_priority = val.b_bool;
685 if( p_sys->i_vcodec )
687 msg_Dbg( p_stream, "codec video=%4.4s %dx%d scaling: %f %dkb/s",
688 (char *)&p_sys->i_vcodec, p_sys->i_width, p_sys->i_height,
689 p_sys->f_scale, p_sys->i_vbitrate / 1000 );
692 /* Subpictures transcoding parameters */
694 p_sys->psz_senc = NULL;
695 p_sys->p_spu_cfg = NULL;
698 var_Get( p_stream, SOUT_CFG_PREFIX "senc", &val );
699 if( val.psz_string && *val.psz_string )
702 psz_next = sout_CfgCreate( &p_sys->psz_senc, &p_sys->p_spu_cfg,
704 if( psz_next ) free( psz_next );
706 if( val.psz_string ) free( val.psz_string );
708 var_Get( p_stream, SOUT_CFG_PREFIX "scodec", &val );
709 if( val.psz_string && *val.psz_string )
712 memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
713 p_sys->i_scodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
715 if( val.psz_string ) free( val.psz_string );
717 if( p_sys->i_scodec )
719 msg_Dbg( p_stream, "codec spu=%4.4s", (char *)&p_sys->i_scodec );
722 var_Get( p_stream, SOUT_CFG_PREFIX "soverlay", &val );
723 p_sys->b_soverlay = val.b_bool;
725 var_Get( p_stream, SOUT_CFG_PREFIX "sfilter", &val );
726 if( val.psz_string && *val.psz_string )
728 p_sys->p_spu = spu_Create( p_stream );
729 var_Create( p_sys->p_spu, "sub-filter", VLC_VAR_STRING );
730 var_Set( p_sys->p_spu, "sub-filter", val );
731 spu_Init( p_sys->p_spu );
733 if( val.psz_string ) free( val.psz_string );
735 /* OSD menu transcoding parameters */
736 p_sys->psz_osdenc = NULL;
737 p_sys->p_osd_cfg = NULL;
738 p_sys->i_osdcodec = 0;
739 p_sys->b_es_osd = VLC_FALSE;
741 var_Get( p_stream, SOUT_CFG_PREFIX "osd", &val );
742 p_sys->b_sout_osd = val.b_bool;
743 if( p_sys->b_sout_osd )
748 psz_next = sout_CfgCreate( &p_sys->psz_osdenc,
749 &p_sys->p_osd_cfg, strdup( "dvbsub") );
750 if( psz_next ) free( psz_next );
752 p_sys->i_osdcodec = VLC_FOURCC('Y','U','V','P' );
754 msg_Dbg( p_stream, "codec osd=%4.4s", (char *)&p_sys->i_osdcodec );
758 osd_val.psz_string = strdup("osdmenu");
759 p_sys->p_spu = spu_Create( p_stream );
760 var_Create( p_sys->p_spu, "sub-filter", VLC_VAR_STRING );
761 var_Set( p_sys->p_spu, "sub-filter", osd_val );
762 spu_Init( p_sys->p_spu );
763 if( osd_val.psz_string ) free( osd_val.psz_string );
767 osd_val.psz_string = strdup("osdmenu");
768 var_Set( p_sys->p_spu, "sub-filter", osd_val );
769 if( osd_val.psz_string ) free( osd_val.psz_string );
774 var_Get( p_stream, SOUT_CFG_PREFIX "audio-sync", &val );
775 p_sys->b_master_sync = val.b_bool;
776 if( p_sys->f_fps > 0 ) p_sys->b_master_sync = VLC_TRUE;
778 p_stream->pf_add = Add;
779 p_stream->pf_del = Del;
780 p_stream->pf_send = Send;
781 p_stream->p_sys = p_sys;
786 /*****************************************************************************
788 *****************************************************************************/
789 static void Close( vlc_object_t * p_this )
791 sout_stream_t *p_stream = (sout_stream_t*)p_this;
792 sout_stream_sys_t *p_sys = p_stream->p_sys;
794 sout_StreamDelete( p_sys->p_out );
796 while( p_sys->p_audio_cfg != NULL )
798 sout_cfg_t *p_next = p_sys->p_audio_cfg->p_next;
800 if( p_sys->p_audio_cfg->psz_name )
801 free( p_sys->p_audio_cfg->psz_name );
802 if( p_sys->p_audio_cfg->psz_value )
803 free( p_sys->p_audio_cfg->psz_value );
804 free( p_sys->p_audio_cfg );
806 p_sys->p_audio_cfg = p_next;
808 if( p_sys->psz_aenc ) free( p_sys->psz_aenc );
810 while( p_sys->p_video_cfg != NULL )
812 sout_cfg_t *p_next = p_sys->p_video_cfg->p_next;
814 if( p_sys->p_video_cfg->psz_name )
815 free( p_sys->p_video_cfg->psz_name );
816 if( p_sys->p_video_cfg->psz_value )
817 free( p_sys->p_video_cfg->psz_value );
818 free( p_sys->p_video_cfg );
820 p_sys->p_video_cfg = p_next;
822 if( p_sys->psz_venc ) free( p_sys->psz_venc );
824 while( p_sys->p_deinterlace_cfg != NULL )
826 sout_cfg_t *p_next = p_sys->p_deinterlace_cfg->p_next;
828 if( p_sys->p_deinterlace_cfg->psz_name )
829 free( p_sys->p_deinterlace_cfg->psz_name );
830 if( p_sys->p_deinterlace_cfg->psz_value )
831 free( p_sys->p_deinterlace_cfg->psz_value );
832 free( p_sys->p_deinterlace_cfg );
834 p_sys->p_deinterlace_cfg = p_next;
836 if( p_sys->psz_deinterlace ) free( p_sys->psz_deinterlace );
838 while( p_sys->p_spu_cfg != NULL )
840 sout_cfg_t *p_next = p_sys->p_spu_cfg->p_next;
842 if( p_sys->p_spu_cfg->psz_name )
843 free( p_sys->p_spu_cfg->psz_name );
844 if( p_sys->p_spu_cfg->psz_value )
845 free( p_sys->p_spu_cfg->psz_value );
846 free( p_sys->p_spu_cfg );
848 p_sys->p_spu_cfg = p_next;
850 if( p_sys->psz_senc ) free( p_sys->psz_senc );
852 if( p_sys->p_spu ) spu_Destroy( p_sys->p_spu );
854 while( p_sys->p_osd_cfg != NULL )
856 sout_cfg_t *p_next = p_sys->p_osd_cfg->p_next;
858 if( p_sys->p_osd_cfg->psz_name )
859 free( p_sys->p_osd_cfg->psz_name );
860 if( p_sys->p_osd_cfg->psz_value )
861 free( p_sys->p_osd_cfg->psz_value );
862 free( p_sys->p_osd_cfg );
864 p_sys->p_osd_cfg = p_next;
866 if( p_sys->psz_osdenc ) free( p_sys->psz_osdenc );
868 vlc_object_destroy( p_sys );
871 struct sout_stream_id_t
873 vlc_fourcc_t b_transcode;
875 /* id of the out stream */
879 decoder_t *p_decoder;
882 filter_t *pp_filter[TRANSCODE_FILTERS];
884 /* User specified filters */
885 filter_t *pp_ufilter[TRANSCODE_FILTERS];
889 encoder_t *p_encoder;
892 date_t interpolated_pts;
895 static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
897 sout_stream_sys_t *p_sys = p_stream->p_sys;
898 sout_stream_id_t *id;
900 id = malloc( sizeof( sout_stream_id_t ) );
901 memset( id, 0, sizeof(sout_stream_id_t) );
904 id->p_decoder = NULL;
905 id->p_encoder = NULL;
907 /* Create decoder object */
908 id->p_decoder = vlc_object_create( p_stream, VLC_OBJECT_DECODER );
911 msg_Err( p_stream, "out of memory" );
914 vlc_object_attach( id->p_decoder, p_stream );
915 id->p_decoder->p_module = NULL;
916 id->p_decoder->fmt_in = *p_fmt;
917 id->p_decoder->b_pace_control = VLC_TRUE;
919 /* Create encoder object */
920 id->p_encoder = vlc_object_create( p_stream, VLC_OBJECT_ENCODER );
923 msg_Err( p_stream, "out of memory" );
926 vlc_object_attach( id->p_encoder, p_stream );
927 id->p_encoder->p_module = NULL;
929 /* Create destination format */
930 es_format_Init( &id->p_encoder->fmt_out, p_fmt->i_cat, 0 );
931 id->p_encoder->fmt_out.i_id = p_fmt->i_id;
932 id->p_encoder->fmt_out.i_group = p_fmt->i_group;
933 if( p_fmt->psz_language )
934 id->p_encoder->fmt_out.psz_language = strdup( p_fmt->psz_language );
936 if( p_fmt->i_cat == AUDIO_ES && (p_sys->i_acodec || p_sys->psz_aenc) )
939 "creating audio transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
940 (char*)&p_fmt->i_codec, (char*)&p_sys->i_acodec );
942 /* Complete destination format */
943 id->p_encoder->fmt_out.i_codec = p_sys->i_acodec;
944 id->p_encoder->fmt_out.audio.i_rate = p_sys->i_sample_rate > 0 ?
945 p_sys->i_sample_rate : (int)p_fmt->audio.i_rate;
946 id->p_encoder->fmt_out.i_bitrate = p_sys->i_abitrate;
947 id->p_encoder->fmt_out.audio.i_bitspersample =
948 p_fmt->audio.i_bitspersample;
949 id->p_encoder->fmt_out.audio.i_channels = p_sys->i_channels > 0 ?
950 p_sys->i_channels : p_fmt->audio.i_channels;
951 /* Sanity check for audio channels */
952 id->p_encoder->fmt_out.audio.i_channels =
953 __MIN( id->p_encoder->fmt_out.audio.i_channels,
954 id->p_decoder->fmt_in.audio.i_channels );
955 id->p_encoder->fmt_out.audio.i_original_channels =
956 id->p_decoder->fmt_in.audio.i_physical_channels;
957 if( id->p_decoder->fmt_in.audio.i_channels ==
958 id->p_encoder->fmt_out.audio.i_channels )
960 id->p_encoder->fmt_out.audio.i_physical_channels =
961 id->p_decoder->fmt_in.audio.i_physical_channels;
965 id->p_encoder->fmt_out.audio.i_physical_channels =
966 pi_channels_maps[id->p_encoder->fmt_out.audio.i_channels];
969 /* Build decoder -> filter -> encoder chain */
970 if( transcode_audio_new( p_stream, id ) )
972 msg_Err( p_stream, "cannot create audio chain" );
976 /* Open output stream */
977 id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
978 id->b_transcode = VLC_TRUE;
982 transcode_audio_close( p_stream, id );
986 date_Init( &id->interpolated_pts, p_fmt->audio.i_rate, 1 );
988 else if( p_fmt->i_cat == VIDEO_ES &&
989 (p_sys->i_vcodec != 0 || p_sys->psz_venc) )
992 "creating video transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
993 (char*)&p_fmt->i_codec, (char*)&p_sys->i_vcodec );
995 /* Complete destination format */
996 id->p_encoder->fmt_out.i_codec = p_sys->i_vcodec;
997 id->p_encoder->fmt_out.video.i_width = p_sys->i_width & ~1;
998 id->p_encoder->fmt_out.video.i_height = p_sys->i_height & ~1;
999 id->p_encoder->fmt_out.i_bitrate = p_sys->i_vbitrate;
1001 /* Build decoder -> filter -> encoder chain */
1002 if( transcode_video_new( p_stream, id ) )
1004 msg_Err( p_stream, "cannot create video chain" );
1008 /* Stream will be added later on because we don't know
1009 * all the characteristics of the decoded stream yet */
1010 id->b_transcode = VLC_TRUE;
1012 if( p_sys->f_fps > 0 )
1014 id->p_encoder->fmt_out.video.i_frame_rate =
1015 (p_sys->f_fps * 1001) + 0.5;
1016 id->p_encoder->fmt_out.video.i_frame_rate_base = 1001;
1019 else if( p_fmt->i_cat == SPU_ES && (p_sys->i_scodec || p_sys->psz_senc) )
1021 msg_Dbg( p_stream, "creating subtitles transcoding from fcc=`%4.4s' "
1022 "to fcc=`%4.4s'", (char*)&p_fmt->i_codec,
1023 (char*)&p_sys->i_scodec );
1025 /* Complete destination format */
1026 id->p_encoder->fmt_out.i_codec = p_sys->i_scodec;
1028 /* build decoder -> filter -> encoder */
1029 if( transcode_spu_new( p_stream, id ) )
1031 msg_Err( p_stream, "cannot create subtitles chain" );
1035 /* open output stream */
1036 id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
1037 id->b_transcode = VLC_TRUE;
1041 transcode_spu_close( p_stream, id );
1045 else if( p_fmt->i_cat == SPU_ES && p_sys->b_soverlay )
1047 msg_Dbg( p_stream, "subtitles (fcc=`%4.4s') overlaying",
1048 (char*)&p_fmt->i_codec );
1050 id->b_transcode = VLC_TRUE;
1052 /* Build decoder -> filter -> overlaying chain */
1053 if( transcode_spu_new( p_stream, id ) )
1055 msg_Err( p_stream, "cannot create subtitles chain" );
1061 msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
1062 (char*)&p_fmt->i_codec );
1063 id->id = p_sys->p_out->pf_add( p_sys->p_out, p_fmt );
1064 id->b_transcode = VLC_FALSE;
1066 if( !id->id ) goto error;
1069 if( p_sys->b_sout_osd )
1071 /* Create a fake OSD menu elementary stream */
1072 if( !p_sys->b_es_osd && (p_sys->i_osdcodec != 0 || p_sys->psz_osdenc) )
1074 if( transcode_osd_new( p_stream, p_sys->id_osd ) )
1076 msg_Err( p_stream, "cannot create osd chain" );
1079 p_sys->b_es_osd = VLC_TRUE;
1087 vlc_object_detach( id->p_decoder );
1088 vlc_object_destroy( id->p_decoder );
1089 id->p_decoder = NULL;
1094 vlc_object_detach( id->p_encoder );
1095 es_format_Clean( &id->p_encoder->fmt_out );
1096 vlc_object_destroy( id->p_encoder );
1097 id->p_encoder = NULL;
1104 static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
1106 sout_stream_sys_t *p_sys = p_stream->p_sys;
1108 if( p_sys->b_es_osd )
1109 transcode_osd_close( p_stream, p_sys->id_osd );
1111 if( id->b_transcode )
1113 switch( id->p_decoder->fmt_in.i_cat )
1116 transcode_audio_close( p_stream, id );
1119 transcode_video_close( p_stream, id );
1122 transcode_spu_close( p_stream, id );
1127 if( id->id ) p_sys->p_out->pf_del( p_sys->p_out, id->id );
1131 vlc_object_detach( id->p_decoder );
1132 vlc_object_destroy( id->p_decoder );
1133 id->p_decoder = NULL;
1138 vlc_object_detach( id->p_encoder );
1139 es_format_Clean( &id->p_encoder->fmt_out );
1140 vlc_object_destroy( id->p_encoder );
1141 id->p_encoder = NULL;
1148 static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
1151 sout_stream_sys_t *p_sys = p_stream->p_sys;
1152 block_t *p_out = NULL;
1154 if( !id->b_transcode && id->id )
1156 /* Transcode OSD menu pictures. */
1157 if( p_sys->b_es_osd )
1159 transcode_osd_process( p_stream, id, p_buffer, &p_out );
1161 return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_buffer );
1163 else if( !id->b_transcode )
1165 block_Release( p_buffer );
1166 return VLC_EGENERIC;
1169 switch( id->p_decoder->fmt_in.i_cat )
1172 transcode_audio_process( p_stream, id, p_buffer, &p_out );
1176 if( transcode_video_process( p_stream, id, p_buffer, &p_out )
1179 return VLC_EGENERIC;
1184 if( transcode_spu_process( p_stream, id, p_buffer, &p_out ) !=
1187 return VLC_EGENERIC;
1193 block_Release( p_buffer );
1197 if( p_out ) return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_out );
1201 /****************************************************************************
1202 * decoder reencoder part
1203 ****************************************************************************/
1204 int audio_BitsPerSample( vlc_fourcc_t i_format )
1208 case VLC_FOURCC('u','8',' ',' '):
1209 case VLC_FOURCC('s','8',' ',' '):
1212 case VLC_FOURCC('u','1','6','l'):
1213 case VLC_FOURCC('s','1','6','l'):
1214 case VLC_FOURCC('u','1','6','b'):
1215 case VLC_FOURCC('s','1','6','b'):
1218 case VLC_FOURCC('u','2','4','l'):
1219 case VLC_FOURCC('s','2','4','l'):
1220 case VLC_FOURCC('u','2','4','b'):
1221 case VLC_FOURCC('s','2','4','b'):
1224 case VLC_FOURCC('u','3','2','l'):
1225 case VLC_FOURCC('s','3','2','l'):
1226 case VLC_FOURCC('u','3','2','b'):
1227 case VLC_FOURCC('s','3','2','b'):
1228 case VLC_FOURCC('f','l','3','2'):
1229 case VLC_FOURCC('f','i','3','2'):
1232 case VLC_FOURCC('f','l','6','4'):
1239 static filter_t *transcode_audio_filter_new( sout_stream_t *p_stream,
1240 sout_stream_id_t *id,
1241 es_format_t *p_fmt_in,
1242 es_format_t *p_fmt_out,
1245 sout_stream_sys_t *p_sys = p_stream->p_sys;
1246 filter_t *p_filter = vlc_object_create( p_stream, VLC_OBJECT_FILTER );
1248 vlc_object_attach( p_filter, p_stream );
1249 p_filter->pf_audio_buffer_new = (block_t* (*) (filter_t*, int))__block_New;
1251 p_filter->fmt_in = *p_fmt_in;
1252 p_filter->fmt_out = *p_fmt_out;
1254 p_filter->p_cfg = p_sys->p_afilters_cfg[id->i_ufilter];
1256 p_filter->p_module = module_Need( p_filter, "audio filter2", psz_name, 0 );
1257 if( p_filter->p_module )
1259 p_filter->fmt_out.audio.i_bitspersample =
1260 audio_BitsPerSample( p_filter->fmt_out.i_codec );
1261 *p_fmt_in = p_filter->fmt_out;
1265 vlc_object_detach( p_filter );
1266 vlc_object_destroy( p_filter );
1273 static int transcode_audio_new( sout_stream_t *p_stream,
1274 sout_stream_id_t *id )
1276 sout_stream_sys_t *p_sys = p_stream->p_sys;
1277 es_format_t fmt_last;
1284 /* Initialization of decoder structures */
1285 id->p_decoder->fmt_out = id->p_decoder->fmt_in;
1286 id->p_decoder->fmt_out.i_extra = 0;
1287 id->p_decoder->fmt_out.p_extra = 0;
1288 id->p_decoder->pf_decode_audio = 0;
1289 id->p_decoder->pf_aout_buffer_new = audio_new_buffer;
1290 id->p_decoder->pf_aout_buffer_del = audio_del_buffer;
1291 /* id->p_decoder->p_cfg = p_sys->p_audio_cfg; */
1293 id->p_decoder->p_module =
1294 module_Need( id->p_decoder, "decoder", "$codec", 0 );
1295 if( !id->p_decoder->p_module )
1297 msg_Err( p_stream, "cannot find decoder" );
1298 return VLC_EGENERIC;
1300 id->p_decoder->fmt_out.audio.i_bitspersample =
1301 audio_BitsPerSample( id->p_decoder->fmt_out.i_codec );
1302 fmt_last = id->p_decoder->fmt_out;
1303 /* FIX decoders so we don't have to do this */
1304 fmt_last.audio.i_rate = id->p_decoder->fmt_in.audio.i_rate;
1310 /* Initialization of encoder format structures */
1311 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1312 id->p_decoder->fmt_out.i_codec );
1313 id->p_encoder->fmt_in.audio.i_format = id->p_decoder->fmt_out.i_codec;
1315 /* Initialization of encoder format structures */
1316 es_format_Init( &id->p_encoder->fmt_in, AUDIO_ES, VLC_FOURCC('f','l','3','2') );
1317 id->p_encoder->fmt_in.audio.i_format = VLC_FOURCC('f','l','3','2');
1319 id->p_encoder->fmt_in.audio.i_rate = id->p_encoder->fmt_out.audio.i_rate;
1320 id->p_encoder->fmt_in.audio.i_physical_channels =
1321 id->p_encoder->fmt_out.audio.i_physical_channels;
1322 id->p_encoder->fmt_in.audio.i_original_channels =
1323 id->p_encoder->fmt_out.audio.i_original_channels;
1324 id->p_encoder->fmt_in.audio.i_channels =
1325 id->p_encoder->fmt_out.audio.i_channels;
1326 id->p_encoder->fmt_in.audio.i_bitspersample =
1327 audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1329 id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
1330 id->p_encoder->p_module =
1331 module_Need( id->p_encoder, "encoder", p_sys->psz_aenc, VLC_TRUE );
1332 if( !id->p_encoder->p_module )
1334 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_aenc );
1335 module_Unneed( id->p_decoder, id->p_decoder->p_module );
1336 id->p_decoder->p_module = NULL;
1337 return VLC_EGENERIC;
1339 id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
1340 id->p_encoder->fmt_in.audio.i_bitspersample =
1341 audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1343 /* Load conversion filters */
1344 if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels ||
1345 fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate )
1347 /* We'll have to go through fl32 first */
1348 es_format_t fmt_out = id->p_encoder->fmt_in;
1349 fmt_out.i_codec = fmt_out.audio.i_format = VLC_FOURCC('f','l','3','2');
1351 id->pp_filter[id->i_filter] =
1352 transcode_audio_filter_new( p_stream, id, &fmt_last, &fmt_out, NULL );
1354 if( id->pp_filter[id->i_filter] ) id->i_filter++;
1357 for( i = 0; i < TRANSCODE_FILTERS; i++ )
1359 if( (fmt_last.audio.i_channels !=
1360 id->p_encoder->fmt_in.audio.i_channels) ||
1361 (fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate) ||
1362 (fmt_last.i_codec != id->p_encoder->fmt_in.i_codec) )
1364 id->pp_filter[id->i_filter] =
1365 transcode_audio_filter_new( p_stream, id, &fmt_last,
1366 &id->p_encoder->fmt_in, NULL );
1368 if( id->pp_filter[id->i_filter] )
1375 /* Final checks to see if conversions were successful */
1376 if( fmt_last.i_codec != id->p_encoder->fmt_in.i_codec )
1378 msg_Err( p_stream, "no audio filter found (%4.4s->%4.4s)",
1379 (char *)&fmt_last.i_codec,
1380 (char *)&id->p_encoder->fmt_in.i_codec );
1381 transcode_audio_close( p_stream, id );
1382 return VLC_EGENERIC;
1385 /* Load user specified audio filters now */
1386 for( i = 0; (i < p_sys->i_afilters) &&
1387 (id->i_ufilter < TRANSCODE_FILTERS); i++ )
1389 id->pp_ufilter[id->i_ufilter] =
1390 transcode_audio_filter_new( p_stream, id, &fmt_last,
1391 &id->p_encoder->fmt_in,
1392 p_sys->psz_afilters[i] );
1394 if( id->pp_ufilter[id->i_ufilter] )
1400 if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels )
1403 module_Unneed( id->p_encoder, id->p_encoder->p_module );
1404 id->p_encoder->p_module = NULL;
1406 /* This might work, but only if the encoder is restarted */
1407 id->p_encoder->fmt_in.audio.i_channels = fmt_last.audio.i_channels;
1408 id->p_encoder->fmt_out.audio.i_channels = fmt_last.audio.i_channels;
1410 id->p_encoder->fmt_in.audio.i_physical_channels =
1411 id->p_encoder->fmt_in.audio.i_original_channels =
1412 fmt_last.audio.i_physical_channels;
1413 id->p_encoder->fmt_out.audio.i_physical_channels =
1414 id->p_encoder->fmt_out.audio.i_original_channels =
1415 fmt_last.audio.i_physical_channels;
1417 msg_Dbg( p_stream, "number of audio channels for mixing changed, "
1418 "trying to reopen the encoder for mixing %i to %i channels",
1419 fmt_last.audio.i_channels,
1420 id->p_encoder->fmt_in.audio.i_channels );
1422 /* reload encoder */
1423 id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
1424 id->p_encoder->p_module =
1425 module_Need( id->p_encoder, "encoder", p_sys->psz_aenc, VLC_TRUE );
1426 if( !id->p_encoder->p_module )
1428 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_aenc );
1429 transcode_audio_close( p_stream, id );
1430 return VLC_EGENERIC;
1432 id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
1433 id->p_encoder->fmt_in.audio.i_bitspersample =
1434 audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1436 msg_Err( p_stream, "no audio filter found for mixing from"
1437 " %i to %i channels", fmt_last.audio.i_channels,
1438 id->p_encoder->fmt_in.audio.i_channels );
1440 transcode_audio_close( p_stream, id );
1441 return VLC_EGENERIC;
1445 if( fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate )
1447 msg_Err( p_stream, "no audio filter found for resampling from"
1448 " %iHz to %iHz", fmt_last.audio.i_rate,
1449 id->p_encoder->fmt_in.audio.i_rate );
1451 /* FIXME : this might work, but only if the encoder is restarted */
1452 id->p_encoder->fmt_in.audio.i_rate = fmt_last.audio.i_rate;
1453 id->p_encoder->fmt_out.audio.i_rate = fmt_last.audio.i_rate;
1455 transcode_audio_close( p_stream, id );
1456 return VLC_EGENERIC;
1460 /* FIXME: Hack for mp3 transcoding support */
1461 if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC( 'm','p','3',' ' ) )
1462 id->p_encoder->fmt_out.i_codec = VLC_FOURCC( 'm','p','g','a' );
1467 static void transcode_audio_close( sout_stream_t *p_stream,
1468 sout_stream_id_t *id )
1473 if( id->p_decoder->p_module )
1474 module_Unneed( id->p_decoder, id->p_decoder->p_module );
1475 id->p_decoder->p_module = NULL;
1478 if( id->p_encoder->p_module )
1479 module_Unneed( id->p_encoder, id->p_encoder->p_module );
1480 id->p_encoder->p_module = NULL;
1483 for( i = 0; i < id->i_filter; i++ )
1485 vlc_object_detach( id->pp_filter[i] );
1486 if( id->pp_filter[i]->p_module )
1487 module_Unneed( id->pp_filter[i], id->pp_filter[i]->p_module );
1488 vlc_object_destroy( id->pp_filter[i] );
1490 for( i = 0; i < id->i_ufilter; i++ )
1492 vlc_object_detach( id->pp_ufilter[i] );
1493 if( id->pp_ufilter[i]->p_module )
1494 module_Unneed( id->pp_ufilter[i], id->pp_ufilter[i]->p_module );
1495 vlc_object_destroy( id->pp_ufilter[i] );
1499 static int transcode_audio_process( sout_stream_t *p_stream,
1500 sout_stream_id_t *id,
1501 block_t *in, block_t **out )
1503 sout_stream_sys_t *p_sys = p_stream->p_sys;
1504 aout_buffer_t *p_audio_buf;
1505 block_t *p_block, *p_audio_block;
1508 input_thread_t *p_input = NULL;
1510 if( p_stream->p_parent->p_parent && p_stream->p_parent->p_parent->
1511 i_object_type == VLC_OBJECT_INPUT )
1512 p_input = (input_thread_t *)p_stream->p_parent->p_parent;
1514 while( (p_audio_buf = id->p_decoder->pf_decode_audio( id->p_decoder,
1518 stats_UpdateInteger( p_input, p_input->counters.p_decoded_audio,
1520 if( p_sys->b_master_sync )
1522 mtime_t i_dts = date_Get( &id->interpolated_pts ) + 1;
1523 if ( p_audio_buf->start_date - i_dts > MASTER_SYNC_MAX_DRIFT
1524 || p_audio_buf->start_date - i_dts < -MASTER_SYNC_MAX_DRIFT )
1526 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
1527 date_Set( &id->interpolated_pts, p_audio_buf->start_date );
1528 i_dts = p_audio_buf->start_date + 1;
1530 p_sys->i_master_drift = p_audio_buf->start_date - i_dts;
1531 date_Increment( &id->interpolated_pts, p_audio_buf->i_nb_samples );
1532 p_audio_buf->start_date -= p_sys->i_master_drift;
1533 p_audio_buf->end_date -= p_sys->i_master_drift;
1536 p_audio_block = p_audio_buf->p_sys;
1537 p_audio_block->i_buffer = p_audio_buf->i_nb_bytes;
1538 p_audio_block->i_dts = p_audio_block->i_pts =
1539 p_audio_buf->start_date;
1540 p_audio_block->i_length = p_audio_buf->end_date -
1541 p_audio_buf->start_date;
1542 p_audio_block->i_samples = p_audio_buf->i_nb_samples;
1544 /* Run filter chain */
1545 for( i = 0; i < id->i_filter; i++ )
1548 id->pp_filter[i]->pf_audio_filter( id->pp_filter[i],
1552 /* Run user specified filter chain */
1553 for( i = 0; i < id->i_ufilter; i++ )
1556 id->pp_ufilter[i]->pf_audio_filter( id->pp_ufilter[i],
1560 p_audio_buf->p_buffer = p_audio_block->p_buffer;
1561 p_audio_buf->i_nb_bytes = p_audio_block->i_buffer;
1562 p_audio_buf->i_nb_samples = p_audio_block->i_samples;
1563 p_audio_buf->start_date = p_audio_block->i_dts;
1564 p_audio_buf->end_date = p_audio_block->i_dts + p_audio_block->i_length;
1566 p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf );
1567 block_ChainAppend( out, p_block );
1568 block_Release( p_audio_block );
1569 free( p_audio_buf );
1575 static void audio_release_buffer( aout_buffer_t *p_buffer )
1577 if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
1578 if( p_buffer ) free( p_buffer );
1581 static aout_buffer_t *audio_new_buffer( decoder_t *p_dec, int i_samples )
1583 aout_buffer_t *p_buffer;
1587 if( p_dec->fmt_out.audio.i_bitspersample )
1589 i_size = i_samples * p_dec->fmt_out.audio.i_bitspersample / 8 *
1590 p_dec->fmt_out.audio.i_channels;
1592 else if( p_dec->fmt_out.audio.i_bytes_per_frame &&
1593 p_dec->fmt_out.audio.i_frame_length )
1595 i_size = i_samples * p_dec->fmt_out.audio.i_bytes_per_frame /
1596 p_dec->fmt_out.audio.i_frame_length;
1600 i_size = i_samples * 4 * p_dec->fmt_out.audio.i_channels;
1603 p_buffer = malloc( sizeof(aout_buffer_t) );
1604 p_buffer->pf_release = audio_release_buffer;
1605 p_buffer->p_sys = p_block = block_New( p_dec, i_size );
1607 p_buffer->p_buffer = p_block->p_buffer;
1608 p_buffer->i_size = p_buffer->i_nb_bytes = p_block->i_buffer;
1609 p_buffer->i_nb_samples = i_samples;
1610 p_block->i_samples = i_samples;
1615 static void audio_del_buffer( decoder_t *p_dec, aout_buffer_t *p_buffer )
1617 if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
1618 if( p_buffer ) free( p_buffer );
1624 static int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_t *id )
1626 sout_stream_sys_t *p_sys = p_stream->p_sys;
1630 * Initialization of decoder structures
1632 id->p_decoder->fmt_out = id->p_decoder->fmt_in;
1633 id->p_decoder->fmt_out.i_extra = 0;
1634 id->p_decoder->fmt_out.p_extra = 0;
1635 id->p_decoder->pf_decode_video = 0;
1636 id->p_decoder->pf_vout_buffer_new = video_new_buffer_decoder;
1637 id->p_decoder->pf_vout_buffer_del = video_del_buffer_decoder;
1638 id->p_decoder->pf_picture_link = video_link_picture_decoder;
1639 id->p_decoder->pf_picture_unlink = video_unlink_picture_decoder;
1640 id->p_decoder->p_owner = malloc( sizeof(decoder_owner_sys_t) );
1641 for( i = 0; i < PICTURE_RING_SIZE; i++ )
1642 id->p_decoder->p_owner->pp_pics[i] = 0;
1643 id->p_decoder->p_owner->p_sys = p_sys;
1644 /* id->p_decoder->p_cfg = p_sys->p_video_cfg; */
1646 id->p_decoder->p_module =
1647 module_Need( id->p_decoder, "decoder", "$codec", 0 );
1649 if( !id->p_decoder->p_module )
1651 msg_Err( p_stream, "cannot find decoder" );
1652 return VLC_EGENERIC;
1657 * Because some info about the decoded input will only be available
1658 * once the first frame is decoded, we actually only test the availability
1659 * of the encoder here.
1662 /* Initialization of encoder format structures */
1663 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1664 id->p_decoder->fmt_out.i_codec );
1665 id->p_encoder->fmt_in.video.i_chroma = id->p_decoder->fmt_out.i_codec;
1667 /* The dimensions will be set properly later on.
1668 * Just put sensible values so we can test an encoder is available. */
1669 id->p_encoder->fmt_in.video.i_width =
1670 id->p_encoder->fmt_out.video.i_width ?
1671 id->p_encoder->fmt_out.video.i_width :
1672 id->p_decoder->fmt_in.video.i_width ?
1673 id->p_decoder->fmt_in.video.i_width : 16;
1674 id->p_encoder->fmt_in.video.i_height =
1675 id->p_encoder->fmt_out.video.i_height ?
1676 id->p_encoder->fmt_out.video.i_height :
1677 id->p_decoder->fmt_in.video.i_height ?
1678 id->p_decoder->fmt_in.video.i_height : 16;
1679 id->p_encoder->fmt_in.video.i_frame_rate = 25;
1680 id->p_encoder->fmt_in.video.i_frame_rate_base = 1;
1682 id->p_encoder->i_threads = p_sys->i_threads;
1683 id->p_encoder->p_cfg = p_sys->p_video_cfg;
1685 id->p_encoder->p_module =
1686 module_Need( id->p_encoder, "encoder", p_sys->psz_venc, VLC_TRUE );
1687 if( !id->p_encoder->p_module )
1689 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_venc );
1690 module_Unneed( id->p_decoder, id->p_decoder->p_module );
1691 id->p_decoder->p_module = 0;
1692 return VLC_EGENERIC;
1695 /* Close the encoder.
1696 * We'll open it only when we have the first frame. */
1697 module_Unneed( id->p_encoder, id->p_encoder->p_module );
1698 if( id->p_encoder->fmt_out.p_extra )
1699 free( id->p_encoder->fmt_out.p_extra );
1700 id->p_encoder->p_module = NULL;
1702 if( p_sys->i_threads >= 1 )
1704 int i_priority = p_sys->b_high_priority ? VLC_THREAD_PRIORITY_OUTPUT :
1705 VLC_THREAD_PRIORITY_VIDEO;
1706 p_sys->id_video = id;
1707 vlc_mutex_init( p_stream, &p_sys->lock_out );
1708 vlc_cond_init( p_stream, &p_sys->cond );
1709 memset( p_sys->pp_pics, 0, sizeof(p_sys->pp_pics) );
1710 p_sys->i_first_pic = 0;
1711 p_sys->i_last_pic = 0;
1712 p_sys->p_buffers = NULL;
1713 p_sys->b_die = p_sys->b_error = 0;
1714 if( vlc_thread_create( p_sys, "encoder", EncoderThread, i_priority,
1717 msg_Err( p_stream, "cannot spawn encoder thread" );
1718 module_Unneed( id->p_decoder, id->p_decoder->p_module );
1719 id->p_decoder->p_module = 0;
1720 return VLC_EGENERIC;
1727 static int transcode_video_encoder_open( sout_stream_t *p_stream,
1728 sout_stream_id_t *id )
1730 sout_stream_sys_t *p_sys = p_stream->p_sys;
1732 /* Calculate scaling, padding, cropping etc. */
1733 /* width/height of source */
1734 int i_src_width = id->p_decoder->fmt_out.video.i_width;
1735 int i_src_height = id->p_decoder->fmt_out.video.i_height;
1737 /* with/height scaling */
1738 float f_scale_width = 1;
1739 float f_scale_height = 1;
1741 /* width/height of output stream */
1746 float f_aspect = (float)id->p_decoder->fmt_out.video.i_aspect /
1749 msg_Dbg( p_stream, "decoder aspect is %i:%i",
1750 id->p_decoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
1752 /* Change f_aspect from source frame to source pixel */
1753 f_aspect = f_aspect * i_src_height / i_src_width;
1754 msg_Dbg( p_stream, "source pixel aspect is %f:1", f_aspect );
1756 /* width/height after cropping */
1757 p_sys->i_src_x_offset = p_sys->i_crop_left & ~1;
1758 p_sys->i_src_y_offset = p_sys->i_crop_top & ~1;
1759 p_sys->i_crop_width = i_src_width - ( p_sys->i_crop_left & ~1 ) -
1760 ( p_sys->i_crop_right & ~1 );
1761 p_sys->i_crop_height = i_src_height - ( p_sys->i_crop_top & ~1 ) -
1762 ( p_sys->i_crop_bottom & ~1 );
1764 /* Calculate scaling factor for specified parameters */
1765 if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1766 id->p_encoder->fmt_out.video.i_height <= 0 && p_sys->f_scale )
1768 /* Global scaling. Make sure width will remain a factor of 16 */
1771 int i_new_width = i_src_width * p_sys->f_scale;
1773 if( i_new_width % 16 <= 7 && i_new_width >= 16 )
1774 i_new_width -= i_new_width % 16;
1776 i_new_width += 16 - i_new_width % 16;
1778 f_real_scale = (float)( i_new_width ) / (float) i_src_width;
1780 i_new_height = __MAX( 16, i_src_height * (float)f_real_scale );
1782 f_scale_width = f_real_scale;
1783 f_scale_height = (float) i_new_height / (float) i_src_height;
1785 else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1786 id->p_encoder->fmt_out.video.i_height <= 0 )
1788 /* Only width specified */
1789 f_scale_width = (float)id->p_encoder->fmt_out.video.i_width /
1790 p_sys->i_crop_width;
1791 f_scale_height = f_scale_width;
1793 else if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1794 id->p_encoder->fmt_out.video.i_height > 0 )
1796 /* Only height specified */
1797 f_scale_height = (float)id->p_encoder->fmt_out.video.i_height /
1798 p_sys->i_crop_height;
1799 f_scale_width = f_scale_height;
1801 else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1802 id->p_encoder->fmt_out.video.i_height > 0 )
1804 /* Width and height specified */
1805 f_scale_width = (float)id->p_encoder->fmt_out.video.i_width
1806 / p_sys->i_crop_width;
1807 f_scale_height = (float)id->p_encoder->fmt_out.video.i_height
1808 / p_sys->i_crop_height;
1811 /* check maxwidth and maxheight
1812 * note: maxwidth and maxheight currently does not handle
1813 * canvas and padding, just scaling and cropping.
1815 if( p_sys->i_maxwidth && f_scale_width > (float)p_sys->i_maxwidth /
1816 p_sys->i_crop_width )
1818 f_scale_width = (float)p_sys->i_maxwidth / p_sys->i_crop_width;
1820 if( p_sys->i_maxheight && f_scale_height > (float)p_sys->i_maxheight /
1821 p_sys->i_crop_height )
1823 f_scale_height = (float)p_sys->i_maxheight / p_sys->i_crop_height;
1826 /* Change aspect ratio from source pixel to scaled pixel */
1827 f_aspect = f_aspect * f_scale_height / f_scale_width;
1828 msg_Dbg( p_stream, "scaled pixel aspect is %f:1", f_aspect );
1830 /* Correct scaling for target aspect ratio
1831 * Shrink video if necessary
1833 if ( p_sys->i_canvas_aspect > 0 )
1835 float f_target_aspect = (float)p_sys->i_canvas_aspect /
1838 if( p_sys->i_canvas_width > 0 && p_sys->i_canvas_height > 0)
1840 /* Calculate pixel aspect of canvas */
1841 f_target_aspect = f_target_aspect / p_sys->i_canvas_width *
1842 p_sys->i_canvas_height;
1844 if( f_target_aspect > f_aspect )
1846 /* Reduce width scale to increase aspect */
1847 f_scale_width = f_scale_width * f_aspect / f_target_aspect;
1851 /* Reduce height scale to decrease aspect */
1852 f_scale_height = f_scale_height * f_target_aspect / f_aspect;
1854 f_aspect = f_target_aspect;
1855 msg_Dbg( p_stream, "canvas scaled pixel aspect is %f:1", f_aspect );
1858 /* f_scale_width and f_scale_height are now final */
1859 /* Calculate width, height from scaling
1860 * Make sure its multiple of 2
1862 i_dst_width = 2 * (int)( p_sys->i_crop_width * f_scale_width / 2 + 0.5 );
1864 (int)( p_sys->i_crop_height * f_scale_height / 2 + 0.5 );
1866 p_sys->i_nopadd_width = i_dst_width;
1867 p_sys->i_nopadd_height = i_dst_height;
1868 p_sys->i_dst_x_offset = 0;
1869 p_sys->i_dst_y_offset = 0;
1871 /* Handle canvas and padding */
1872 if( p_sys->i_canvas_width <= 0 )
1874 /* No canvas width set, add explicit padding border */
1875 i_dst_width = p_sys->i_nopadd_width + ( p_sys->i_padd_left & ~1 ) +
1876 ( p_sys->i_padd_right & ~1 );
1877 p_sys->i_dst_x_offset = ( p_sys->i_padd_left & ~1 );
1881 /* Canvas set, check if we have to padd or crop */
1882 if( p_sys->i_canvas_width < p_sys->i_nopadd_width )
1884 /* need to crop more, but keep same scaling */
1885 int i_crop = 2 * (int)( ( p_sys->i_canvas_width & ~1 ) /
1886 f_scale_width / 2 + 0.5 );
1888 p_sys->i_src_x_offset += ( ( p_sys->i_crop_width - i_crop ) / 2 )
1890 p_sys->i_crop_width = i_crop;
1891 i_dst_width = p_sys->i_canvas_width & ~1;
1892 p_sys->i_nopadd_width = i_dst_width;
1894 else if( p_sys->i_canvas_width > p_sys->i_nopadd_width )
1897 i_dst_width = p_sys->i_canvas_width & ~1;
1898 p_sys->i_dst_x_offset = ( i_dst_width - p_sys->i_nopadd_width )/2;
1899 p_sys->i_dst_x_offset = p_sys->i_dst_x_offset & ~1;
1903 if( p_sys->i_canvas_height <= 0 )
1905 /* No canvas set, add padding border */
1906 i_dst_height = p_sys->i_nopadd_height + ( p_sys->i_padd_top & ~1 ) +
1907 ( p_sys->i_padd_bottom & ~1 );
1908 p_sys->i_dst_y_offset = ( p_sys->i_padd_top & ~1 );
1912 /* Canvas set, check if we have to padd or crop */
1913 if( p_sys->i_canvas_height < p_sys->i_nopadd_height )
1915 /* need to crop more, but keep same scaling */
1916 int i_crop = 2 * (int)( ( p_sys->i_canvas_height & ~1 ) /
1917 f_scale_height / 2 + 0.5 );
1919 p_sys->i_src_y_offset += ( ( p_sys->i_crop_height - i_crop ) / 2 )
1921 p_sys->i_crop_height = i_crop;
1922 i_dst_height = p_sys->i_canvas_height & ~1;
1923 p_sys->i_nopadd_height = i_dst_height;
1925 else if( p_sys->i_canvas_height > p_sys->i_nopadd_height )
1928 i_dst_height = p_sys->i_canvas_height & ~1;
1929 p_sys->i_dst_y_offset = ( i_dst_height - p_sys->i_nopadd_height )
1931 p_sys->i_dst_y_offset = p_sys->i_dst_y_offset & ~1;
1935 /* Change aspect ratio from scaled pixel to output frame */
1936 f_aspect = f_aspect * i_dst_width / i_dst_height;
1938 /* Store calculated values */
1939 id->p_encoder->fmt_out.video.i_width = i_dst_width;
1940 id->p_encoder->fmt_out.video.i_height = i_dst_height;
1942 id->p_encoder->fmt_in.video.i_width = i_dst_width;
1943 id->p_encoder->fmt_in.video.i_height = i_dst_height;
1945 msg_Dbg( p_stream, "source %ix%i, crop %ix%i, "
1946 "destination %ix%i, padding %ix%i",
1947 i_src_width, i_src_height,
1948 p_sys->i_crop_width, p_sys->i_crop_height,
1949 p_sys->i_nopadd_width, p_sys->i_nopadd_height,
1950 i_dst_width, i_dst_height
1953 /* Handle frame rate conversion */
1954 if( !id->p_encoder->fmt_out.video.i_frame_rate ||
1955 !id->p_encoder->fmt_out.video.i_frame_rate_base )
1957 if( id->p_decoder->fmt_out.video.i_frame_rate &&
1958 id->p_decoder->fmt_out.video.i_frame_rate_base )
1960 id->p_encoder->fmt_out.video.i_frame_rate =
1961 id->p_decoder->fmt_out.video.i_frame_rate;
1962 id->p_encoder->fmt_out.video.i_frame_rate_base =
1963 id->p_decoder->fmt_out.video.i_frame_rate_base;
1967 /* Pick a sensible default value */
1968 id->p_encoder->fmt_out.video.i_frame_rate = 25;
1969 id->p_encoder->fmt_out.video.i_frame_rate_base = 1;
1973 id->p_encoder->fmt_in.video.i_frame_rate =
1974 id->p_encoder->fmt_out.video.i_frame_rate;
1975 id->p_encoder->fmt_in.video.i_frame_rate_base =
1976 id->p_encoder->fmt_out.video.i_frame_rate_base;
1978 date_Init( &id->interpolated_pts,
1979 id->p_encoder->fmt_out.video.i_frame_rate,
1980 id->p_encoder->fmt_out.video.i_frame_rate_base );
1982 /* Check whether a particular aspect ratio was requested */
1983 if( !id->p_encoder->fmt_out.video.i_aspect )
1985 id->p_encoder->fmt_out.video.i_aspect = (int)( f_aspect * VOUT_ASPECT_FACTOR + 0.5 );
1987 id->p_encoder->fmt_in.video.i_aspect =
1988 id->p_encoder->fmt_out.video.i_aspect;
1990 msg_Dbg( p_stream, "encoder aspect is %i:%i", id->p_encoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
1992 id->p_encoder->p_module =
1993 module_Need( id->p_encoder, "encoder", p_sys->psz_venc, VLC_TRUE );
1994 if( !id->p_encoder->p_module )
1996 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_venc );
1997 return VLC_EGENERIC;
2000 id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
2002 /* Hack for mp2v/mp1v transcoding support */
2003 if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','1','v') ||
2004 id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','2','v') )
2006 id->p_encoder->fmt_out.i_codec = VLC_FOURCC('m','p','g','v');
2009 id->id = p_stream->p_sys->p_out->pf_add( p_stream->p_sys->p_out,
2010 &id->p_encoder->fmt_out );
2013 msg_Err( p_stream, "cannot add this stream" );
2014 return VLC_EGENERIC;
2020 static void transcode_video_close( sout_stream_t *p_stream,
2021 sout_stream_id_t *id )
2025 if( p_stream->p_sys->i_threads >= 1 )
2027 vlc_mutex_lock( &p_stream->p_sys->lock_out );
2028 p_stream->p_sys->b_die = 1;
2029 vlc_cond_signal( &p_stream->p_sys->cond );
2030 vlc_mutex_unlock( &p_stream->p_sys->lock_out );
2031 vlc_thread_join( p_stream->p_sys );
2032 vlc_mutex_destroy( &p_stream->p_sys->lock_out );
2033 vlc_cond_destroy( &p_stream->p_sys->cond );
2037 if( id->p_decoder->p_module )
2038 module_Unneed( id->p_decoder, id->p_decoder->p_module );
2040 if( id->p_decoder->p_owner )
2042 /* Clean-up pictures ring buffer */
2043 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2045 if( id->p_decoder->p_owner->pp_pics[i] )
2046 video_del_buffer( VLC_OBJECT(id->p_decoder),
2047 id->p_decoder->p_owner->pp_pics[i] );
2049 free( id->p_decoder->p_owner );
2053 if( id->p_encoder->p_module )
2054 module_Unneed( id->p_encoder, id->p_encoder->p_module );
2057 for( i = 0; i < id->i_filter; i++ )
2059 vlc_object_detach( id->pp_filter[i] );
2060 if( id->pp_filter[i]->p_module )
2061 module_Unneed( id->pp_filter[i], id->pp_filter[i]->p_module );
2063 /* Clean-up pictures ring buffer */
2064 for( j = 0; j < PICTURE_RING_SIZE; j++ )
2066 if( id->pp_filter[i]->p_owner->pp_pics[j] )
2067 video_del_buffer( VLC_OBJECT(id->pp_filter[i]),
2068 id->pp_filter[i]->p_owner->pp_pics[j] );
2070 free( id->pp_filter[i]->p_owner );
2071 vlc_object_destroy( id->pp_filter[i] );
2072 id->pp_filter[i] = NULL;
2075 for( i = 0; i < id->i_ufilter; i++ )
2077 vlc_object_detach( id->pp_ufilter[i] );
2078 if( id->pp_ufilter[i]->p_module )
2079 module_Unneed( id->pp_ufilter[i], id->pp_ufilter[i]->p_module );
2081 /* Clean-up pictures ring buffer */
2082 for( j = 0; j < PICTURE_RING_SIZE; j++ )
2084 if( id->pp_ufilter[i]->p_owner->pp_pics[j] )
2085 video_del_buffer( VLC_OBJECT(id->pp_ufilter[i]),
2086 id->pp_ufilter[i]->p_owner->pp_pics[j] );
2088 free( id->pp_ufilter[i]->p_owner );
2089 vlc_object_destroy( id->pp_ufilter[i] );
2090 id->pp_ufilter[i] = NULL;
2094 static int transcode_video_process( sout_stream_t *p_stream,
2095 sout_stream_id_t *id,
2096 block_t *in, block_t **out )
2098 sout_stream_sys_t *p_sys = p_stream->p_sys;
2099 int i_duplicate = 1, i;
2100 picture_t *p_pic, *p_pic2 = NULL;
2102 input_thread_t *p_input = NULL;
2104 if( p_stream->p_parent->p_parent && p_stream->p_parent->p_parent->
2105 i_object_type == VLC_OBJECT_INPUT )
2106 p_input = (input_thread_t *)p_stream->p_parent->p_parent;
2108 while( (p_pic = id->p_decoder->pf_decode_video( id->p_decoder, &in )) )
2110 subpicture_t *p_subpic = 0;
2112 stats_UpdateInteger( p_input, p_input->counters.p_decoded_video,
2115 if( p_stream->p_sout->i_out_pace_nocontrol && p_sys->b_hurry_up )
2117 mtime_t current_date = mdate();
2118 if( current_date + 50000 > p_pic->date )
2120 msg_Dbg( p_stream, "late picture skipped ("I64Fd")",
2121 current_date + 50000 - p_pic->date );
2122 p_pic->pf_release( p_pic );
2127 if( p_sys->b_master_sync )
2129 mtime_t i_video_drift;
2130 mtime_t i_master_drift = p_sys->i_master_drift;
2133 i_pts = date_Get( &id->interpolated_pts ) + 1;
2134 if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2135 || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2137 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2138 date_Set( &id->interpolated_pts, p_pic->date );
2139 i_pts = p_pic->date + 1;
2141 i_video_drift = p_pic->date - i_pts;
2144 /* Set the pts of the frame being encoded */
2145 p_pic->date = i_pts;
2147 if( i_video_drift < i_master_drift - 50000 )
2150 msg_Dbg( p_stream, "dropping frame (%i)",
2151 (int)(i_video_drift - i_master_drift) );
2153 p_pic->pf_release( p_pic );
2156 else if( i_video_drift > i_master_drift + 50000 )
2159 msg_Dbg( p_stream, "adding frame (%i)",
2160 (int)(i_video_drift - i_master_drift) );
2166 if( !id->p_encoder->p_module )
2168 if( transcode_video_encoder_open( p_stream, id ) != VLC_SUCCESS )
2170 p_pic->pf_release( p_pic );
2171 transcode_video_close( p_stream, id );
2172 id->b_transcode = VLC_FALSE;
2173 return VLC_EGENERIC;
2177 if( p_stream->p_sys->b_deinterlace )
2179 id->pp_filter[id->i_filter] =
2180 vlc_object_create( p_stream, VLC_OBJECT_FILTER );
2181 vlc_object_attach( id->pp_filter[id->i_filter], p_stream );
2183 id->pp_filter[id->i_filter]->pf_vout_buffer_new =
2184 video_new_buffer_filter;
2185 id->pp_filter[id->i_filter]->pf_vout_buffer_del =
2186 video_del_buffer_filter;
2188 id->pp_filter[id->i_filter]->fmt_in = id->p_decoder->fmt_out;
2189 id->pp_filter[id->i_filter]->fmt_out = id->p_decoder->fmt_out;
2190 id->pp_filter[id->i_filter]->p_cfg = p_sys->p_deinterlace_cfg;
2191 id->pp_filter[id->i_filter]->p_module =
2192 module_Need( id->pp_filter[id->i_filter],
2193 "video filter2", p_sys->psz_deinterlace, 0 );
2194 if( id->pp_filter[id->i_filter]->p_module )
2196 id->pp_filter[id->i_filter]->p_owner =
2197 malloc( sizeof(filter_owner_sys_t) );
2198 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2199 id->pp_filter[id->i_filter]->p_owner->pp_pics[i] = 0;
2200 id->pp_filter[id->i_filter]->p_owner->p_sys = p_sys;
2206 msg_Dbg( p_stream, "no video filter found" );
2207 vlc_object_detach( id->pp_filter[id->i_filter] );
2208 vlc_object_destroy( id->pp_filter[id->i_filter] );
2212 /* Check if we need a filter for chroma conversion or resizing */
2213 if( id->p_decoder->fmt_out.video.i_chroma !=
2214 id->p_encoder->fmt_in.video.i_chroma ||
2216 (int)id->p_decoder->fmt_out.video.i_width != p_sys->i_crop_width ||
2217 p_sys->i_crop_width != p_sys->i_nopadd_width ||
2218 p_sys->i_nopadd_width != (int)id->p_encoder->fmt_out.video.i_width ||
2220 (int)id->p_decoder->fmt_out.video.i_height != p_sys->i_crop_height ||
2221 p_sys->i_crop_height != p_sys->i_nopadd_height ||
2222 p_sys->i_nopadd_height != (int)id->p_encoder->fmt_out.video.i_height)
2224 id->pp_filter[id->i_filter] =
2225 vlc_object_create( p_stream, VLC_OBJECT_FILTER );
2226 vlc_object_attach( id->pp_filter[id->i_filter], p_stream );
2228 id->pp_filter[id->i_filter]->pf_vout_buffer_new =
2229 video_new_buffer_filter;
2230 id->pp_filter[id->i_filter]->pf_vout_buffer_del =
2231 video_del_buffer_filter;
2233 id->pp_filter[id->i_filter]->fmt_in = id->p_decoder->fmt_out;
2234 id->pp_filter[id->i_filter]->fmt_out = id->p_encoder->fmt_in;
2235 id->pp_filter[id->i_filter]->p_cfg = NULL;
2237 id->pp_filter[id->i_filter]->fmt_in.video.i_x_offset = p_sys->i_src_x_offset;
2238 id->pp_filter[id->i_filter]->fmt_in.video.i_y_offset = p_sys->i_src_y_offset;
2239 id->pp_filter[id->i_filter]->fmt_in.video.i_visible_width = p_sys->i_crop_width;
2240 id->pp_filter[id->i_filter]->fmt_in.video.i_visible_height = p_sys->i_crop_height;
2242 id->pp_filter[id->i_filter]->fmt_out.video.i_x_offset = p_sys->i_dst_x_offset;
2243 id->pp_filter[id->i_filter]->fmt_out.video.i_y_offset = p_sys->i_dst_y_offset;
2244 id->pp_filter[id->i_filter]->fmt_out.video.i_visible_width = p_sys->i_nopadd_width;
2245 id->pp_filter[id->i_filter]->fmt_out.video.i_visible_height = p_sys->i_nopadd_height;
2247 id->pp_filter[id->i_filter]->p_module =
2248 module_Need( id->pp_filter[id->i_filter],
2249 "crop padd", 0, 0 );
2250 if( id->pp_filter[id->i_filter]->p_module )
2252 id->pp_filter[id->i_filter]->p_owner =
2253 malloc( sizeof(filter_owner_sys_t) );
2254 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2255 id->pp_filter[id->i_filter]->p_owner->pp_pics[i] = 0;
2256 id->pp_filter[id->i_filter]->p_owner->p_sys = p_sys;
2262 msg_Dbg( p_stream, "no video filter found" );
2263 vlc_object_detach( id->pp_filter[id->i_filter] );
2264 vlc_object_destroy( id->pp_filter[id->i_filter] );
2266 p_pic->pf_release( p_pic );
2267 transcode_video_close( p_stream, id );
2268 id->b_transcode = VLC_FALSE;
2269 return VLC_EGENERIC;
2273 for( i = 0; (i < p_sys->i_vfilters) && (id->i_ufilter < TRANSCODE_FILTERS); i++ )
2275 id->pp_ufilter[id->i_ufilter] =
2276 vlc_object_create( p_stream, VLC_OBJECT_FILTER );
2277 vlc_object_attach( id->pp_ufilter[id->i_ufilter], p_stream );
2279 id->pp_ufilter[id->i_ufilter]->pf_vout_buffer_new =
2280 video_new_buffer_filter;
2281 id->pp_ufilter[id->i_ufilter]->pf_vout_buffer_del =
2282 video_del_buffer_filter;
2284 id->pp_ufilter[id->i_ufilter]->fmt_in = id->p_encoder->fmt_in;
2285 id->pp_ufilter[id->i_ufilter]->fmt_out = id->p_encoder->fmt_in;
2286 id->pp_ufilter[id->i_ufilter]->p_cfg = p_sys->p_vfilters_cfg[i];
2287 id->pp_ufilter[id->i_ufilter]->p_module =
2288 module_Need( id->pp_ufilter[id->i_ufilter],
2289 "video filter2", p_sys->psz_vfilters[i], 0 );
2290 if( id->pp_ufilter[id->i_ufilter]->p_module )
2292 id->pp_ufilter[id->i_ufilter]->p_owner =
2293 malloc( sizeof(filter_owner_sys_t) );
2294 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2295 id->pp_ufilter[id->i_ufilter]->p_owner->pp_pics[i] = 0;
2296 id->pp_ufilter[id->i_ufilter]->p_owner->p_sys = p_sys;
2301 msg_Dbg( p_stream, "no video filter found" );
2302 vlc_object_detach( id->pp_ufilter[id->i_ufilter] );
2303 vlc_object_destroy( id->pp_ufilter[id->i_ufilter] );
2304 id->pp_ufilter[id->i_ufilter] = NULL;
2309 /* Run filter chain */
2310 for( i = 0; i < id->i_filter; i++ )
2312 p_pic = id->pp_filter[i]->pf_video_filter(id->pp_filter[i], p_pic);
2319 /* Check if we have a subpicture to overlay */
2322 p_subpic = spu_SortSubpictures( p_sys->p_spu, p_pic->date );
2323 /* TODO: get another pic */
2326 /* Overlay subpicture */
2329 int i_scale_width, i_scale_height;
2330 video_format_t *p_fmt;
2332 i_scale_width = id->p_encoder->fmt_in.video.i_width * 1000 /
2333 id->p_decoder->fmt_out.video.i_width;
2334 i_scale_height = id->p_encoder->fmt_in.video.i_height * 1000 /
2335 id->p_decoder->fmt_out.video.i_height;
2337 if( p_pic->i_refcount && !id->i_filter )
2339 /* We can't modify the picture, we need to duplicate it */
2340 picture_t *p_tmp = video_new_buffer_decoder( id->p_decoder );
2343 vout_CopyPicture( p_stream, p_tmp, p_pic );
2344 p_pic->pf_release( p_pic );
2350 p_fmt = &id->pp_filter[id->i_filter -1]->fmt_out.video;
2352 p_fmt = &id->p_decoder->fmt_out.video;
2354 /* FIXME (shouldn't have to be done here) */
2355 p_fmt->i_sar_num = p_fmt->i_aspect *
2356 p_fmt->i_height / p_fmt->i_width;
2357 p_fmt->i_sar_den = VOUT_ASPECT_FACTOR;
2359 spu_RenderSubpictures( p_sys->p_spu, p_fmt, p_pic, p_pic, p_subpic,
2360 i_scale_width, i_scale_height );
2363 /* Run user specified filter chain */
2364 for( i = 0; i < id->i_ufilter; i++ )
2366 p_pic = id->pp_ufilter[i]->pf_video_filter(id->pp_ufilter[i], p_pic);
2369 if( p_sys->i_threads == 0 )
2372 p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
2373 block_ChainAppend( out, p_block );
2376 if( p_sys->b_master_sync )
2378 mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
2379 if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2380 || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2382 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2383 date_Set( &id->interpolated_pts, p_pic->date );
2384 i_pts = p_pic->date + 1;
2386 date_Increment( &id->interpolated_pts, 1 );
2389 if( p_sys->b_master_sync && i_duplicate > 1 )
2391 mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
2392 if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2393 || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2395 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2396 date_Set( &id->interpolated_pts, p_pic->date );
2397 i_pts = p_pic->date + 1;
2399 date_Increment( &id->interpolated_pts, 1 );
2401 if( p_sys->i_threads >= 1 )
2403 /* We can't modify the picture, we need to duplicate it */
2404 p_pic2 = video_new_buffer_decoder( id->p_decoder );
2405 if( p_pic2 != NULL )
2407 vout_CopyPicture( p_stream, p_pic2, p_pic );
2408 p_pic2->date = i_pts;
2414 p_pic->date = i_pts;
2415 p_block = id->p_encoder->pf_encode_video(id->p_encoder, p_pic);
2416 block_ChainAppend( out, p_block );
2420 if( p_sys->i_threads == 0 )
2422 p_pic->pf_release( p_pic );
2426 vlc_mutex_lock( &p_sys->lock_out );
2427 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic;
2428 p_sys->i_last_pic %= PICTURE_RING_SIZE;
2429 *out = p_sys->p_buffers;
2430 p_sys->p_buffers = NULL;
2431 if( p_pic2 != NULL )
2433 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic2;
2434 p_sys->i_last_pic %= PICTURE_RING_SIZE;
2436 vlc_cond_signal( &p_sys->cond );
2437 vlc_mutex_unlock( &p_sys->lock_out );
2444 static int EncoderThread( sout_stream_sys_t *p_sys )
2446 sout_stream_id_t *id = p_sys->id_video;
2449 while( !p_sys->b_die && !p_sys->b_error )
2453 vlc_mutex_lock( &p_sys->lock_out );
2454 while( p_sys->i_last_pic == p_sys->i_first_pic )
2456 vlc_cond_wait( &p_sys->cond, &p_sys->lock_out );
2457 if( p_sys->b_die || p_sys->b_error ) break;
2459 if( p_sys->b_die || p_sys->b_error )
2461 vlc_mutex_unlock( &p_sys->lock_out );
2465 p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2466 p_sys->i_first_pic %= PICTURE_RING_SIZE;
2467 vlc_mutex_unlock( &p_sys->lock_out );
2469 p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
2470 vlc_mutex_lock( &p_sys->lock_out );
2471 block_ChainAppend( &p_sys->p_buffers, p_block );
2473 vlc_mutex_unlock( &p_sys->lock_out );
2474 p_pic->pf_release( p_pic );
2477 while( p_sys->i_last_pic != p_sys->i_first_pic )
2479 p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2480 p_sys->i_first_pic %= PICTURE_RING_SIZE;
2481 p_pic->pf_release( p_pic );
2483 block_ChainRelease( p_sys->p_buffers );
2488 struct picture_sys_t
2490 vlc_object_t *p_owner;
2493 static void video_release_buffer( picture_t *p_pic )
2495 if( p_pic && !p_pic->i_refcount && p_pic->pf_release && p_pic->p_sys )
2497 video_del_buffer_decoder( (decoder_t *)p_pic->p_sys->p_owner, p_pic );
2499 else if( p_pic && p_pic->i_refcount > 0 ) p_pic->i_refcount--;
2502 static picture_t *video_new_buffer( vlc_object_t *p_this, picture_t **pp_ring,
2503 sout_stream_sys_t *p_sys )
2505 decoder_t *p_dec = (decoder_t *)p_this;
2509 /* Find an empty space in the picture ring buffer */
2510 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2512 if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
2514 pp_ring[i]->i_status = RESERVED_PICTURE;
2518 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2520 if( pp_ring[i] == 0 ) break;
2523 if( i == PICTURE_RING_SIZE && p_sys->i_threads >= 1 )
2525 int i_first_pic = p_sys->i_first_pic;
2527 if( p_sys->i_first_pic != p_sys->i_last_pic )
2529 /* Encoder still has stuff to encode, wait to clear-up the list */
2530 while( p_sys->i_first_pic == i_first_pic )
2534 /* Find an empty space in the picture ring buffer */
2535 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2537 if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
2539 pp_ring[i]->i_status = RESERVED_PICTURE;
2543 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2545 if( pp_ring[i] == 0 ) break;
2549 if( i == PICTURE_RING_SIZE )
2551 msg_Err( p_this, "decoder/filter is leaking pictures, "
2552 "resetting its ring buffer" );
2554 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2556 pp_ring[i]->pf_release( pp_ring[i] );
2562 p_pic = malloc( sizeof(picture_t) );
2563 p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
2564 vout_AllocatePicture( VLC_OBJECT(p_dec), p_pic,
2565 p_dec->fmt_out.video.i_chroma,
2566 p_dec->fmt_out.video.i_width,
2567 p_dec->fmt_out.video.i_height,
2568 p_dec->fmt_out.video.i_aspect );
2570 if( !p_pic->i_planes )
2576 p_pic->pf_release = video_release_buffer;
2577 p_pic->p_sys = malloc( sizeof(picture_sys_t) );
2578 p_pic->p_sys->p_owner = p_this;
2579 p_pic->i_status = RESERVED_PICTURE;
2585 static picture_t *video_new_buffer_decoder( decoder_t *p_dec )
2587 return video_new_buffer( VLC_OBJECT(p_dec),
2588 p_dec->p_owner->pp_pics, p_dec->p_owner->p_sys );
2591 static picture_t *video_new_buffer_filter( filter_t *p_filter )
2593 return video_new_buffer( VLC_OBJECT(p_filter),
2594 p_filter->p_owner->pp_pics,
2595 p_filter->p_owner->p_sys );
2598 static void video_del_buffer( vlc_object_t *p_this, picture_t *p_pic )
2600 if( p_pic && p_pic->p_data_orig ) free( p_pic->p_data_orig );
2601 if( p_pic && p_pic->p_sys ) free( p_pic->p_sys );
2602 if( p_pic ) free( p_pic );
2605 static void video_del_buffer_decoder( decoder_t *p_decoder, picture_t *p_pic )
2607 p_pic->i_refcount = 0;
2608 p_pic->i_status = DESTROYED_PICTURE;
2611 static void video_del_buffer_filter( filter_t *p_filter, picture_t *p_pic )
2613 p_pic->i_refcount = 0;
2614 p_pic->i_status = DESTROYED_PICTURE;
2617 static void video_link_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2619 p_pic->i_refcount++;
2622 static void video_unlink_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2624 video_release_buffer( p_pic );
2630 static subpicture_t *spu_new_buffer( decoder_t * );
2631 static void spu_del_buffer( decoder_t *, subpicture_t * );
2633 static int transcode_spu_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2635 sout_stream_sys_t *p_sys = p_stream->p_sys;
2641 /* Initialization of decoder structures */
2642 id->p_decoder->pf_spu_buffer_new = spu_new_buffer;
2643 id->p_decoder->pf_spu_buffer_del = spu_del_buffer;
2644 id->p_decoder->p_owner = (decoder_owner_sys_t *)p_stream;
2645 /* id->p_decoder->p_cfg = p_sys->p_spu_cfg; */
2647 id->p_decoder->p_module =
2648 module_Need( id->p_decoder, "decoder", "$codec", 0 );
2650 if( !id->p_decoder->p_module )
2652 msg_Err( p_stream, "cannot find decoder" );
2653 return VLC_EGENERIC;
2656 if( !p_sys->b_soverlay )
2659 /* Initialization of encoder format structures */
2660 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
2661 id->p_decoder->fmt_in.i_codec );
2663 id->p_encoder->p_cfg = p_sys->p_spu_cfg;
2665 id->p_encoder->p_module =
2666 module_Need( id->p_encoder, "encoder", p_sys->psz_senc, VLC_TRUE );
2668 if( !id->p_encoder->p_module )
2670 module_Unneed( id->p_decoder, id->p_decoder->p_module );
2671 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_senc );
2672 return VLC_EGENERIC;
2678 p_sys->p_spu = spu_Create( p_stream );
2679 spu_Init( p_sys->p_spu );
2685 static void transcode_spu_close( sout_stream_t *p_stream, sout_stream_id_t *id)
2688 if( id->p_decoder->p_module )
2689 module_Unneed( id->p_decoder, id->p_decoder->p_module );
2692 if( id->p_encoder->p_module )
2693 module_Unneed( id->p_encoder, id->p_encoder->p_module );
2696 static int transcode_spu_process( sout_stream_t *p_stream,
2697 sout_stream_id_t *id,
2698 block_t *in, block_t **out )
2700 sout_stream_sys_t *p_sys = p_stream->p_sys;
2701 subpicture_t *p_subpic;
2704 p_subpic = id->p_decoder->pf_decode_sub( id->p_decoder, &in );
2705 if( !p_subpic ) return VLC_EGENERIC;
2707 if( p_sys->b_master_sync && p_sys->i_master_drift )
2709 p_subpic->i_start -= p_sys->i_master_drift;
2710 if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2713 if( p_sys->b_soverlay )
2715 spu_DisplaySubpicture( p_sys->p_spu, p_subpic );
2721 p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
2722 spu_del_buffer( id->p_decoder, p_subpic );
2726 block_ChainAppend( out, p_block );
2731 return VLC_EGENERIC;
2734 static subpicture_t *spu_new_buffer( decoder_t *p_dec )
2736 sout_stream_t *p_stream = (sout_stream_t *)p_dec->p_owner;
2737 return spu_CreateSubpicture( p_stream->p_sys->p_spu );
2740 static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_subpic )
2742 sout_stream_t *p_stream = (sout_stream_t *)p_dec->p_owner;
2743 spu_DestroySubpicture( p_stream->p_sys->p_spu, p_subpic );
2749 static int transcode_osd_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2751 sout_stream_sys_t *p_sys = p_stream->p_sys;
2755 fmt.i_id = 0xbd1f; /* pid ?? */
2756 fmt.i_group = 3; /* pmt entry ?? */
2757 fmt.i_codec = VLC_FOURCC( 'Y', 'U', 'V', 'A' );
2758 fmt.psz_language = strdup( "osd" );
2760 id = malloc( sizeof( sout_stream_id_t ) );
2761 memset( id, 0, sizeof(sout_stream_id_t) );
2764 id->p_decoder = NULL;
2765 id->p_encoder = NULL;
2767 /* Create encoder object */
2768 id->p_encoder = vlc_object_create( p_stream, VLC_OBJECT_ENCODER );
2769 if( !id->p_encoder )
2771 msg_Err( p_stream, "out of memory" );
2774 vlc_object_attach( id->p_encoder, p_stream );
2775 id->p_encoder->p_module = NULL;
2777 /* Create fake destination format */
2778 es_format_Init( &id->p_encoder->fmt_out, fmt.i_cat, 0 );
2779 id->p_encoder->fmt_out.i_id = fmt.i_id;
2780 id->p_encoder->fmt_out.i_group = fmt.i_group;
2781 id->p_encoder->fmt_out.psz_language = strdup( fmt.psz_language );
2783 if( p_sys->i_osdcodec != 0 || p_sys->psz_osdenc )
2785 msg_Dbg( p_stream, "creating osdmenu transcoding from fcc=`%4.4s' "
2786 "to fcc=`%4.4s'", (char*)&fmt.i_codec,
2787 (char*)&p_sys->i_osdcodec );
2789 /* Complete destination format */
2790 id->p_encoder->fmt_out.i_codec = p_sys->i_osdcodec;
2793 /* Initialization of encoder format structures */
2794 es_format_Init( &id->p_encoder->fmt_in, fmt.i_cat, fmt.i_codec );
2795 id->p_encoder->fmt_in.psz_language = strdup( fmt.psz_language );
2797 id->p_encoder->p_cfg = p_sys->p_osd_cfg;
2799 id->p_encoder->p_module =
2800 module_Need( id->p_encoder, "encoder", p_sys->psz_osdenc, VLC_TRUE );
2802 if( !id->p_encoder->p_module )
2804 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_osdenc );
2808 /* open output stream */
2809 id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
2810 id->b_transcode = VLC_TRUE;
2812 if( !id->id ) goto error;
2816 msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
2817 (char*)&fmt.i_codec );
2818 id->id = p_sys->p_out->pf_add( p_sys->p_out, &fmt );
2819 id->b_transcode = VLC_FALSE;
2821 if( !id->id ) goto error;
2825 p_sys->b_es_osd = VLC_TRUE;
2829 p_sys->p_spu = spu_Create( p_stream );
2830 if( spu_Init( p_sys->p_spu ) != VLC_SUCCESS )
2831 msg_Err( p_sys, "spu initialisation failed" );
2834 if( fmt.psz_language )
2835 free( fmt.psz_language );
2840 msg_Err( p_stream, "starting osd encoding thread failed" );
2841 if( id->p_encoder->p_module )
2842 module_Unneed( id->p_encoder, id->p_encoder->p_module );
2845 vlc_object_detach( id->p_encoder );
2846 vlc_object_destroy( id->p_encoder );
2848 if( fmt.psz_language ) free( fmt.psz_language );
2849 if( id ) free( id );
2850 p_sys->id_osd = NULL;
2851 p_sys->b_es_osd = VLC_FALSE;
2852 return VLC_EGENERIC;
2855 static void transcode_osd_close( sout_stream_t *p_stream, sout_stream_id_t *id)
2857 sout_stream_sys_t *p_sys = p_stream->p_sys;
2860 if( p_sys->b_es_osd && id )
2862 if( id->p_encoder->p_module )
2863 module_Unneed( id->p_encoder, id->p_encoder->p_module );
2865 if( id->id ) p_sys->p_out->pf_del( p_sys->p_out, id->id );
2869 vlc_object_detach( id->p_encoder );
2870 vlc_object_destroy( id->p_encoder );
2873 p_sys->b_es_osd = VLC_FALSE;
2874 if( id ) free( id );
2877 static int transcode_osd_process( sout_stream_t *p_stream,
2878 sout_stream_id_t *id,
2879 block_t *in, block_t **out )
2881 sout_stream_sys_t *p_sys = p_stream->p_sys;
2882 subpicture_t *p_subpic = NULL;
2884 /* Check if we have a subpicture to send */
2885 if( p_sys->p_spu && in->i_dts > 0)
2887 p_subpic = spu_SortSubpictures( p_sys->p_spu, in->i_dts );
2891 msg_Warn( p_stream, "spu channel not initialized, doing it now" );
2894 p_sys->p_spu = spu_Create( p_stream );
2895 if( spu_Init( p_sys->p_spu ) != VLC_SUCCESS )
2896 msg_Err( p_stream, "spu initialisation failed" );
2902 block_t *p_block = NULL;
2904 if( p_sys->b_master_sync && p_sys->i_master_drift )
2906 p_subpic->i_start -= p_sys->i_master_drift;
2907 if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2910 p_block = p_sys->id_osd->p_encoder->pf_encode_sub( p_sys->id_osd->p_encoder, p_subpic );
2913 p_block->i_dts = p_block->i_pts = in->i_dts;
2914 block_ChainAppend( out, p_block );
2917 if( p_sys->p_out->pf_send( p_sys->p_out, p_sys->id_osd->id, *out ) == VLC_SUCCESS )
2918 spu_DestroySubpicture( p_sys->p_spu, p_subpic );
2923 return VLC_EGENERIC;