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 *****************************************************************************/
30 #include <vlc_input.h>
34 #include <vlc_codec.h>
35 #include <vlc_block.h>
36 #include <vlc_filter.h>
41 #define MASTER_SYNC_MAX_DRIFT 100000
43 /* FIXME Ugly, needed for (disabled) stats updates */
45 #include "../../src/input/input_internal.h"
48 /*****************************************************************************
50 *****************************************************************************/
51 #define VENC_TEXT N_("Video encoder")
52 #define VENC_LONGTEXT N_( \
53 "This is the video encoder module that will be used (and its associated "\
55 #define VCODEC_TEXT N_("Destination video codec")
56 #define VCODEC_LONGTEXT N_( \
57 "This is the video codec that will be used.")
58 #define VB_TEXT N_("Video bitrate")
59 #define VB_LONGTEXT N_( \
60 "Target bitrate of the transcoded video stream." )
61 #define SCALE_TEXT N_("Video scaling")
62 #define SCALE_LONGTEXT N_( \
63 "Scale factor to apply to the video while transcoding (eg: 0.25)")
64 #define FPS_TEXT N_("Video frame-rate")
65 #define FPS_LONGTEXT N_( \
66 "Target output frame rate for the video stream." )
67 #define DEINTERLACE_TEXT N_("Deinterlace video")
68 #define DEINTERLACE_LONGTEXT N_( \
69 "Deinterlace the video before encoding." )
70 #define DEINTERLACE_MODULE_TEXT N_("Deinterlace module")
71 #define DEINTERLACE_MODULE_LONGTEXT N_( \
72 "Specify the deinterlace module to use." )
73 #define WIDTH_TEXT N_("Video width")
74 #define WIDTH_LONGTEXT N_( \
75 "Output video width." )
76 #define HEIGHT_TEXT N_("Video height")
77 #define HEIGHT_LONGTEXT N_( \
78 "Output video height." )
79 #define MAXWIDTH_TEXT N_("Maximum video width")
80 #define MAXWIDTH_LONGTEXT N_( \
81 "Maximum output video width." )
82 #define MAXHEIGHT_TEXT N_("Maximum video height")
83 #define MAXHEIGHT_LONGTEXT N_( \
84 "Maximum output video height." )
85 #define VFILTER_TEXT N_("Video filter")
86 #define VFILTER_LONGTEXT N_( \
87 "Video filters will be applied to the video streams (after overlays " \
88 "are applied). You must enter a comma-separated list of filters." )
90 #define CROPTOP_TEXT N_("Video crop (top)")
91 #define CROPTOP_LONGTEXT N_( \
92 "Number of pixels to crop at the top of the video." )
93 #define CROPLEFT_TEXT N_("Video crop (left)")
94 #define CROPLEFT_LONGTEXT N_( \
95 "Number of pixels to crop at the left of the video." )
96 #define CROPBOTTOM_TEXT N_("Video crop (bottom)")
97 #define CROPBOTTOM_LONGTEXT N_( \
98 "Number of pixels to crop at the bottom of the video." )
99 #define CROPRIGHT_TEXT N_("Video crop (right)")
100 #define CROPRIGHT_LONGTEXT N_( \
101 "Number of pixels to crop at the right of the video." )
103 #define PADDTOP_TEXT N_("Video padding (top)")
104 #define PADDTOP_LONGTEXT N_( \
105 "Size of the black border to add at the top of the video." )
106 #define PADDLEFT_TEXT N_("Video padding (left)")
107 #define PADDLEFT_LONGTEXT N_( \
108 "Size of the black border to add at the left of the video." )
109 #define PADDBOTTOM_TEXT N_("Video padding (bottom)")
110 #define PADDBOTTOM_LONGTEXT N_( \
111 "Size of the black border to add at the bottom of the video." )
112 #define PADDRIGHT_TEXT N_("Video padding (right)")
113 #define PADDRIGHT_LONGTEXT N_( \
114 "Size of the black border to add at the right of the video." )
116 #define CANVAS_WIDTH_TEXT N_("Video canvas width")
117 #define CANVAS_WIDTH_LONGTEXT N_( \
118 "This will automatically crod and pad the video to a specified width." )
119 #define CANVAS_HEIGHT_TEXT N_("Video canvas height")
120 #define CANVAS_HEIGHT_LONGTEXT N_( \
121 "This will automatically crod and pad the video to a specified height." )
122 #define CANVAS_ASPECT_TEXT N_("Video canvas aspect ratio")
123 #define CANVAS_ASPECT_LONGTEXT N_( \
124 "This sets aspect (like 4:3) of the video canvas and letterbox the video "\
127 #define AENC_TEXT N_("Audio encoder")
128 #define AENC_LONGTEXT N_( \
129 "This is the audio encoder module that will be used (and its associated "\
131 #define ACODEC_TEXT N_("Destination audio codec")
132 #define ACODEC_LONGTEXT N_( \
133 "This is the audio codec that will be used.")
134 #define AB_TEXT N_("Audio bitrate")
135 #define AB_LONGTEXT N_( \
136 "Target bitrate of the transcoded audio stream." )
137 #define ARATE_TEXT N_("Audio sample rate")
138 #define ARATE_LONGTEXT N_( \
139 "Sample rate of the transcoded audio stream (11250, 22500, 44100 or 48000).")
140 #define ACHANS_TEXT N_("Audio channels")
141 #define ACHANS_LONGTEXT N_( \
142 "Number of audio channels in the transcoded streams." )
143 #define AFILTER_TEXT N_("Audio filter")
144 #define AFILTER_LONGTEXT N_( \
145 "Audio filters will be applied to the audio streams (after conversion " \
146 "filters are applied). You must enter a comma-separated list of filters." )
148 #define SENC_TEXT N_("Subtitles encoder")
149 #define SENC_LONGTEXT N_( \
150 "This is the subtitles encoder module that will be used (and its " \
151 "associated options)." )
152 #define SCODEC_TEXT N_("Destination subtitles codec")
153 #define SCODEC_LONGTEXT N_( \
154 "This is the subtitles codec that will be used." )
156 #define SFILTER_TEXT N_("Overlays")
157 #define SFILTER_LONGTEXT N_( \
158 "This allows you to add overlays (also known as \"subpictures\" on the "\
159 "transcoded video stream. The subpictures produced by the filters will "\
160 "be overlayed directly onto the video. You must specify a comma-separated "\
161 "list of subpicture modules" )
163 #define OSD_TEXT N_("OSD menu")
164 #define OSD_LONGTEXT N_(\
165 "Stream the On Screen Display menu (using the osdmenu subpicture module)." )
167 #define THREADS_TEXT N_("Number of threads")
168 #define THREADS_LONGTEXT N_( \
169 "Number of threads used for the transcoding." )
170 #define HP_TEXT N_("High priority")
171 #define HP_LONGTEXT N_( \
172 "Runs the optional encoder thread at the OUTPUT priority instead of " \
175 #define ASYNC_TEXT N_("Synchronise on audio track")
176 #define ASYNC_LONGTEXT N_( \
177 "This option will drop/duplicate video frames to synchronise the video " \
178 "track on the audio track." )
180 #define HURRYUP_TEXT N_( "Hurry up" )
181 #define HURRYUP_LONGTEXT N_( "The transcoder will drop frames if your CPU " \
182 "can't keep up with the encoding rate." )
184 static const char *ppsz_deinterlace_type[] =
186 "deinterlace", "ffmpeg-deinterlace"
189 static int Open ( vlc_object_t * );
190 static void Close( vlc_object_t * );
192 #define SOUT_CFG_PREFIX "sout-transcode-"
195 set_shortname( _("Transcode"));
196 set_description( _("Transcode stream output") );
197 set_capability( "sout stream", 50 );
198 add_shortcut( "transcode" );
199 set_callbacks( Open, Close );
200 set_category( CAT_SOUT );
201 set_subcategory( SUBCAT_SOUT_STREAM );
202 set_section( N_("Video"), NULL );
203 add_string( SOUT_CFG_PREFIX "venc", NULL, NULL, VENC_TEXT,
204 VENC_LONGTEXT, VLC_FALSE );
205 add_string( SOUT_CFG_PREFIX "vcodec", NULL, NULL, VCODEC_TEXT,
206 VCODEC_LONGTEXT, VLC_FALSE );
207 add_integer( SOUT_CFG_PREFIX "vb", 800 * 1000, NULL, VB_TEXT,
208 VB_LONGTEXT, VLC_FALSE );
209 add_float( SOUT_CFG_PREFIX "scale", 1, NULL, SCALE_TEXT,
210 SCALE_LONGTEXT, VLC_FALSE );
211 add_float( SOUT_CFG_PREFIX "fps", 0, NULL, FPS_TEXT,
212 FPS_LONGTEXT, VLC_FALSE );
213 add_bool( SOUT_CFG_PREFIX "hurry-up", VLC_TRUE, NULL, HURRYUP_TEXT,
214 HURRYUP_LONGTEXT, VLC_FALSE );
215 add_bool( SOUT_CFG_PREFIX "deinterlace", 0, NULL, DEINTERLACE_TEXT,
216 DEINTERLACE_LONGTEXT, VLC_FALSE );
217 add_string( SOUT_CFG_PREFIX "deinterlace-module", "deinterlace", NULL,
218 DEINTERLACE_MODULE_TEXT, DEINTERLACE_MODULE_LONGTEXT,
220 change_string_list( ppsz_deinterlace_type, 0, 0 );
221 add_integer( SOUT_CFG_PREFIX "width", 0, NULL, WIDTH_TEXT,
222 WIDTH_LONGTEXT, VLC_TRUE );
223 add_integer( SOUT_CFG_PREFIX "height", 0, NULL, HEIGHT_TEXT,
224 HEIGHT_LONGTEXT, VLC_TRUE );
225 add_integer( SOUT_CFG_PREFIX "maxwidth", 0, NULL, MAXWIDTH_TEXT,
226 MAXWIDTH_LONGTEXT, VLC_TRUE );
227 add_integer( SOUT_CFG_PREFIX "maxheight", 0, NULL, MAXHEIGHT_TEXT,
228 MAXHEIGHT_LONGTEXT, VLC_TRUE );
229 add_module_list( SOUT_CFG_PREFIX "vfilter", "video filter2",
231 VFILTER_TEXT, VFILTER_LONGTEXT, VLC_FALSE );
233 add_integer( SOUT_CFG_PREFIX "croptop", 0, NULL, CROPTOP_TEXT,
234 CROPTOP_LONGTEXT, VLC_TRUE );
235 add_integer( SOUT_CFG_PREFIX "cropleft", 0, NULL, CROPLEFT_TEXT,
236 CROPLEFT_LONGTEXT, VLC_TRUE );
237 add_integer( SOUT_CFG_PREFIX "cropbottom", 0, NULL, CROPBOTTOM_TEXT,
238 CROPBOTTOM_LONGTEXT, VLC_TRUE );
239 add_integer( SOUT_CFG_PREFIX "cropright", 0, NULL, CROPRIGHT_TEXT,
240 CROPRIGHT_LONGTEXT, VLC_TRUE );
242 add_integer( SOUT_CFG_PREFIX "paddtop", 0, NULL, PADDTOP_TEXT,
243 PADDTOP_LONGTEXT, VLC_TRUE );
244 add_integer( SOUT_CFG_PREFIX "paddleft", 0, NULL, PADDLEFT_TEXT,
245 PADDLEFT_LONGTEXT, VLC_TRUE );
246 add_integer( SOUT_CFG_PREFIX "paddbottom", 0, NULL, PADDBOTTOM_TEXT,
247 PADDBOTTOM_LONGTEXT, VLC_TRUE );
248 add_integer( SOUT_CFG_PREFIX "paddright", 0, NULL, PADDRIGHT_TEXT,
249 PADDRIGHT_LONGTEXT, VLC_TRUE );
251 add_integer( SOUT_CFG_PREFIX "canvas-width", 0, NULL, CANVAS_WIDTH_TEXT,
252 CANVAS_WIDTH_LONGTEXT, VLC_TRUE );
253 add_integer( SOUT_CFG_PREFIX "canvas-height", 0, NULL, CANVAS_HEIGHT_TEXT,
254 CANVAS_HEIGHT_LONGTEXT, VLC_TRUE );
255 add_string( SOUT_CFG_PREFIX "canvas-aspect", NULL, NULL, CANVAS_ASPECT_TEXT,
256 CANVAS_ASPECT_LONGTEXT, VLC_FALSE );
258 set_section( N_("Audio"), NULL );
259 add_string( SOUT_CFG_PREFIX "aenc", NULL, NULL, AENC_TEXT,
260 AENC_LONGTEXT, VLC_FALSE );
261 add_string( SOUT_CFG_PREFIX "acodec", NULL, NULL, ACODEC_TEXT,
262 ACODEC_LONGTEXT, VLC_FALSE );
263 add_integer( SOUT_CFG_PREFIX "ab", 0, NULL, AB_TEXT,
264 AB_LONGTEXT, VLC_FALSE );
265 add_integer( SOUT_CFG_PREFIX "channels", 0, NULL, ACHANS_TEXT,
266 ACHANS_LONGTEXT, VLC_FALSE );
267 add_integer( SOUT_CFG_PREFIX "samplerate", 0, NULL, ARATE_TEXT,
268 ARATE_LONGTEXT, VLC_TRUE );
269 add_bool( SOUT_CFG_PREFIX "audio-sync", 0, NULL, ASYNC_TEXT,
270 ASYNC_LONGTEXT, VLC_FALSE );
271 add_module_list_cat( SOUT_CFG_PREFIX "afilter", SUBCAT_AUDIO_MISC,
273 AFILTER_TEXT, AFILTER_LONGTEXT, VLC_FALSE );
275 set_section( N_("Overlays/Subtitles"), NULL );
276 add_string( SOUT_CFG_PREFIX "senc", NULL, NULL, SENC_TEXT,
277 SENC_LONGTEXT, VLC_FALSE );
278 add_string( SOUT_CFG_PREFIX "scodec", NULL, NULL, SCODEC_TEXT,
279 SCODEC_LONGTEXT, VLC_FALSE );
280 add_bool( SOUT_CFG_PREFIX "soverlay", 0, NULL, SCODEC_TEXT,
281 SCODEC_LONGTEXT, VLC_FALSE );
282 add_module_list_cat( SOUT_CFG_PREFIX "sfilter", SUBCAT_VIDEO_SUBPIC,
284 SFILTER_TEXT, SFILTER_LONGTEXT, VLC_FALSE );
286 set_section( N_("On Screen Display"), NULL );
287 add_bool( SOUT_CFG_PREFIX "osd", 0, NULL, OSD_TEXT,
288 OSD_LONGTEXT, VLC_FALSE );
290 set_section( N_("Miscellaneous"), NULL );
291 add_integer( SOUT_CFG_PREFIX "threads", 0, NULL, THREADS_TEXT,
292 THREADS_LONGTEXT, VLC_TRUE );
293 add_bool( SOUT_CFG_PREFIX "high-priority", 0, NULL, HP_TEXT, HP_LONGTEXT,
298 static const char *ppsz_sout_options[] = {
299 "venc", "vcodec", "vb", "croptop", "cropbottom", "cropleft", "cropright",
300 "paddtop", "paddbottom", "paddleft", "paddright",
301 "canvas-width", "canvas-height", "canvas-aspect",
302 "scale", "fps", "width", "height", "vfilter", "deinterlace",
303 "deinterlace-module", "threads", "hurry-up", "aenc", "acodec", "ab",
304 "afilter", "samplerate", "channels", "senc", "scodec", "soverlay",
305 "sfilter", "osd", "audio-sync", "high-priority", "maxwidth", "maxheight",
309 /*****************************************************************************
310 * Exported prototypes
311 *****************************************************************************/
312 static sout_stream_id_t *Add ( sout_stream_t *, es_format_t * );
313 static int Del ( sout_stream_t *, sout_stream_id_t * );
314 static int Send( sout_stream_t *, sout_stream_id_t *, block_t* );
316 static int transcode_audio_new ( sout_stream_t *, sout_stream_id_t * );
317 static void transcode_audio_close ( sout_stream_t *, sout_stream_id_t * );
318 static int transcode_audio_process( sout_stream_t *, sout_stream_id_t *,
319 block_t *, block_t ** );
321 static aout_buffer_t *audio_new_buffer( decoder_t *, int );
322 static void audio_del_buffer( decoder_t *, aout_buffer_t * );
324 static int transcode_video_new ( sout_stream_t *, sout_stream_id_t * );
325 static void transcode_video_close ( sout_stream_t *, sout_stream_id_t * );
326 static int transcode_video_encoder_open( sout_stream_t *, sout_stream_id_t *);
327 static int transcode_video_process( sout_stream_t *, sout_stream_id_t *,
328 block_t *, block_t ** );
330 static void video_del_buffer( vlc_object_t *, picture_t * );
331 static picture_t *video_new_buffer_decoder( decoder_t * );
332 static void video_del_buffer_decoder( decoder_t *, picture_t * );
333 static void video_link_picture_decoder( decoder_t *, picture_t * );
334 static void video_unlink_picture_decoder( decoder_t *, picture_t * );
335 static picture_t *video_new_buffer_filter( filter_t * );
336 static void video_del_buffer_filter( filter_t *, picture_t * );
338 static int transcode_spu_new ( sout_stream_t *, sout_stream_id_t * );
339 static void transcode_spu_close ( sout_stream_t *, sout_stream_id_t * );
340 static int transcode_spu_process( sout_stream_t *, sout_stream_id_t *,
341 block_t *, block_t ** );
343 static int transcode_osd_new ( sout_stream_t *, sout_stream_id_t * );
344 static void transcode_osd_close ( sout_stream_t *, sout_stream_id_t * );
345 static int transcode_osd_process( sout_stream_t *, sout_stream_id_t *,
346 block_t *, block_t ** );
348 static int EncoderThread( struct sout_stream_sys_t * p_sys );
350 static int pi_channels_maps[6] =
353 AOUT_CHAN_CENTER, AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
354 AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
355 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
356 | AOUT_CHAN_REARRIGHT,
357 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
358 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
361 #define PICTURE_RING_SIZE 64
362 #define SUBPICTURE_RING_SIZE 20
363 #define TRANSCODE_FILTERS 10
365 struct sout_stream_sys_t
369 sout_stream_t *p_out;
370 sout_stream_id_t *id_video;
372 vlc_mutex_t lock_out;
374 picture_t * pp_pics[PICTURE_RING_SIZE];
375 int i_first_pic, i_last_pic;
378 vlc_fourcc_t i_acodec; /* codec audio (0 if not transcode) */
380 config_chain_t *p_audio_cfg;
384 char *psz_afilters[TRANSCODE_FILTERS];
385 config_chain_t *p_afilters_cfg[TRANSCODE_FILTERS];
389 vlc_fourcc_t i_vcodec; /* codec video (0 if not transcode) */
391 config_chain_t *p_video_cfg;
395 unsigned int i_width, i_maxwidth;
396 unsigned int i_height, i_maxheight;
397 vlc_bool_t b_deinterlace;
398 char *psz_deinterlace;
399 config_chain_t *p_deinterlace_cfg;
401 vlc_bool_t b_high_priority;
402 vlc_bool_t b_hurry_up;
403 char *psz_vfilters[TRANSCODE_FILTERS];
404 config_chain_t *p_vfilters_cfg[TRANSCODE_FILTERS];
421 /* Video, calculated */
433 vlc_fourcc_t i_scodec; /* codec spu (0 if not transcode) */
435 vlc_bool_t b_soverlay;
436 config_chain_t *p_spu_cfg;
440 vlc_fourcc_t i_osdcodec; /* codec osd menu (0 if not transcode) */
442 config_chain_t *p_osd_cfg;
443 vlc_bool_t b_osd; /* VLC_TRUE when osd es is registered */
446 vlc_bool_t b_master_sync;
447 mtime_t i_master_drift;
450 struct decoder_owner_sys_t
452 picture_t *pp_pics[PICTURE_RING_SIZE];
453 sout_stream_sys_t *p_sys;
455 struct filter_owner_sys_t
457 picture_t *pp_pics[PICTURE_RING_SIZE];
458 sout_stream_sys_t *p_sys;
461 /*****************************************************************************
463 *****************************************************************************/
464 static int Open( vlc_object_t *p_this )
466 sout_stream_t *p_stream = (sout_stream_t*)p_this;
467 sout_stream_sys_t *p_sys;
470 p_sys = vlc_object_create( p_this, sizeof( sout_stream_sys_t ) );
472 p_sys->p_out = sout_StreamNew( p_stream->p_sout, p_stream->psz_next );
475 msg_Err( p_stream, "cannot create chain" );
476 vlc_object_destroy( p_sys );
480 p_sys->i_master_drift = 0;
482 config_ChainParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
485 /* Audio transcoding parameters */
486 var_Get( p_stream, SOUT_CFG_PREFIX "aenc", &val );
487 p_sys->psz_aenc = NULL;
488 p_sys->p_audio_cfg = NULL;
489 if( val.psz_string && *val.psz_string )
492 psz_next = config_ChainCreate( &p_sys->psz_aenc, &p_sys->p_audio_cfg,
494 if( psz_next ) free( psz_next );
496 if( val.psz_string ) free( val.psz_string );
498 var_Get( p_stream, SOUT_CFG_PREFIX "acodec", &val );
500 if( val.psz_string && *val.psz_string )
503 memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
504 p_sys->i_acodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
506 if( val.psz_string ) free( val.psz_string );
508 var_Get( p_stream, SOUT_CFG_PREFIX "ab", &val );
509 p_sys->i_abitrate = val.i_int;
510 if( p_sys->i_abitrate < 4000 ) p_sys->i_abitrate *= 1000;
512 var_Get( p_stream, SOUT_CFG_PREFIX "samplerate", &val );
513 p_sys->i_sample_rate = val.i_int;
515 var_Get( p_stream, SOUT_CFG_PREFIX "channels", &val );
516 p_sys->i_channels = val.i_int;
518 if( p_sys->i_acodec )
520 if( p_sys->i_acodec == VLC_FOURCC('m','p','3',0) &&
521 p_sys->i_channels > 2 )
523 msg_Warn( p_stream, "%d channels invalid for mp3, forcing to 2",
525 p_sys->i_channels = 2;
527 msg_Dbg( p_stream, "codec audio=%4.4s %dHz %d channels %dKb/s",
528 (char *)&p_sys->i_acodec, p_sys->i_sample_rate,
529 p_sys->i_channels, p_sys->i_abitrate / 1000 );
532 var_Get( p_stream, SOUT_CFG_PREFIX "afilter", &val );
533 p_sys->i_afilters = 0;
534 if( val.psz_string && *val.psz_string )
536 char *psz_parser = val.psz_string;
538 while( (psz_parser != NULL) && (*psz_parser != '\0')
539 && (p_sys->i_afilters < TRANSCODE_FILTERS) )
541 psz_parser = config_ChainCreate(
542 &p_sys->psz_afilters[p_sys->i_afilters],
543 &p_sys->p_afilters_cfg[p_sys->i_afilters],
546 if( (psz_parser != NULL) && (*psz_parser != '\0') ) psz_parser++;
549 if( val.psz_string ) free( val.psz_string );
550 if( p_sys->i_afilters < TRANSCODE_FILTERS-1 )
552 p_sys->psz_afilters[p_sys->i_afilters] = NULL;
553 p_sys->p_afilters_cfg[p_sys->i_afilters] = NULL;
556 /* Video transcoding parameters */
557 var_Get( p_stream, SOUT_CFG_PREFIX "venc", &val );
558 p_sys->psz_venc = NULL;
559 p_sys->p_video_cfg = NULL;
560 if( val.psz_string && *val.psz_string )
563 psz_next = config_ChainCreate( &p_sys->psz_venc, &p_sys->p_video_cfg,
565 if( psz_next ) free( psz_next );
567 if( val.psz_string ) free( val.psz_string );
569 var_Get( p_stream, SOUT_CFG_PREFIX "vcodec", &val );
571 if( val.psz_string && *val.psz_string )
574 memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
575 p_sys->i_vcodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
577 if( val.psz_string ) free( val.psz_string );
579 var_Get( p_stream, SOUT_CFG_PREFIX "vb", &val );
580 p_sys->i_vbitrate = val.i_int;
581 if( p_sys->i_vbitrate < 16000 ) p_sys->i_vbitrate *= 1000;
583 var_Get( p_stream, SOUT_CFG_PREFIX "scale", &val );
584 p_sys->f_scale = val.f_float;
586 var_Get( p_stream, SOUT_CFG_PREFIX "fps", &val );
587 p_sys->f_fps = val.f_float;
589 var_Get( p_stream, SOUT_CFG_PREFIX "hurry-up", &val );
590 p_sys->b_hurry_up = val.b_bool;
592 var_Get( p_stream, SOUT_CFG_PREFIX "width", &val );
593 p_sys->i_width = val.i_int;
595 var_Get( p_stream, SOUT_CFG_PREFIX "height", &val );
596 p_sys->i_height = val.i_int;
598 var_Get( p_stream, SOUT_CFG_PREFIX "maxwidth", &val );
599 p_sys->i_maxwidth = val.i_int;
601 var_Get( p_stream, SOUT_CFG_PREFIX "maxheight", &val );
602 p_sys->i_maxheight = val.i_int;
604 var_Get( p_stream, SOUT_CFG_PREFIX "vfilter", &val );
605 p_sys->i_vfilters = 0;
606 if( val.psz_string && *val.psz_string )
608 char *psz_parser = val.psz_string;
610 while( (psz_parser != NULL) && (*psz_parser != '\0')
611 && (p_sys->i_vfilters < TRANSCODE_FILTERS) )
613 psz_parser = config_ChainCreate(
614 &p_sys->psz_vfilters[p_sys->i_vfilters],
615 &p_sys->p_vfilters_cfg[p_sys->i_vfilters],
618 if( psz_parser != NULL && *psz_parser != '\0' ) psz_parser++;
621 if( val.psz_string ) free( val.psz_string );
622 if( p_sys->i_vfilters < TRANSCODE_FILTERS-1 )
624 p_sys->psz_vfilters[p_sys->i_vfilters] = NULL;
625 p_sys->p_vfilters_cfg[p_sys->i_vfilters] = NULL;
628 var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace", &val );
629 p_sys->b_deinterlace = val.b_bool;
631 var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace-module", &val );
632 p_sys->psz_deinterlace = NULL;
633 p_sys->p_deinterlace_cfg = NULL;
634 if( val.psz_string && *val.psz_string )
637 psz_next = config_ChainCreate( &p_sys->psz_deinterlace,
638 &p_sys->p_deinterlace_cfg,
640 if( psz_next ) free( psz_next );
642 if( val.psz_string ) free( val.psz_string );
644 var_Get( p_stream, SOUT_CFG_PREFIX "croptop", &val );
645 p_sys->i_crop_top = val.i_int;
646 var_Get( p_stream, SOUT_CFG_PREFIX "cropbottom", &val );
647 p_sys->i_crop_bottom = val.i_int;
648 var_Get( p_stream, SOUT_CFG_PREFIX "cropleft", &val );
649 p_sys->i_crop_left = val.i_int;
650 var_Get( p_stream, SOUT_CFG_PREFIX "cropright", &val );
651 p_sys->i_crop_right = val.i_int;
653 var_Get( p_stream, SOUT_CFG_PREFIX "paddtop", &val );
654 p_sys->i_padd_top = val.i_int;
655 var_Get( p_stream, SOUT_CFG_PREFIX "paddbottom", &val );
656 p_sys->i_padd_bottom = val.i_int;
657 var_Get( p_stream, SOUT_CFG_PREFIX "paddleft", &val );
658 p_sys->i_padd_left = val.i_int;
659 var_Get( p_stream, SOUT_CFG_PREFIX "paddright", &val );
660 p_sys->i_padd_right = val.i_int;
662 var_Get( p_stream, SOUT_CFG_PREFIX "canvas-width", &val );
663 p_sys->i_canvas_width = val.i_int;
664 var_Get( p_stream, SOUT_CFG_PREFIX "canvas-height", &val );
665 p_sys->i_canvas_height = val.i_int;
667 var_Get( p_stream, SOUT_CFG_PREFIX "canvas-aspect", &val );
668 p_sys->i_canvas_aspect = 0;
669 if( val.psz_string && *val.psz_string )
671 char *psz_parser = strchr( val.psz_string, ':' );
674 *psz_parser++ = '\0';
675 p_sys->i_canvas_aspect = atoi( val.psz_string ) *
676 VOUT_ASPECT_FACTOR / atoi( psz_parser );
678 else msg_Warn( p_stream, "bad aspect ratio %s", val.psz_string );
681 if( val.psz_string ) free( val.psz_string );
683 var_Get( p_stream, SOUT_CFG_PREFIX "threads", &val );
684 p_sys->i_threads = val.i_int;
685 var_Get( p_stream, SOUT_CFG_PREFIX "high-priority", &val );
686 p_sys->b_high_priority = val.b_bool;
688 if( p_sys->i_vcodec )
690 msg_Dbg( p_stream, "codec video=%4.4s %dx%d scaling: %f %dkb/s",
691 (char *)&p_sys->i_vcodec, p_sys->i_width, p_sys->i_height,
692 p_sys->f_scale, p_sys->i_vbitrate / 1000 );
695 /* Subpictures transcoding parameters */
697 p_sys->psz_senc = NULL;
698 p_sys->p_spu_cfg = NULL;
701 var_Get( p_stream, SOUT_CFG_PREFIX "senc", &val );
702 if( val.psz_string && *val.psz_string )
705 psz_next = config_ChainCreate( &p_sys->psz_senc, &p_sys->p_spu_cfg,
707 if( psz_next ) free( psz_next );
709 if( val.psz_string ) free( val.psz_string );
711 var_Get( p_stream, SOUT_CFG_PREFIX "scodec", &val );
712 if( val.psz_string && *val.psz_string )
715 memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
716 p_sys->i_scodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
718 if( val.psz_string ) free( val.psz_string );
720 if( p_sys->i_scodec )
722 msg_Dbg( p_stream, "codec spu=%4.4s", (char *)&p_sys->i_scodec );
725 var_Get( p_stream, SOUT_CFG_PREFIX "soverlay", &val );
726 p_sys->b_soverlay = val.b_bool;
728 var_Get( p_stream, SOUT_CFG_PREFIX "sfilter", &val );
729 if( val.psz_string && *val.psz_string )
731 p_sys->p_spu = spu_Create( p_stream );
732 var_Create( p_sys->p_spu, "sub-filter", VLC_VAR_STRING );
733 var_Set( p_sys->p_spu, "sub-filter", val );
734 spu_Init( p_sys->p_spu );
736 if( val.psz_string ) free( val.psz_string );
738 /* OSD menu transcoding parameters */
739 p_sys->psz_osdenc = NULL;
740 p_sys->p_osd_cfg = NULL;
741 p_sys->i_osdcodec = 0;
742 p_sys->b_osd = VLC_FALSE;
744 var_Get( p_stream, SOUT_CFG_PREFIX "osd", &val );
750 psz_next = config_ChainCreate( &p_sys->psz_osdenc,
751 &p_sys->p_osd_cfg, strdup( "dvbsub") );
752 if( psz_next ) free( psz_next );
754 p_sys->i_osdcodec = VLC_FOURCC('Y','U','V','P' );
756 msg_Dbg( p_stream, "codec osd=%4.4s", (char *)&p_sys->i_osdcodec );
760 osd_val.psz_string = strdup("osdmenu");
761 p_sys->p_spu = spu_Create( p_stream );
762 var_Create( p_sys->p_spu, "sub-filter", VLC_VAR_STRING );
763 var_Set( p_sys->p_spu, "sub-filter", osd_val );
764 spu_Init( p_sys->p_spu );
765 if( osd_val.psz_string ) free( osd_val.psz_string );
769 osd_val.psz_string = strdup("osdmenu");
770 var_Set( p_sys->p_spu, "sub-filter", osd_val );
771 if( osd_val.psz_string ) free( osd_val.psz_string );
776 var_Get( p_stream, SOUT_CFG_PREFIX "audio-sync", &val );
777 p_sys->b_master_sync = val.b_bool;
778 if( p_sys->f_fps > 0 ) p_sys->b_master_sync = VLC_TRUE;
780 p_stream->pf_add = Add;
781 p_stream->pf_del = Del;
782 p_stream->pf_send = Send;
783 p_stream->p_sys = p_sys;
788 /*****************************************************************************
790 *****************************************************************************/
791 static void Close( vlc_object_t * p_this )
793 sout_stream_t *p_stream = (sout_stream_t*)p_this;
794 sout_stream_sys_t *p_sys = p_stream->p_sys;
796 sout_StreamDelete( p_sys->p_out );
798 while( p_sys->i_afilters )
801 if( p_sys->psz_afilters[p_sys->i_afilters] )
802 free( p_sys->psz_afilters[p_sys->i_afilters] );
803 if( p_sys->p_afilters_cfg[p_sys->i_afilters] )
804 free( p_sys->p_afilters_cfg[p_sys->i_afilters] );
807 while( p_sys->p_audio_cfg != NULL )
809 config_chain_t *p_next = p_sys->p_audio_cfg->p_next;
811 if( p_sys->p_audio_cfg->psz_name )
812 free( p_sys->p_audio_cfg->psz_name );
813 if( p_sys->p_audio_cfg->psz_value )
814 free( p_sys->p_audio_cfg->psz_value );
815 free( p_sys->p_audio_cfg );
817 p_sys->p_audio_cfg = p_next;
819 if( p_sys->psz_aenc ) free( p_sys->psz_aenc );
821 while( p_sys->i_vfilters )
824 if( p_sys->psz_vfilters[p_sys->i_vfilters] )
825 free( p_sys->psz_vfilters[p_sys->i_vfilters] );
826 if( p_sys->p_vfilters_cfg[p_sys->i_vfilters] )
827 free( p_sys->p_vfilters_cfg[p_sys->i_vfilters] );
830 while( p_sys->p_video_cfg != NULL )
832 config_chain_t *p_next = p_sys->p_video_cfg->p_next;
834 if( p_sys->p_video_cfg->psz_name )
835 free( p_sys->p_video_cfg->psz_name );
836 if( p_sys->p_video_cfg->psz_value )
837 free( p_sys->p_video_cfg->psz_value );
838 free( p_sys->p_video_cfg );
840 p_sys->p_video_cfg = p_next;
842 if( p_sys->psz_venc ) free( p_sys->psz_venc );
844 while( p_sys->p_deinterlace_cfg != NULL )
846 config_chain_t *p_next = p_sys->p_deinterlace_cfg->p_next;
848 if( p_sys->p_deinterlace_cfg->psz_name )
849 free( p_sys->p_deinterlace_cfg->psz_name );
850 if( p_sys->p_deinterlace_cfg->psz_value )
851 free( p_sys->p_deinterlace_cfg->psz_value );
852 free( p_sys->p_deinterlace_cfg );
854 p_sys->p_deinterlace_cfg = p_next;
856 if( p_sys->psz_deinterlace ) free( p_sys->psz_deinterlace );
858 while( p_sys->p_spu_cfg != NULL )
860 config_chain_t *p_next = p_sys->p_spu_cfg->p_next;
862 if( p_sys->p_spu_cfg->psz_name )
863 free( p_sys->p_spu_cfg->psz_name );
864 if( p_sys->p_spu_cfg->psz_value )
865 free( p_sys->p_spu_cfg->psz_value );
866 free( p_sys->p_spu_cfg );
868 p_sys->p_spu_cfg = p_next;
870 if( p_sys->psz_senc ) free( p_sys->psz_senc );
872 if( p_sys->p_spu ) spu_Destroy( p_sys->p_spu );
874 while( p_sys->p_osd_cfg != NULL )
876 config_chain_t *p_next = p_sys->p_osd_cfg->p_next;
878 if( p_sys->p_osd_cfg->psz_name )
879 free( p_sys->p_osd_cfg->psz_name );
880 if( p_sys->p_osd_cfg->psz_value )
881 free( p_sys->p_osd_cfg->psz_value );
882 free( p_sys->p_osd_cfg );
884 p_sys->p_osd_cfg = p_next;
886 if( p_sys->psz_osdenc ) free( p_sys->psz_osdenc );
888 vlc_object_destroy( p_sys );
891 struct sout_stream_id_t
893 vlc_fourcc_t b_transcode;
895 /* id of the out stream */
899 decoder_t *p_decoder;
902 filter_t *pp_filter[TRANSCODE_FILTERS];
904 /* User specified filters */
905 filter_t *pp_ufilter[TRANSCODE_FILTERS];
909 encoder_t *p_encoder;
912 date_t interpolated_pts;
915 static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
917 sout_stream_sys_t *p_sys = p_stream->p_sys;
918 sout_stream_id_t *id;
920 id = malloc( sizeof( sout_stream_id_t ) );
923 msg_Err( p_stream, "out of memory" );
926 memset( id, 0, sizeof(sout_stream_id_t) );
929 id->p_decoder = NULL;
930 id->p_encoder = NULL;
932 /* Create decoder object */
933 id->p_decoder = vlc_object_create( p_stream, VLC_OBJECT_DECODER );
936 msg_Err( p_stream, "out of memory" );
939 vlc_object_attach( id->p_decoder, p_stream );
940 id->p_decoder->p_module = NULL;
941 id->p_decoder->fmt_in = *p_fmt;
942 id->p_decoder->b_pace_control = VLC_TRUE;
944 /* Create encoder object */
945 id->p_encoder = vlc_object_create( p_stream, VLC_OBJECT_ENCODER );
948 msg_Err( p_stream, "out of memory" );
951 vlc_object_attach( id->p_encoder, p_stream );
952 id->p_encoder->p_module = NULL;
954 /* Create destination format */
955 es_format_Init( &id->p_encoder->fmt_out, p_fmt->i_cat, 0 );
956 id->p_encoder->fmt_out.i_id = p_fmt->i_id;
957 id->p_encoder->fmt_out.i_group = p_fmt->i_group;
958 if( p_fmt->psz_language )
959 id->p_encoder->fmt_out.psz_language = strdup( p_fmt->psz_language );
961 if( p_fmt->i_cat == AUDIO_ES && (p_sys->i_acodec || p_sys->psz_aenc) )
964 "creating audio transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
965 (char*)&p_fmt->i_codec, (char*)&p_sys->i_acodec );
967 /* Complete destination format */
968 id->p_encoder->fmt_out.i_codec = p_sys->i_acodec;
969 id->p_encoder->fmt_out.audio.i_rate = p_sys->i_sample_rate > 0 ?
970 p_sys->i_sample_rate : (int)p_fmt->audio.i_rate;
971 id->p_encoder->fmt_out.i_bitrate = p_sys->i_abitrate;
972 id->p_encoder->fmt_out.audio.i_bitspersample =
973 p_fmt->audio.i_bitspersample;
974 id->p_encoder->fmt_out.audio.i_channels = p_sys->i_channels > 0 ?
975 p_sys->i_channels : p_fmt->audio.i_channels;
976 /* Sanity check for audio channels */
977 id->p_encoder->fmt_out.audio.i_channels =
978 __MIN( id->p_encoder->fmt_out.audio.i_channels,
979 id->p_decoder->fmt_in.audio.i_channels );
980 id->p_encoder->fmt_out.audio.i_original_channels =
981 id->p_decoder->fmt_in.audio.i_physical_channels;
982 if( id->p_decoder->fmt_in.audio.i_channels ==
983 id->p_encoder->fmt_out.audio.i_channels )
985 id->p_encoder->fmt_out.audio.i_physical_channels =
986 id->p_decoder->fmt_in.audio.i_physical_channels;
990 id->p_encoder->fmt_out.audio.i_physical_channels =
991 pi_channels_maps[id->p_encoder->fmt_out.audio.i_channels];
994 /* Build decoder -> filter -> encoder chain */
995 if( transcode_audio_new( p_stream, id ) )
997 msg_Err( p_stream, "cannot create audio chain" );
1001 /* Open output stream */
1002 id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
1003 id->b_transcode = VLC_TRUE;
1007 transcode_audio_close( p_stream, id );
1011 date_Init( &id->interpolated_pts, p_fmt->audio.i_rate, 1 );
1013 else if( p_fmt->i_cat == VIDEO_ES &&
1014 (p_sys->i_vcodec != 0 || p_sys->psz_venc) )
1017 "creating video transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
1018 (char*)&p_fmt->i_codec, (char*)&p_sys->i_vcodec );
1020 /* Complete destination format */
1021 id->p_encoder->fmt_out.i_codec = p_sys->i_vcodec;
1022 id->p_encoder->fmt_out.video.i_width = p_sys->i_width & ~1;
1023 id->p_encoder->fmt_out.video.i_height = p_sys->i_height & ~1;
1024 id->p_encoder->fmt_out.i_bitrate = p_sys->i_vbitrate;
1026 /* Build decoder -> filter -> encoder chain */
1027 if( transcode_video_new( p_stream, id ) )
1029 msg_Err( p_stream, "cannot create video chain" );
1033 /* Stream will be added later on because we don't know
1034 * all the characteristics of the decoded stream yet */
1035 id->b_transcode = VLC_TRUE;
1037 if( p_sys->f_fps > 0 )
1039 id->p_encoder->fmt_out.video.i_frame_rate =
1040 (p_sys->f_fps * 1001) + 0.5;
1041 id->p_encoder->fmt_out.video.i_frame_rate_base = 1001;
1044 else if( ( p_fmt->i_cat == SPU_ES ) &&
1045 ( p_sys->i_scodec || p_sys->psz_senc ) )
1047 msg_Dbg( p_stream, "creating subtitles transcoding from fcc=`%4.4s' "
1048 "to fcc=`%4.4s'", (char*)&p_fmt->i_codec,
1049 (char*)&p_sys->i_scodec );
1051 /* Complete destination format */
1052 id->p_encoder->fmt_out.i_codec = p_sys->i_scodec;
1054 /* build decoder -> filter -> encoder */
1055 if( transcode_spu_new( p_stream, id ) )
1057 msg_Err( p_stream, "cannot create subtitles chain" );
1061 /* open output stream */
1062 id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
1063 id->b_transcode = VLC_TRUE;
1067 transcode_spu_close( p_stream, id );
1071 else if( p_fmt->i_cat == SPU_ES && p_sys->b_soverlay )
1073 msg_Dbg( p_stream, "subtitles (fcc=`%4.4s') overlaying",
1074 (char*)&p_fmt->i_codec );
1076 id->b_transcode = VLC_TRUE;
1078 /* Build decoder -> filter -> overlaying chain */
1079 if( transcode_spu_new( p_stream, id ) )
1081 msg_Err( p_stream, "cannot create subtitles chain" );
1085 else if( !p_sys->b_osd && (p_sys->i_osdcodec != 0 || p_sys->psz_osdenc) )
1087 msg_Dbg( p_stream, "creating osd transcoding from fcc=`%4.4s' "
1088 "to fcc=`%4.4s'", (char*)&p_fmt->i_codec,
1089 (char*)&p_sys->i_scodec );
1091 id->b_transcode = VLC_TRUE;
1093 /* Create a fake OSD menu elementary stream */
1094 if( transcode_osd_new( p_stream, id ) )
1096 msg_Err( p_stream, "cannot create osd chain" );
1099 p_sys->b_osd = VLC_TRUE;
1103 msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
1104 (char*)&p_fmt->i_codec );
1105 id->id = p_sys->p_out->pf_add( p_sys->p_out, p_fmt );
1106 id->b_transcode = VLC_FALSE;
1108 if( !id->id ) goto error;
1116 vlc_object_detach( id->p_decoder );
1117 vlc_object_destroy( id->p_decoder );
1118 id->p_decoder = NULL;
1123 vlc_object_detach( id->p_encoder );
1124 es_format_Clean( &id->p_encoder->fmt_out );
1125 vlc_object_destroy( id->p_encoder );
1126 id->p_encoder = NULL;
1133 static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
1135 sout_stream_sys_t *p_sys = p_stream->p_sys;
1137 if( id->b_transcode )
1139 switch( id->p_decoder->fmt_in.i_cat )
1142 transcode_audio_close( p_stream, id );
1145 transcode_video_close( p_stream, id );
1149 transcode_osd_close( p_stream, id );
1151 transcode_spu_close( p_stream, id );
1156 if( id->id ) p_sys->p_out->pf_del( p_sys->p_out, id->id );
1160 vlc_object_detach( id->p_decoder );
1161 vlc_object_destroy( id->p_decoder );
1162 id->p_decoder = NULL;
1167 vlc_object_detach( id->p_encoder );
1168 es_format_Clean( &id->p_encoder->fmt_out );
1169 vlc_object_destroy( id->p_encoder );
1170 id->p_encoder = NULL;
1177 static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
1180 sout_stream_sys_t *p_sys = p_stream->p_sys;
1181 block_t *p_out = NULL;
1183 if( !id->b_transcode && id->id )
1185 return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_buffer );
1187 else if( !id->b_transcode )
1189 block_Release( p_buffer );
1190 return VLC_EGENERIC;
1193 switch( id->p_decoder->fmt_in.i_cat )
1196 transcode_audio_process( p_stream, id, p_buffer, &p_out );
1200 if( transcode_video_process( p_stream, id, p_buffer, &p_out )
1203 return VLC_EGENERIC;
1208 /* Transcode OSD menu pictures. */
1211 if( transcode_osd_process( p_stream, id, p_buffer, &p_out ) !=
1214 return VLC_EGENERIC;
1217 else if ( transcode_spu_process( p_stream, id, p_buffer, &p_out ) !=
1220 return VLC_EGENERIC;
1226 block_Release( p_buffer );
1230 if( p_out ) return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_out );
1234 /****************************************************************************
1235 * decoder reencoder part
1236 ****************************************************************************/
1237 static int audio_BitsPerSample( vlc_fourcc_t i_format )
1241 case VLC_FOURCC('u','8',' ',' '):
1242 case VLC_FOURCC('s','8',' ',' '):
1245 case VLC_FOURCC('u','1','6','l'):
1246 case VLC_FOURCC('s','1','6','l'):
1247 case VLC_FOURCC('u','1','6','b'):
1248 case VLC_FOURCC('s','1','6','b'):
1251 case VLC_FOURCC('u','2','4','l'):
1252 case VLC_FOURCC('s','2','4','l'):
1253 case VLC_FOURCC('u','2','4','b'):
1254 case VLC_FOURCC('s','2','4','b'):
1257 case VLC_FOURCC('u','3','2','l'):
1258 case VLC_FOURCC('s','3','2','l'):
1259 case VLC_FOURCC('u','3','2','b'):
1260 case VLC_FOURCC('s','3','2','b'):
1261 case VLC_FOURCC('f','l','3','2'):
1262 case VLC_FOURCC('f','i','3','2'):
1265 case VLC_FOURCC('f','l','6','4'):
1272 static filter_t *transcode_audio_filter_new( sout_stream_t *p_stream,
1273 sout_stream_id_t *id,
1274 es_format_t *p_fmt_in,
1275 es_format_t *p_fmt_out,
1278 sout_stream_sys_t *p_sys = p_stream->p_sys;
1279 filter_t *p_filter = vlc_object_create( p_stream, VLC_OBJECT_FILTER );
1281 vlc_object_attach( p_filter, p_stream );
1282 p_filter->pf_audio_buffer_new = (block_t* (*) (filter_t*, int))__block_New;
1284 p_filter->fmt_in = *p_fmt_in;
1285 p_filter->fmt_out = *p_fmt_out;
1287 p_filter->p_cfg = p_sys->p_afilters_cfg[id->i_ufilter];
1289 p_filter->p_module = module_Need( p_filter, "audio filter2", psz_name,
1291 if( p_filter->p_module )
1293 p_filter->fmt_out.audio.i_bitspersample =
1294 audio_BitsPerSample( p_filter->fmt_out.i_codec );
1295 *p_fmt_in = p_filter->fmt_out;
1299 vlc_object_detach( p_filter );
1300 vlc_object_destroy( p_filter );
1307 static int transcode_audio_new( sout_stream_t *p_stream,
1308 sout_stream_id_t *id )
1310 sout_stream_sys_t *p_sys = p_stream->p_sys;
1311 es_format_t fmt_last;
1318 /* Initialization of decoder structures */
1319 id->p_decoder->fmt_out = id->p_decoder->fmt_in;
1320 id->p_decoder->fmt_out.i_extra = 0;
1321 id->p_decoder->fmt_out.p_extra = 0;
1322 id->p_decoder->pf_decode_audio = 0;
1323 id->p_decoder->pf_aout_buffer_new = audio_new_buffer;
1324 id->p_decoder->pf_aout_buffer_del = audio_del_buffer;
1325 /* id->p_decoder->p_cfg = p_sys->p_audio_cfg; */
1327 id->p_decoder->p_module =
1328 module_Need( id->p_decoder, "decoder", "$codec", 0 );
1329 if( !id->p_decoder->p_module )
1331 msg_Err( p_stream, "cannot find decoder" );
1332 return VLC_EGENERIC;
1334 id->p_decoder->fmt_out.audio.i_bitspersample =
1335 audio_BitsPerSample( id->p_decoder->fmt_out.i_codec );
1336 fmt_last = id->p_decoder->fmt_out;
1337 /* Fix AAC SBR changing number of channels and sampling rate */
1338 if( !(id->p_decoder->fmt_in.i_codec == VLC_FOURCC('m','p','4','a') &&
1339 fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate &&
1340 fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels) )
1341 fmt_last.audio.i_rate = id->p_decoder->fmt_in.audio.i_rate;
1347 /* Initialization of encoder format structures */
1348 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1349 id->p_decoder->fmt_out.i_codec );
1350 id->p_encoder->fmt_in.audio.i_format = id->p_decoder->fmt_out.i_codec;
1352 /* Initialization of encoder format structures */
1353 es_format_Init( &id->p_encoder->fmt_in, AUDIO_ES, VLC_FOURCC('f','l','3','2') );
1354 id->p_encoder->fmt_in.audio.i_format = VLC_FOURCC('f','l','3','2');
1356 id->p_encoder->fmt_in.audio.i_rate = id->p_encoder->fmt_out.audio.i_rate;
1357 id->p_encoder->fmt_in.audio.i_physical_channels =
1358 id->p_encoder->fmt_out.audio.i_physical_channels;
1359 id->p_encoder->fmt_in.audio.i_original_channels =
1360 id->p_encoder->fmt_out.audio.i_original_channels;
1361 id->p_encoder->fmt_in.audio.i_channels =
1362 id->p_encoder->fmt_out.audio.i_channels;
1363 id->p_encoder->fmt_in.audio.i_bitspersample =
1364 audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1366 id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
1367 id->p_encoder->p_module =
1368 module_Need( id->p_encoder, "encoder", p_sys->psz_aenc, VLC_TRUE );
1369 if( !id->p_encoder->p_module )
1371 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_aenc );
1372 module_Unneed( id->p_decoder, id->p_decoder->p_module );
1373 id->p_decoder->p_module = NULL;
1374 return VLC_EGENERIC;
1376 id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
1377 id->p_encoder->fmt_in.audio.i_bitspersample =
1378 audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1380 /* Fix AAC SBR changing number of channels and sampling rate */
1381 if( id->p_decoder->fmt_in.i_codec == VLC_FOURCC('m','p','4','a') &&
1382 fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate &&
1383 fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels )
1385 id->p_encoder->fmt_in.audio.i_rate = fmt_last.audio.i_rate;
1386 id->p_encoder->fmt_out.audio.i_rate = fmt_last.audio.i_rate;
1389 /* Load conversion filters */
1390 if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels ||
1391 fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate )
1393 /* We'll have to go through fl32 first */
1394 es_format_t fmt_out = id->p_encoder->fmt_in;
1395 fmt_out.i_codec = fmt_out.audio.i_format = VLC_FOURCC('f','l','3','2');
1397 id->pp_filter[id->i_filter] =
1398 transcode_audio_filter_new( p_stream, id, &fmt_last, &fmt_out, NULL );
1400 if( id->pp_filter[id->i_filter] ) id->i_filter++;
1403 for( i = 0; i < TRANSCODE_FILTERS; i++ )
1405 if( (fmt_last.audio.i_channels !=
1406 id->p_encoder->fmt_in.audio.i_channels) ||
1407 (fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate) ||
1408 (fmt_last.i_codec != id->p_encoder->fmt_in.i_codec) )
1410 id->pp_filter[id->i_filter] =
1411 transcode_audio_filter_new( p_stream, id, &fmt_last,
1412 &id->p_encoder->fmt_in, NULL );
1414 if( id->pp_filter[id->i_filter] )
1421 /* Final checks to see if conversions were successful */
1422 if( fmt_last.i_codec != id->p_encoder->fmt_in.i_codec )
1424 msg_Err( p_stream, "no audio filter found (%4.4s->%4.4s)",
1425 (char *)&fmt_last.i_codec,
1426 (char *)&id->p_encoder->fmt_in.i_codec );
1427 transcode_audio_close( p_stream, id );
1428 return VLC_EGENERIC;
1431 /* Load user specified audio filters now */
1432 for( i = 0; (i < p_sys->i_afilters) &&
1433 (id->i_ufilter < TRANSCODE_FILTERS); i++ )
1435 id->pp_ufilter[id->i_ufilter] =
1436 transcode_audio_filter_new( p_stream, id, &fmt_last,
1437 &id->p_encoder->fmt_in,
1438 p_sys->psz_afilters[i] );
1440 if( id->pp_ufilter[id->i_ufilter] )
1446 if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels )
1449 module_Unneed( id->p_encoder, id->p_encoder->p_module );
1450 id->p_encoder->p_module = NULL;
1452 /* This might work, but only if the encoder is restarted */
1453 id->p_encoder->fmt_in.audio.i_channels = fmt_last.audio.i_channels;
1454 id->p_encoder->fmt_out.audio.i_channels = fmt_last.audio.i_channels;
1456 id->p_encoder->fmt_in.audio.i_physical_channels =
1457 id->p_encoder->fmt_in.audio.i_original_channels =
1458 fmt_last.audio.i_physical_channels;
1459 id->p_encoder->fmt_out.audio.i_physical_channels =
1460 id->p_encoder->fmt_out.audio.i_original_channels =
1461 fmt_last.audio.i_physical_channels;
1463 msg_Dbg( p_stream, "number of audio channels for mixing changed, "
1464 "trying to reopen the encoder for mixing %i to %i channels",
1465 fmt_last.audio.i_channels,
1466 id->p_encoder->fmt_in.audio.i_channels );
1468 /* reload encoder */
1469 id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
1470 id->p_encoder->p_module =
1471 module_Need( id->p_encoder, "encoder", p_sys->psz_aenc, VLC_TRUE );
1472 if( !id->p_encoder->p_module )
1474 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_aenc );
1475 transcode_audio_close( p_stream, id );
1476 return VLC_EGENERIC;
1478 id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
1479 id->p_encoder->fmt_in.audio.i_bitspersample =
1480 audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1482 msg_Err( p_stream, "no audio filter found for mixing from"
1483 " %i to %i channels", fmt_last.audio.i_channels,
1484 id->p_encoder->fmt_in.audio.i_channels );
1486 transcode_audio_close( p_stream, id );
1487 return VLC_EGENERIC;
1491 if( fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate )
1493 msg_Err( p_stream, "no audio filter found for resampling from"
1494 " %iHz to %iHz", fmt_last.audio.i_rate,
1495 id->p_encoder->fmt_in.audio.i_rate );
1497 /* FIXME : this might work, but only if the encoder is restarted */
1498 id->p_encoder->fmt_in.audio.i_rate = fmt_last.audio.i_rate;
1499 id->p_encoder->fmt_out.audio.i_rate = fmt_last.audio.i_rate;
1501 transcode_audio_close( p_stream, id );
1502 return VLC_EGENERIC;
1506 /* FIXME: Hack for mp3 transcoding support */
1507 if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC( 'm','p','3',' ' ) )
1508 id->p_encoder->fmt_out.i_codec = VLC_FOURCC( 'm','p','g','a' );
1513 static void transcode_audio_close( sout_stream_t *p_stream,
1514 sout_stream_id_t *id )
1519 if( id->p_decoder->p_module )
1520 module_Unneed( id->p_decoder, id->p_decoder->p_module );
1521 id->p_decoder->p_module = NULL;
1524 if( id->p_encoder->p_module )
1525 module_Unneed( id->p_encoder, id->p_encoder->p_module );
1526 id->p_encoder->p_module = NULL;
1529 for( i = 0; i < id->i_filter; i++ )
1531 vlc_object_detach( id->pp_filter[i] );
1532 if( id->pp_filter[i]->p_module )
1533 module_Unneed( id->pp_filter[i], id->pp_filter[i]->p_module );
1534 vlc_object_destroy( id->pp_filter[i] );
1536 for( i = 0; i < id->i_ufilter; i++ )
1538 vlc_object_detach( id->pp_ufilter[i] );
1539 if( id->pp_ufilter[i]->p_module )
1540 module_Unneed( id->pp_ufilter[i], id->pp_ufilter[i]->p_module );
1541 vlc_object_destroy( id->pp_ufilter[i] );
1545 static int transcode_audio_process( sout_stream_t *p_stream,
1546 sout_stream_id_t *id,
1547 block_t *in, block_t **out )
1549 sout_stream_sys_t *p_sys = p_stream->p_sys;
1550 aout_buffer_t *p_audio_buf;
1551 block_t *p_block, *p_audio_block;
1554 input_thread_t *p_input = NULL;
1556 if( p_stream->p_parent->p_parent && p_stream->p_parent->p_parent->
1557 i_object_type == VLC_OBJECT_INPUT )
1558 p_input = (input_thread_t *)p_stream->p_parent->p_parent;
1560 while( (p_audio_buf = id->p_decoder->pf_decode_audio( id->p_decoder,
1563 #warning Stats not implemented!
1566 stats_UpdateInteger( p_input, p_input->p->counters.p_decoded_audio,
1569 if( p_sys->b_master_sync )
1571 mtime_t i_dts = date_Get( &id->interpolated_pts ) + 1;
1572 if ( p_audio_buf->start_date - i_dts > MASTER_SYNC_MAX_DRIFT
1573 || p_audio_buf->start_date - i_dts < -MASTER_SYNC_MAX_DRIFT )
1575 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
1576 date_Set( &id->interpolated_pts, p_audio_buf->start_date );
1577 i_dts = p_audio_buf->start_date + 1;
1579 p_sys->i_master_drift = p_audio_buf->start_date - i_dts;
1580 date_Increment( &id->interpolated_pts, p_audio_buf->i_nb_samples );
1581 p_audio_buf->start_date -= p_sys->i_master_drift;
1582 p_audio_buf->end_date -= p_sys->i_master_drift;
1585 p_audio_block = p_audio_buf->p_sys;
1586 p_audio_block->i_buffer = p_audio_buf->i_nb_bytes;
1587 p_audio_block->i_dts = p_audio_block->i_pts =
1588 p_audio_buf->start_date;
1589 p_audio_block->i_length = p_audio_buf->end_date -
1590 p_audio_buf->start_date;
1591 p_audio_block->i_samples = p_audio_buf->i_nb_samples;
1593 /* Run filter chain */
1594 for( i = 0; i < id->i_filter; i++ )
1597 id->pp_filter[i]->pf_audio_filter( id->pp_filter[i],
1601 /* Run user specified filter chain */
1602 for( i = 0; i < id->i_ufilter; i++ )
1605 id->pp_ufilter[i]->pf_audio_filter( id->pp_ufilter[i],
1609 p_audio_buf->p_buffer = p_audio_block->p_buffer;
1610 p_audio_buf->i_nb_bytes = p_audio_block->i_buffer;
1611 p_audio_buf->i_nb_samples = p_audio_block->i_samples;
1612 p_audio_buf->start_date = p_audio_block->i_dts;
1613 p_audio_buf->end_date = p_audio_block->i_dts + p_audio_block->i_length;
1615 p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf );
1616 block_ChainAppend( out, p_block );
1617 block_Release( p_audio_block );
1618 free( p_audio_buf );
1624 static void audio_release_buffer( aout_buffer_t *p_buffer )
1626 if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
1627 if( p_buffer ) free( p_buffer );
1630 static aout_buffer_t *audio_new_buffer( decoder_t *p_dec, int i_samples )
1632 aout_buffer_t *p_buffer;
1636 if( p_dec->fmt_out.audio.i_bitspersample )
1638 i_size = i_samples * p_dec->fmt_out.audio.i_bitspersample / 8 *
1639 p_dec->fmt_out.audio.i_channels;
1641 else if( p_dec->fmt_out.audio.i_bytes_per_frame &&
1642 p_dec->fmt_out.audio.i_frame_length )
1644 i_size = i_samples * p_dec->fmt_out.audio.i_bytes_per_frame /
1645 p_dec->fmt_out.audio.i_frame_length;
1649 i_size = i_samples * 4 * p_dec->fmt_out.audio.i_channels;
1652 p_buffer = malloc( sizeof(aout_buffer_t) );
1653 if( !p_buffer ) return NULL;
1654 p_buffer->b_discontinuity = VLC_FALSE;
1655 p_buffer->pf_release = audio_release_buffer;
1656 p_buffer->p_sys = p_block = block_New( p_dec, i_size );
1658 p_buffer->p_buffer = p_block->p_buffer;
1659 p_buffer->i_size = p_buffer->i_nb_bytes = p_block->i_buffer;
1660 p_buffer->i_nb_samples = i_samples;
1661 p_block->i_samples = i_samples;
1666 static void audio_del_buffer( decoder_t *p_dec, aout_buffer_t *p_buffer )
1668 if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
1669 if( p_buffer ) free( p_buffer );
1675 static int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_t *id )
1677 sout_stream_sys_t *p_sys = p_stream->p_sys;
1681 * Initialization of decoder structures
1683 id->p_decoder->fmt_out = id->p_decoder->fmt_in;
1684 id->p_decoder->fmt_out.i_extra = 0;
1685 id->p_decoder->fmt_out.p_extra = 0;
1686 id->p_decoder->pf_decode_video = 0;
1687 id->p_decoder->pf_get_cc = 0;
1688 id->p_decoder->pf_vout_buffer_new = video_new_buffer_decoder;
1689 id->p_decoder->pf_vout_buffer_del = video_del_buffer_decoder;
1690 id->p_decoder->pf_picture_link = video_link_picture_decoder;
1691 id->p_decoder->pf_picture_unlink = video_unlink_picture_decoder;
1692 id->p_decoder->p_owner = malloc( sizeof(decoder_owner_sys_t) );
1693 for( i = 0; i < PICTURE_RING_SIZE; i++ )
1694 id->p_decoder->p_owner->pp_pics[i] = 0;
1695 id->p_decoder->p_owner->p_sys = p_sys;
1696 /* id->p_decoder->p_cfg = p_sys->p_video_cfg; */
1698 id->p_decoder->p_module =
1699 module_Need( id->p_decoder, "decoder", "$codec", 0 );
1701 if( !id->p_decoder->p_module )
1703 msg_Err( p_stream, "cannot find decoder" );
1704 return VLC_EGENERIC;
1709 * Because some info about the decoded input will only be available
1710 * once the first frame is decoded, we actually only test the availability
1711 * of the encoder here.
1714 /* Initialization of encoder format structures */
1715 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1716 id->p_decoder->fmt_out.i_codec );
1717 id->p_encoder->fmt_in.video.i_chroma = id->p_decoder->fmt_out.i_codec;
1719 /* The dimensions will be set properly later on.
1720 * Just put sensible values so we can test an encoder is available. */
1721 id->p_encoder->fmt_in.video.i_width =
1722 id->p_encoder->fmt_out.video.i_width ?
1723 id->p_encoder->fmt_out.video.i_width :
1724 id->p_decoder->fmt_in.video.i_width ?
1725 id->p_decoder->fmt_in.video.i_width : 16;
1726 id->p_encoder->fmt_in.video.i_height =
1727 id->p_encoder->fmt_out.video.i_height ?
1728 id->p_encoder->fmt_out.video.i_height :
1729 id->p_decoder->fmt_in.video.i_height ?
1730 id->p_decoder->fmt_in.video.i_height : 16;
1731 id->p_encoder->fmt_in.video.i_frame_rate = 25;
1732 id->p_encoder->fmt_in.video.i_frame_rate_base = 1;
1734 id->p_encoder->i_threads = p_sys->i_threads;
1735 id->p_encoder->p_cfg = p_sys->p_video_cfg;
1737 id->p_encoder->p_module =
1738 module_Need( id->p_encoder, "encoder", p_sys->psz_venc, VLC_TRUE );
1739 if( !id->p_encoder->p_module )
1741 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_venc );
1742 module_Unneed( id->p_decoder, id->p_decoder->p_module );
1743 id->p_decoder->p_module = 0;
1744 return VLC_EGENERIC;
1747 /* Close the encoder.
1748 * We'll open it only when we have the first frame. */
1749 module_Unneed( id->p_encoder, id->p_encoder->p_module );
1750 if( id->p_encoder->fmt_out.p_extra )
1752 free( id->p_encoder->fmt_out.p_extra );
1753 id->p_encoder->fmt_out.p_extra = NULL;
1754 id->p_encoder->fmt_out.i_extra = 0;
1756 id->p_encoder->p_module = NULL;
1758 if( p_sys->i_threads >= 1 )
1760 int i_priority = p_sys->b_high_priority ? VLC_THREAD_PRIORITY_OUTPUT :
1761 VLC_THREAD_PRIORITY_VIDEO;
1762 p_sys->id_video = id;
1763 vlc_mutex_init( p_stream, &p_sys->lock_out );
1764 vlc_cond_init( p_stream, &p_sys->cond );
1765 memset( p_sys->pp_pics, 0, sizeof(p_sys->pp_pics) );
1766 p_sys->i_first_pic = 0;
1767 p_sys->i_last_pic = 0;
1768 p_sys->p_buffers = NULL;
1769 p_sys->b_die = p_sys->b_error = 0;
1770 if( vlc_thread_create( p_sys, "encoder", EncoderThread, i_priority,
1773 msg_Err( p_stream, "cannot spawn encoder thread" );
1774 module_Unneed( id->p_decoder, id->p_decoder->p_module );
1775 id->p_decoder->p_module = 0;
1776 return VLC_EGENERIC;
1783 static int transcode_video_encoder_open( sout_stream_t *p_stream,
1784 sout_stream_id_t *id )
1786 sout_stream_sys_t *p_sys = p_stream->p_sys;
1788 /* Calculate scaling, padding, cropping etc. */
1789 /* width/height of source */
1790 int i_src_width = id->p_decoder->fmt_out.video.i_width;
1791 int i_src_height = id->p_decoder->fmt_out.video.i_height;
1793 /* with/height scaling */
1794 float f_scale_width = 1;
1795 float f_scale_height = 1;
1797 /* width/height of output stream */
1802 float f_aspect = (float)id->p_decoder->fmt_out.video.i_aspect /
1805 msg_Dbg( p_stream, "decoder aspect is %i:%i",
1806 id->p_decoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
1808 /* Change f_aspect from source frame to source pixel */
1809 f_aspect = f_aspect * i_src_height / i_src_width;
1810 msg_Dbg( p_stream, "source pixel aspect is %f:1", f_aspect );
1812 /* width/height after cropping */
1813 p_sys->i_src_x_offset = p_sys->i_crop_left & ~1;
1814 p_sys->i_src_y_offset = p_sys->i_crop_top & ~1;
1815 p_sys->i_crop_width = i_src_width - ( p_sys->i_crop_left & ~1 ) -
1816 ( p_sys->i_crop_right & ~1 );
1817 p_sys->i_crop_height = i_src_height - ( p_sys->i_crop_top & ~1 ) -
1818 ( p_sys->i_crop_bottom & ~1 );
1820 /* Calculate scaling factor for specified parameters */
1821 if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1822 id->p_encoder->fmt_out.video.i_height <= 0 && p_sys->f_scale )
1824 /* Global scaling. Make sure width will remain a factor of 16 */
1827 int i_new_width = i_src_width * p_sys->f_scale;
1829 if( i_new_width % 16 <= 7 && i_new_width >= 16 )
1830 i_new_width -= i_new_width % 16;
1832 i_new_width += 16 - i_new_width % 16;
1834 f_real_scale = (float)( i_new_width ) / (float) i_src_width;
1836 i_new_height = __MAX( 16, i_src_height * (float)f_real_scale );
1838 f_scale_width = f_real_scale;
1839 f_scale_height = (float) i_new_height / (float) i_src_height;
1841 else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1842 id->p_encoder->fmt_out.video.i_height <= 0 )
1844 /* Only width specified */
1845 f_scale_width = (float)id->p_encoder->fmt_out.video.i_width /
1846 p_sys->i_crop_width;
1847 f_scale_height = f_scale_width;
1849 else if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1850 id->p_encoder->fmt_out.video.i_height > 0 )
1852 /* Only height specified */
1853 f_scale_height = (float)id->p_encoder->fmt_out.video.i_height /
1854 p_sys->i_crop_height;
1855 f_scale_width = f_scale_height;
1857 else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1858 id->p_encoder->fmt_out.video.i_height > 0 )
1860 /* Width and height specified */
1861 f_scale_width = (float)id->p_encoder->fmt_out.video.i_width
1862 / p_sys->i_crop_width;
1863 f_scale_height = (float)id->p_encoder->fmt_out.video.i_height
1864 / p_sys->i_crop_height;
1867 /* check maxwidth and maxheight
1868 * note: maxwidth and maxheight currently does not handle
1869 * canvas and padding, just scaling and cropping.
1871 if( p_sys->i_maxwidth && f_scale_width > (float)p_sys->i_maxwidth /
1872 p_sys->i_crop_width )
1874 f_scale_width = (float)p_sys->i_maxwidth / p_sys->i_crop_width;
1876 if( p_sys->i_maxheight && f_scale_height > (float)p_sys->i_maxheight /
1877 p_sys->i_crop_height )
1879 f_scale_height = (float)p_sys->i_maxheight / p_sys->i_crop_height;
1882 /* Change aspect ratio from source pixel to scaled pixel */
1883 f_aspect = f_aspect * f_scale_height / f_scale_width;
1884 msg_Dbg( p_stream, "scaled pixel aspect is %f:1", f_aspect );
1886 /* Correct scaling for target aspect ratio
1887 * Shrink video if necessary
1889 if ( p_sys->i_canvas_aspect > 0 )
1891 float f_target_aspect = (float)p_sys->i_canvas_aspect /
1894 if( p_sys->i_canvas_width > 0 && p_sys->i_canvas_height > 0)
1896 /* Calculate pixel aspect of canvas */
1897 f_target_aspect = f_target_aspect / p_sys->i_canvas_width *
1898 p_sys->i_canvas_height;
1900 if( f_target_aspect > f_aspect )
1902 /* Reduce width scale to increase aspect */
1903 f_scale_width = f_scale_width * f_aspect / f_target_aspect;
1907 /* Reduce height scale to decrease aspect */
1908 f_scale_height = f_scale_height * f_target_aspect / f_aspect;
1910 f_aspect = f_target_aspect;
1911 msg_Dbg( p_stream, "canvas scaled pixel aspect is %f:1", f_aspect );
1914 /* f_scale_width and f_scale_height are now final */
1915 /* Calculate width, height from scaling
1916 * Make sure its multiple of 2
1918 i_dst_width = 2 * (int)( p_sys->i_crop_width * f_scale_width / 2 + 0.5 );
1920 (int)( p_sys->i_crop_height * f_scale_height / 2 + 0.5 );
1922 p_sys->i_nopadd_width = i_dst_width;
1923 p_sys->i_nopadd_height = i_dst_height;
1924 p_sys->i_dst_x_offset = 0;
1925 p_sys->i_dst_y_offset = 0;
1927 /* Handle canvas and padding */
1928 if( p_sys->i_canvas_width <= 0 )
1930 /* No canvas width set, add explicit padding border */
1931 i_dst_width = p_sys->i_nopadd_width + ( p_sys->i_padd_left & ~1 ) +
1932 ( p_sys->i_padd_right & ~1 );
1933 p_sys->i_dst_x_offset = ( p_sys->i_padd_left & ~1 );
1937 /* Canvas set, check if we have to padd or crop */
1938 if( p_sys->i_canvas_width < p_sys->i_nopadd_width )
1940 /* need to crop more, but keep same scaling */
1941 int i_crop = 2 * (int)( ( p_sys->i_canvas_width & ~1 ) /
1942 f_scale_width / 2 + 0.5 );
1944 p_sys->i_src_x_offset += ( ( p_sys->i_crop_width - i_crop ) / 2 )
1946 p_sys->i_crop_width = i_crop;
1947 i_dst_width = p_sys->i_canvas_width & ~1;
1948 p_sys->i_nopadd_width = i_dst_width;
1950 else if( p_sys->i_canvas_width > p_sys->i_nopadd_width )
1953 i_dst_width = p_sys->i_canvas_width & ~1;
1954 p_sys->i_dst_x_offset = ( i_dst_width - p_sys->i_nopadd_width )/2;
1955 p_sys->i_dst_x_offset = p_sys->i_dst_x_offset & ~1;
1959 if( p_sys->i_canvas_height <= 0 )
1961 /* No canvas set, add padding border */
1962 i_dst_height = p_sys->i_nopadd_height + ( p_sys->i_padd_top & ~1 ) +
1963 ( p_sys->i_padd_bottom & ~1 );
1964 p_sys->i_dst_y_offset = ( p_sys->i_padd_top & ~1 );
1968 /* Canvas set, check if we have to padd or crop */
1969 if( p_sys->i_canvas_height < p_sys->i_nopadd_height )
1971 /* need to crop more, but keep same scaling */
1972 int i_crop = 2 * (int)( ( p_sys->i_canvas_height & ~1 ) /
1973 f_scale_height / 2 + 0.5 );
1975 p_sys->i_src_y_offset += ( ( p_sys->i_crop_height - i_crop ) / 2 )
1977 p_sys->i_crop_height = i_crop;
1978 i_dst_height = p_sys->i_canvas_height & ~1;
1979 p_sys->i_nopadd_height = i_dst_height;
1981 else if( p_sys->i_canvas_height > p_sys->i_nopadd_height )
1984 i_dst_height = p_sys->i_canvas_height & ~1;
1985 p_sys->i_dst_y_offset = ( i_dst_height - p_sys->i_nopadd_height )
1987 p_sys->i_dst_y_offset = p_sys->i_dst_y_offset & ~1;
1991 /* Change aspect ratio from scaled pixel to output frame */
1992 f_aspect = f_aspect * i_dst_width / i_dst_height;
1994 /* Store calculated values */
1995 id->p_encoder->fmt_out.video.i_width = i_dst_width;
1996 id->p_encoder->fmt_out.video.i_height = i_dst_height;
1998 id->p_encoder->fmt_in.video.i_width = i_dst_width;
1999 id->p_encoder->fmt_in.video.i_height = i_dst_height;
2001 msg_Dbg( p_stream, "source %ix%i, crop %ix%i, "
2002 "destination %ix%i, padding %ix%i",
2003 i_src_width, i_src_height,
2004 p_sys->i_crop_width, p_sys->i_crop_height,
2005 p_sys->i_nopadd_width, p_sys->i_nopadd_height,
2006 i_dst_width, i_dst_height
2009 /* Handle frame rate conversion */
2010 if( !id->p_encoder->fmt_out.video.i_frame_rate ||
2011 !id->p_encoder->fmt_out.video.i_frame_rate_base )
2013 if( id->p_decoder->fmt_out.video.i_frame_rate &&
2014 id->p_decoder->fmt_out.video.i_frame_rate_base )
2016 id->p_encoder->fmt_out.video.i_frame_rate =
2017 id->p_decoder->fmt_out.video.i_frame_rate;
2018 id->p_encoder->fmt_out.video.i_frame_rate_base =
2019 id->p_decoder->fmt_out.video.i_frame_rate_base;
2023 /* Pick a sensible default value */
2024 id->p_encoder->fmt_out.video.i_frame_rate = 25;
2025 id->p_encoder->fmt_out.video.i_frame_rate_base = 1;
2029 id->p_encoder->fmt_in.video.i_frame_rate =
2030 id->p_encoder->fmt_out.video.i_frame_rate;
2031 id->p_encoder->fmt_in.video.i_frame_rate_base =
2032 id->p_encoder->fmt_out.video.i_frame_rate_base;
2034 date_Init( &id->interpolated_pts,
2035 id->p_encoder->fmt_out.video.i_frame_rate,
2036 id->p_encoder->fmt_out.video.i_frame_rate_base );
2038 /* Check whether a particular aspect ratio was requested */
2039 if( !id->p_encoder->fmt_out.video.i_aspect )
2041 id->p_encoder->fmt_out.video.i_aspect = (int)( f_aspect * VOUT_ASPECT_FACTOR + 0.5 );
2043 id->p_encoder->fmt_in.video.i_aspect =
2044 id->p_encoder->fmt_out.video.i_aspect;
2046 msg_Dbg( p_stream, "encoder aspect is %i:%i", id->p_encoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
2048 id->p_encoder->p_module =
2049 module_Need( id->p_encoder, "encoder", p_sys->psz_venc, VLC_TRUE );
2050 if( !id->p_encoder->p_module )
2052 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_venc );
2053 return VLC_EGENERIC;
2056 id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
2058 /* Hack for mp2v/mp1v transcoding support */
2059 if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','1','v') ||
2060 id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','2','v') )
2062 id->p_encoder->fmt_out.i_codec = VLC_FOURCC('m','p','g','v');
2065 id->id = p_stream->p_sys->p_out->pf_add( p_stream->p_sys->p_out,
2066 &id->p_encoder->fmt_out );
2069 msg_Err( p_stream, "cannot add this stream" );
2070 return VLC_EGENERIC;
2076 static void transcode_video_close( sout_stream_t *p_stream,
2077 sout_stream_id_t *id )
2081 if( p_stream->p_sys->i_threads >= 1 )
2083 vlc_mutex_lock( &p_stream->p_sys->lock_out );
2084 vlc_object_kill( p_stream->p_sys );
2085 vlc_cond_signal( &p_stream->p_sys->cond );
2086 vlc_mutex_unlock( &p_stream->p_sys->lock_out );
2087 vlc_thread_join( p_stream->p_sys );
2088 vlc_mutex_destroy( &p_stream->p_sys->lock_out );
2089 vlc_cond_destroy( &p_stream->p_sys->cond );
2093 if( id->p_decoder->p_module )
2094 module_Unneed( id->p_decoder, id->p_decoder->p_module );
2096 if( id->p_decoder->p_owner )
2098 /* Clean-up pictures ring buffer */
2099 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2101 if( id->p_decoder->p_owner->pp_pics[i] )
2102 video_del_buffer( VLC_OBJECT(id->p_decoder),
2103 id->p_decoder->p_owner->pp_pics[i] );
2105 free( id->p_decoder->p_owner );
2109 if( id->p_encoder->p_module )
2110 module_Unneed( id->p_encoder, id->p_encoder->p_module );
2113 for( i = 0; i < id->i_filter; i++ )
2115 vlc_object_detach( id->pp_filter[i] );
2116 if( id->pp_filter[i]->p_module )
2117 module_Unneed( id->pp_filter[i], id->pp_filter[i]->p_module );
2119 /* Clean-up pictures ring buffer */
2120 for( j = 0; j < PICTURE_RING_SIZE; j++ )
2122 if( id->pp_filter[i]->p_owner->pp_pics[j] )
2123 video_del_buffer( VLC_OBJECT(id->pp_filter[i]),
2124 id->pp_filter[i]->p_owner->pp_pics[j] );
2126 free( id->pp_filter[i]->p_owner );
2127 vlc_object_destroy( id->pp_filter[i] );
2128 id->pp_filter[i] = NULL;
2131 for( i = 0; i < id->i_ufilter; i++ )
2133 vlc_object_detach( id->pp_ufilter[i] );
2134 if( id->pp_ufilter[i]->p_module )
2135 module_Unneed( id->pp_ufilter[i], id->pp_ufilter[i]->p_module );
2137 /* Clean-up pictures ring buffer */
2138 for( j = 0; j < PICTURE_RING_SIZE; j++ )
2140 if( id->pp_ufilter[i]->p_owner->pp_pics[j] )
2141 video_del_buffer( VLC_OBJECT(id->pp_ufilter[i]),
2142 id->pp_ufilter[i]->p_owner->pp_pics[j] );
2144 free( id->pp_ufilter[i]->p_owner );
2145 vlc_object_destroy( id->pp_ufilter[i] );
2146 id->pp_ufilter[i] = NULL;
2150 static int transcode_video_process( sout_stream_t *p_stream,
2151 sout_stream_id_t *id,
2152 block_t *in, block_t **out )
2154 sout_stream_sys_t *p_sys = p_stream->p_sys;
2155 int i_duplicate = 1, i;
2156 picture_t *p_pic, *p_pic2 = NULL;
2158 input_thread_t *p_input = NULL;
2160 if( p_stream->p_parent->p_parent && p_stream->p_parent->p_parent->
2161 i_object_type == VLC_OBJECT_INPUT )
2162 p_input = (input_thread_t *)p_stream->p_parent->p_parent;
2164 while( (p_pic = id->p_decoder->pf_decode_video( id->p_decoder, &in )) )
2166 subpicture_t *p_subpic = NULL;
2167 #warning Stats not implemented!
2170 stats_UpdateInteger( p_input, p_input->p->counters.p_decoded_video,
2174 if( p_stream->p_sout->i_out_pace_nocontrol && p_sys->b_hurry_up )
2176 mtime_t current_date = mdate();
2177 if( current_date + 50000 > p_pic->date )
2179 msg_Dbg( p_stream, "late picture skipped ("I64Fd")",
2180 current_date + 50000 - p_pic->date );
2181 p_pic->pf_release( p_pic );
2186 if( p_sys->b_master_sync )
2188 mtime_t i_video_drift;
2189 mtime_t i_master_drift = p_sys->i_master_drift;
2192 i_pts = date_Get( &id->interpolated_pts ) + 1;
2193 if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2194 || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2196 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2197 date_Set( &id->interpolated_pts, p_pic->date );
2198 i_pts = p_pic->date + 1;
2200 i_video_drift = p_pic->date - i_pts;
2203 /* Set the pts of the frame being encoded */
2204 p_pic->date = i_pts;
2206 if( i_video_drift < (i_master_drift - 50000) )
2209 msg_Dbg( p_stream, "dropping frame (%i)",
2210 (int)(i_video_drift - i_master_drift) );
2212 p_pic->pf_release( p_pic );
2215 else if( i_video_drift > (i_master_drift + 50000) )
2218 msg_Dbg( p_stream, "adding frame (%i)",
2219 (int)(i_video_drift - i_master_drift) );
2225 if( !id->p_encoder->p_module )
2227 if( transcode_video_encoder_open( p_stream, id ) != VLC_SUCCESS )
2229 p_pic->pf_release( p_pic );
2230 transcode_video_close( p_stream, id );
2231 id->b_transcode = VLC_FALSE;
2232 return VLC_EGENERIC;
2236 if( p_stream->p_sys->b_deinterlace )
2238 id->pp_filter[id->i_filter] =
2239 vlc_object_create( p_stream, VLC_OBJECT_FILTER );
2240 vlc_object_attach( id->pp_filter[id->i_filter], p_stream );
2242 id->pp_filter[id->i_filter]->pf_vout_buffer_new =
2243 video_new_buffer_filter;
2244 id->pp_filter[id->i_filter]->pf_vout_buffer_del =
2245 video_del_buffer_filter;
2247 id->pp_filter[id->i_filter]->fmt_in = id->p_decoder->fmt_out;
2248 id->pp_filter[id->i_filter]->fmt_out = id->p_decoder->fmt_out;
2249 id->pp_filter[id->i_filter]->p_cfg = p_sys->p_deinterlace_cfg;
2250 id->pp_filter[id->i_filter]->p_module =
2251 module_Need( id->pp_filter[id->i_filter],
2252 "video filter2", p_sys->psz_deinterlace,
2254 if( id->pp_filter[id->i_filter]->p_module )
2256 id->pp_filter[id->i_filter]->p_owner =
2257 malloc( sizeof(filter_owner_sys_t) );
2258 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2259 id->pp_filter[id->i_filter]->p_owner->pp_pics[i] = 0;
2260 id->pp_filter[id->i_filter]->p_owner->p_sys = p_sys;
2266 msg_Dbg( p_stream, "no video filter found" );
2267 vlc_object_detach( id->pp_filter[id->i_filter] );
2268 vlc_object_destroy( id->pp_filter[id->i_filter] );
2272 /* Check if we need a filter for chroma conversion or resizing */
2273 if( id->p_decoder->fmt_out.video.i_chroma !=
2274 id->p_encoder->fmt_in.video.i_chroma ||
2276 (int)id->p_decoder->fmt_out.video.i_width != p_sys->i_crop_width ||
2277 p_sys->i_crop_width != p_sys->i_nopadd_width ||
2278 p_sys->i_nopadd_width != (int)id->p_encoder->fmt_out.video.i_width ||
2280 (int)id->p_decoder->fmt_out.video.i_height != p_sys->i_crop_height ||
2281 p_sys->i_crop_height != p_sys->i_nopadd_height ||
2282 p_sys->i_nopadd_height != (int)id->p_encoder->fmt_out.video.i_height)
2284 id->pp_filter[id->i_filter] =
2285 vlc_object_create( p_stream, VLC_OBJECT_FILTER );
2286 vlc_object_attach( id->pp_filter[id->i_filter], p_stream );
2288 id->pp_filter[id->i_filter]->pf_vout_buffer_new =
2289 video_new_buffer_filter;
2290 id->pp_filter[id->i_filter]->pf_vout_buffer_del =
2291 video_del_buffer_filter;
2293 id->pp_filter[id->i_filter]->fmt_in = id->p_decoder->fmt_out;
2294 id->pp_filter[id->i_filter]->fmt_out = id->p_encoder->fmt_in;
2295 id->pp_filter[id->i_filter]->p_cfg = NULL;
2297 id->pp_filter[id->i_filter]->fmt_in.video.i_x_offset = p_sys->i_src_x_offset;
2298 id->pp_filter[id->i_filter]->fmt_in.video.i_y_offset = p_sys->i_src_y_offset;
2299 id->pp_filter[id->i_filter]->fmt_in.video.i_visible_width = p_sys->i_crop_width;
2300 id->pp_filter[id->i_filter]->fmt_in.video.i_visible_height = p_sys->i_crop_height;
2302 id->pp_filter[id->i_filter]->fmt_out.video.i_x_offset = p_sys->i_dst_x_offset;
2303 id->pp_filter[id->i_filter]->fmt_out.video.i_y_offset = p_sys->i_dst_y_offset;
2304 id->pp_filter[id->i_filter]->fmt_out.video.i_visible_width = p_sys->i_nopadd_width;
2305 id->pp_filter[id->i_filter]->fmt_out.video.i_visible_height = p_sys->i_nopadd_height;
2307 id->pp_filter[id->i_filter]->p_module =
2308 module_Need( id->pp_filter[id->i_filter],
2309 "crop padd", 0, 0 );
2310 if( id->pp_filter[id->i_filter]->p_module )
2312 id->pp_filter[id->i_filter]->p_owner =
2313 malloc( sizeof(filter_owner_sys_t) );
2314 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2315 id->pp_filter[id->i_filter]->p_owner->pp_pics[i] = 0;
2316 id->pp_filter[id->i_filter]->p_owner->p_sys = p_sys;
2322 msg_Dbg( p_stream, "no video filter found" );
2323 vlc_object_detach( id->pp_filter[id->i_filter] );
2324 vlc_object_destroy( id->pp_filter[id->i_filter] );
2326 p_pic->pf_release( p_pic );
2327 transcode_video_close( p_stream, id );
2328 id->b_transcode = VLC_FALSE;
2329 return VLC_EGENERIC;
2333 for( i = 0; (i < p_sys->i_vfilters) && (id->i_ufilter < TRANSCODE_FILTERS); i++ )
2335 id->pp_ufilter[id->i_ufilter] =
2336 vlc_object_create( p_stream, VLC_OBJECT_FILTER );
2337 vlc_object_attach( id->pp_ufilter[id->i_ufilter], p_stream );
2339 id->pp_ufilter[id->i_ufilter]->pf_vout_buffer_new =
2340 video_new_buffer_filter;
2341 id->pp_ufilter[id->i_ufilter]->pf_vout_buffer_del =
2342 video_del_buffer_filter;
2344 id->pp_ufilter[id->i_ufilter]->fmt_in = id->p_encoder->fmt_in;
2345 id->pp_ufilter[id->i_ufilter]->fmt_out = id->p_encoder->fmt_in;
2346 id->pp_ufilter[id->i_ufilter]->p_cfg = p_sys->p_vfilters_cfg[i];
2347 id->pp_ufilter[id->i_ufilter]->p_module =
2348 module_Need( id->pp_ufilter[id->i_ufilter],
2349 "video filter2", p_sys->psz_vfilters[i], VLC_TRUE );
2350 if( id->pp_ufilter[id->i_ufilter]->p_module )
2352 id->pp_ufilter[id->i_ufilter]->p_owner =
2353 malloc( sizeof(filter_owner_sys_t) );
2354 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2355 id->pp_ufilter[id->i_ufilter]->p_owner->pp_pics[i] = 0;
2356 id->pp_ufilter[id->i_ufilter]->p_owner->p_sys = p_sys;
2361 msg_Dbg( p_stream, "no video filter found" );
2362 vlc_object_detach( id->pp_ufilter[id->i_ufilter] );
2363 vlc_object_destroy( id->pp_ufilter[id->i_ufilter] );
2364 id->pp_ufilter[id->i_ufilter] = NULL;
2369 /* Run filter chain */
2370 for( i = 0; i < id->i_filter; i++ )
2372 p_pic = id->pp_filter[i]->pf_video_filter(id->pp_filter[i], p_pic);
2379 /* Check if we have a subpicture to overlay */
2382 p_subpic = spu_SortSubpictures( p_sys->p_spu, p_pic->date,
2383 VLC_FALSE /* Fixme: check if stream is paused */ );
2384 /* TODO: get another pic */
2387 /* Overlay subpicture */
2390 int i_scale_width, i_scale_height;
2391 video_format_t *p_fmt;
2393 i_scale_width = id->p_encoder->fmt_in.video.i_width * 1000 /
2394 id->p_decoder->fmt_out.video.i_width;
2395 i_scale_height = id->p_encoder->fmt_in.video.i_height * 1000 /
2396 id->p_decoder->fmt_out.video.i_height;
2398 if( p_pic->i_refcount && !id->i_filter )
2400 /* We can't modify the picture, we need to duplicate it */
2401 picture_t *p_tmp = video_new_buffer_decoder( id->p_decoder );
2404 vout_CopyPicture( p_stream, p_tmp, p_pic );
2405 p_pic->pf_release( p_pic );
2411 p_fmt = &id->pp_filter[id->i_filter -1]->fmt_out.video;
2413 p_fmt = &id->p_decoder->fmt_out.video;
2415 /* FIXME (shouldn't have to be done here) */
2416 p_fmt->i_sar_num = p_fmt->i_aspect *
2417 p_fmt->i_height / p_fmt->i_width;
2418 p_fmt->i_sar_den = VOUT_ASPECT_FACTOR;
2420 spu_RenderSubpictures( p_sys->p_spu, p_fmt, p_pic, p_pic, p_subpic,
2421 i_scale_width, i_scale_height );
2424 /* Run user specified filter chain */
2425 for( i = 0; i < id->i_ufilter; i++ )
2427 p_pic = id->pp_ufilter[i]->pf_video_filter( id->pp_ufilter[i],
2431 if( p_sys->i_threads == 0 )
2434 p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
2435 block_ChainAppend( out, p_block );
2438 if( p_sys->b_master_sync )
2440 mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
2441 if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2442 || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2444 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2445 date_Set( &id->interpolated_pts, p_pic->date );
2446 i_pts = p_pic->date + 1;
2448 date_Increment( &id->interpolated_pts, 1 );
2451 if( p_sys->b_master_sync && i_duplicate > 1 )
2453 mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
2454 if( (p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT)
2455 || ((p_pic->date - i_pts) < -MASTER_SYNC_MAX_DRIFT) )
2457 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2458 date_Set( &id->interpolated_pts, p_pic->date );
2459 i_pts = p_pic->date + 1;
2461 date_Increment( &id->interpolated_pts, 1 );
2463 if( p_sys->i_threads >= 1 )
2465 /* We can't modify the picture, we need to duplicate it */
2466 p_pic2 = video_new_buffer_decoder( id->p_decoder );
2467 if( p_pic2 != NULL )
2469 vout_CopyPicture( p_stream, p_pic2, p_pic );
2470 p_pic2->date = i_pts;
2476 p_pic->date = i_pts;
2477 p_block = id->p_encoder->pf_encode_video(id->p_encoder, p_pic);
2478 block_ChainAppend( out, p_block );
2482 if( p_sys->i_threads == 0 )
2484 p_pic->pf_release( p_pic );
2488 vlc_mutex_lock( &p_sys->lock_out );
2489 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic;
2490 p_sys->i_last_pic %= PICTURE_RING_SIZE;
2491 *out = p_sys->p_buffers;
2492 p_sys->p_buffers = NULL;
2493 if( p_pic2 != NULL )
2495 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic2;
2496 p_sys->i_last_pic %= PICTURE_RING_SIZE;
2498 vlc_cond_signal( &p_sys->cond );
2499 vlc_mutex_unlock( &p_sys->lock_out );
2506 static int EncoderThread( sout_stream_sys_t *p_sys )
2508 sout_stream_id_t *id = p_sys->id_video;
2511 while( !p_sys->b_die && !p_sys->b_error )
2515 vlc_mutex_lock( &p_sys->lock_out );
2516 while( p_sys->i_last_pic == p_sys->i_first_pic )
2518 vlc_cond_wait( &p_sys->cond, &p_sys->lock_out );
2519 if( p_sys->b_die || p_sys->b_error ) break;
2521 if( p_sys->b_die || p_sys->b_error )
2523 vlc_mutex_unlock( &p_sys->lock_out );
2527 p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2528 p_sys->i_first_pic %= PICTURE_RING_SIZE;
2529 vlc_mutex_unlock( &p_sys->lock_out );
2531 p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
2532 vlc_mutex_lock( &p_sys->lock_out );
2533 block_ChainAppend( &p_sys->p_buffers, p_block );
2535 vlc_mutex_unlock( &p_sys->lock_out );
2536 p_pic->pf_release( p_pic );
2539 while( p_sys->i_last_pic != p_sys->i_first_pic )
2541 p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2542 p_sys->i_first_pic %= PICTURE_RING_SIZE;
2543 p_pic->pf_release( p_pic );
2545 block_ChainRelease( p_sys->p_buffers );
2550 struct picture_sys_t
2552 vlc_object_t *p_owner;
2555 static void video_release_buffer( picture_t *p_pic )
2557 if( p_pic && !p_pic->i_refcount && p_pic->pf_release && p_pic->p_sys )
2559 video_del_buffer_decoder( (decoder_t *)p_pic->p_sys->p_owner, p_pic );
2561 else if( p_pic && p_pic->i_refcount > 0 ) p_pic->i_refcount--;
2564 static picture_t *video_new_buffer( vlc_object_t *p_this, picture_t **pp_ring,
2565 sout_stream_sys_t *p_sys )
2567 decoder_t *p_dec = (decoder_t *)p_this;
2571 /* Find an empty space in the picture ring buffer */
2572 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2574 if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
2576 pp_ring[i]->i_status = RESERVED_PICTURE;
2580 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2582 if( pp_ring[i] == 0 ) break;
2585 if( i == PICTURE_RING_SIZE && p_sys->i_threads >= 1 )
2587 int i_first_pic = p_sys->i_first_pic;
2589 if( p_sys->i_first_pic != p_sys->i_last_pic )
2591 /* Encoder still has stuff to encode, wait to clear-up the list */
2592 while( p_sys->i_first_pic == i_first_pic )
2596 /* Find an empty space in the picture ring buffer */
2597 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2599 if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
2601 pp_ring[i]->i_status = RESERVED_PICTURE;
2605 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2607 if( pp_ring[i] == 0 ) break;
2611 if( i == PICTURE_RING_SIZE )
2613 msg_Err( p_this, "decoder/filter is leaking pictures, "
2614 "resetting its ring buffer" );
2616 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2618 pp_ring[i]->pf_release( pp_ring[i] );
2624 p_pic = malloc( sizeof(picture_t) );
2625 if( !p_pic ) return NULL;
2626 p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
2627 vout_AllocatePicture( VLC_OBJECT(p_dec), p_pic,
2628 p_dec->fmt_out.video.i_chroma,
2629 p_dec->fmt_out.video.i_width,
2630 p_dec->fmt_out.video.i_height,
2631 p_dec->fmt_out.video.i_aspect );
2633 if( !p_pic->i_planes )
2639 p_pic->pf_release = video_release_buffer;
2640 p_pic->p_sys = malloc( sizeof(picture_sys_t) );
2647 p_pic->p_sys->p_owner = p_this;
2648 p_pic->i_status = RESERVED_PICTURE;
2654 static picture_t *video_new_buffer_decoder( decoder_t *p_dec )
2656 return video_new_buffer( VLC_OBJECT(p_dec),
2657 p_dec->p_owner->pp_pics, p_dec->p_owner->p_sys );
2660 static picture_t *video_new_buffer_filter( filter_t *p_filter )
2662 return video_new_buffer( VLC_OBJECT(p_filter),
2663 p_filter->p_owner->pp_pics,
2664 p_filter->p_owner->p_sys );
2667 static void video_del_buffer( vlc_object_t *p_this, picture_t *p_pic )
2669 if( p_pic && p_pic->p_data_orig ) free( p_pic->p_data_orig );
2670 if( p_pic && p_pic->p_sys ) free( p_pic->p_sys );
2671 if( p_pic ) free( p_pic );
2674 static void video_del_buffer_decoder( decoder_t *p_decoder, picture_t *p_pic )
2676 p_pic->i_refcount = 0;
2677 p_pic->i_status = DESTROYED_PICTURE;
2680 static void video_del_buffer_filter( filter_t *p_filter, picture_t *p_pic )
2682 p_pic->i_refcount = 0;
2683 p_pic->i_status = DESTROYED_PICTURE;
2686 static void video_link_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2688 p_pic->i_refcount++;
2691 static void video_unlink_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2693 video_release_buffer( p_pic );
2699 static subpicture_t *spu_new_buffer( decoder_t * );
2700 static void spu_del_buffer( decoder_t *, subpicture_t * );
2702 static int transcode_spu_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2704 sout_stream_sys_t *p_sys = p_stream->p_sys;
2710 /* Initialization of decoder structures */
2711 id->p_decoder->pf_spu_buffer_new = spu_new_buffer;
2712 id->p_decoder->pf_spu_buffer_del = spu_del_buffer;
2713 id->p_decoder->p_owner = (decoder_owner_sys_t *)p_stream;
2714 /* id->p_decoder->p_cfg = p_sys->p_spu_cfg; */
2716 id->p_decoder->p_module =
2717 module_Need( id->p_decoder, "decoder", "$codec", 0 );
2719 if( !id->p_decoder->p_module )
2721 msg_Err( p_stream, "cannot find decoder" );
2722 return VLC_EGENERIC;
2725 if( !p_sys->b_soverlay )
2728 /* Initialization of encoder format structures */
2729 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
2730 id->p_decoder->fmt_in.i_codec );
2732 id->p_encoder->p_cfg = p_sys->p_spu_cfg;
2734 id->p_encoder->p_module =
2735 module_Need( id->p_encoder, "encoder", p_sys->psz_senc, VLC_TRUE );
2737 if( !id->p_encoder->p_module )
2739 module_Unneed( id->p_decoder, id->p_decoder->p_module );
2740 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_senc );
2741 return VLC_EGENERIC;
2747 p_sys->p_spu = spu_Create( p_stream );
2748 spu_Init( p_sys->p_spu );
2754 static void transcode_spu_close( sout_stream_t *p_stream, sout_stream_id_t *id)
2757 if( id->p_decoder->p_module )
2758 module_Unneed( id->p_decoder, id->p_decoder->p_module );
2761 if( id->p_encoder->p_module )
2762 module_Unneed( id->p_encoder, id->p_encoder->p_module );
2765 static int transcode_spu_process( sout_stream_t *p_stream,
2766 sout_stream_id_t *id,
2767 block_t *in, block_t **out )
2769 sout_stream_sys_t *p_sys = p_stream->p_sys;
2770 subpicture_t *p_subpic;
2773 p_subpic = id->p_decoder->pf_decode_sub( id->p_decoder, &in );
2774 if( !p_subpic ) return VLC_EGENERIC;
2776 if( p_sys->b_master_sync && p_sys->i_master_drift )
2778 p_subpic->i_start -= p_sys->i_master_drift;
2779 if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2782 if( p_sys->b_soverlay )
2784 spu_DisplaySubpicture( p_sys->p_spu, p_subpic );
2790 p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
2791 spu_del_buffer( id->p_decoder, p_subpic );
2794 block_ChainAppend( out, p_block );
2799 return VLC_EGENERIC;
2802 static subpicture_t *spu_new_buffer( decoder_t *p_dec )
2804 sout_stream_t *p_stream = (sout_stream_t *)p_dec->p_owner;
2805 return spu_CreateSubpicture( p_stream->p_sys->p_spu );
2808 static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_subpic )
2810 sout_stream_t *p_stream = (sout_stream_t *)p_dec->p_owner;
2811 spu_DestroySubpicture( p_stream->p_sys->p_spu, p_subpic );
2817 static int transcode_osd_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2819 sout_stream_sys_t *p_sys = p_stream->p_sys;
2821 id->p_decoder->fmt_in.i_cat = SPU_ES;
2822 id->p_encoder->fmt_out.psz_language = strdup( "osd" );
2824 if( p_sys->i_osdcodec != 0 || p_sys->psz_osdenc )
2826 msg_Dbg( p_stream, "creating osdmenu transcoding from fcc=`%4.4s' "
2827 "to fcc=`%4.4s'", (char*)&id->p_encoder->fmt_out.i_codec,
2828 (char*)&p_sys->i_osdcodec );
2830 /* Complete destination format */
2831 id->p_encoder->fmt_out.i_codec = p_sys->i_osdcodec;
2834 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
2835 VLC_FOURCC('Y','U','V','A') );
2836 id->p_encoder->fmt_in.psz_language = strdup( "osd" );
2838 id->p_encoder->p_cfg = p_sys->p_osd_cfg;
2840 id->p_encoder->p_module =
2841 module_Need( id->p_encoder, "encoder", p_sys->psz_osdenc, VLC_TRUE );
2843 if( !id->p_encoder->p_module )
2845 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_osdenc );
2849 /* open output stream */
2850 id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
2851 id->b_transcode = VLC_TRUE;
2853 if( !id->id ) goto error;
2857 msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
2858 (char*)&id->p_decoder->fmt_out.i_codec );
2859 id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_decoder->fmt_out );
2860 id->b_transcode = VLC_FALSE;
2862 if( !id->id ) goto error;
2867 p_sys->p_spu = spu_Create( p_stream );
2868 spu_Init( p_sys->p_spu );
2874 msg_Err( p_stream, "starting osd encoding thread failed" );
2875 if( id->p_encoder->p_module )
2876 module_Unneed( id->p_encoder, id->p_encoder->p_module );
2877 p_sys->b_osd = VLC_FALSE;
2878 return VLC_EGENERIC;
2881 static void transcode_osd_close( sout_stream_t *p_stream, sout_stream_id_t *id)
2883 sout_stream_sys_t *p_sys = p_stream->p_sys;
2886 if( p_sys->b_osd && id )
2888 if( id->p_encoder->p_module )
2889 module_Unneed( id->p_encoder, id->p_encoder->p_module );
2891 p_sys->b_osd = VLC_FALSE;
2894 static int transcode_osd_process( sout_stream_t *p_stream,
2895 sout_stream_id_t *id,
2896 block_t *in, block_t **out )
2898 sout_stream_sys_t *p_sys = p_stream->p_sys;
2899 subpicture_t *p_subpic = NULL;
2901 /* Check if we have a subpicture to send */
2902 if( p_sys->p_spu && in->i_dts > 0)
2904 p_subpic = spu_SortSubpictures( p_sys->p_spu, in->i_dts, VLC_FALSE );
2908 msg_Warn( p_stream, "spu channel not initialized, doing it now" );
2911 p_sys->p_spu = spu_Create( p_stream );
2912 spu_Init( p_sys->p_spu );
2918 block_t *p_block = NULL;
2920 if( p_sys->b_master_sync && p_sys->i_master_drift )
2922 p_subpic->i_start -= p_sys->i_master_drift;
2923 if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2926 p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
2927 spu_DestroySubpicture( p_sys->p_spu, p_subpic );
2930 p_block->i_dts = p_block->i_pts = in->i_dts;
2931 block_ChainAppend( out, p_block );
2935 return VLC_EGENERIC;