1 /*****************************************************************************
2 * transcode.c: transcoding stream output module
3 *****************************************************************************
4 * Copyright (C) 2003-2008 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>
38 #include <vlc_codec.h>
39 #include <vlc_block.h>
40 #include <vlc_filter.h>
45 #define MASTER_SYNC_MAX_DRIFT 100000
47 /*****************************************************************************
49 *****************************************************************************/
50 #define VENC_TEXT N_("Video encoder")
51 #define VENC_LONGTEXT N_( \
52 "This is the video encoder module that will be used (and its associated "\
54 #define VCODEC_TEXT N_("Destination video codec")
55 #define VCODEC_LONGTEXT N_( \
56 "This is the video codec that will be used.")
57 #define VB_TEXT N_("Video bitrate")
58 #define VB_LONGTEXT N_( \
59 "Target bitrate of the transcoded video stream." )
60 #define SCALE_TEXT N_("Video scaling")
61 #define SCALE_LONGTEXT N_( \
62 "Scale factor to apply to the video while transcoding (eg: 0.25)")
63 #define FPS_TEXT N_("Video frame-rate")
64 #define FPS_LONGTEXT N_( \
65 "Target output frame rate for the video stream." )
66 #define DEINTERLACE_TEXT N_("Deinterlace video")
67 #define DEINTERLACE_LONGTEXT N_( \
68 "Deinterlace the video before encoding." )
69 #define DEINTERLACE_MODULE_TEXT N_("Deinterlace module")
70 #define DEINTERLACE_MODULE_LONGTEXT N_( \
71 "Specify the deinterlace module to use." )
72 #define WIDTH_TEXT N_("Video width")
73 #define WIDTH_LONGTEXT N_( \
74 "Output video width." )
75 #define HEIGHT_TEXT N_("Video height")
76 #define HEIGHT_LONGTEXT N_( \
77 "Output video height." )
78 #define MAXWIDTH_TEXT N_("Maximum video width")
79 #define MAXWIDTH_LONGTEXT N_( \
80 "Maximum output video width." )
81 #define MAXHEIGHT_TEXT N_("Maximum video height")
82 #define MAXHEIGHT_LONGTEXT N_( \
83 "Maximum output video height." )
84 #define VFILTER_TEXT N_("Video filter")
85 #define VFILTER_LONGTEXT N_( \
86 "Video filters will be applied to the video streams (after overlays " \
87 "are applied). You must enter a comma-separated list of filters." )
89 #define CROPTOP_TEXT N_("Video crop (top)")
90 #define CROPTOP_LONGTEXT N_( \
91 "Number of pixels to crop at the top of the video." )
92 #define CROPLEFT_TEXT N_("Video crop (left)")
93 #define CROPLEFT_LONGTEXT N_( \
94 "Number of pixels to crop at the left of the video." )
95 #define CROPBOTTOM_TEXT N_("Video crop (bottom)")
96 #define CROPBOTTOM_LONGTEXT N_( \
97 "Number of pixels to crop at the bottom of the video." )
98 #define CROPRIGHT_TEXT N_("Video crop (right)")
99 #define CROPRIGHT_LONGTEXT N_( \
100 "Number of pixels to crop at the right of the video." )
102 #define PADDTOP_TEXT N_("Video padding (top)")
103 #define PADDTOP_LONGTEXT N_( \
104 "Size of the black border to add at the top of the video." )
105 #define PADDLEFT_TEXT N_("Video padding (left)")
106 #define PADDLEFT_LONGTEXT N_( \
107 "Size of the black border to add at the left of the video." )
108 #define PADDBOTTOM_TEXT N_("Video padding (bottom)")
109 #define PADDBOTTOM_LONGTEXT N_( \
110 "Size of the black border to add at the bottom of the video." )
111 #define PADDRIGHT_TEXT N_("Video padding (right)")
112 #define PADDRIGHT_LONGTEXT N_( \
113 "Size of the black border to add at the right of the video." )
115 #define CANVAS_WIDTH_TEXT N_("Video canvas width")
116 #define CANVAS_WIDTH_LONGTEXT N_( \
117 "This will automatically crod and pad the video to a specified width." )
118 #define CANVAS_HEIGHT_TEXT N_("Video canvas height")
119 #define CANVAS_HEIGHT_LONGTEXT N_( \
120 "This will automatically crod and pad the video to a specified height." )
121 #define CANVAS_ASPECT_TEXT N_("Video canvas aspect ratio")
122 #define CANVAS_ASPECT_LONGTEXT N_( \
123 "This sets aspect (like 4:3) of the video canvas and letterbox the video "\
126 #define AENC_TEXT N_("Audio encoder")
127 #define AENC_LONGTEXT N_( \
128 "This is the audio encoder module that will be used (and its associated "\
130 #define ACODEC_TEXT N_("Destination audio codec")
131 #define ACODEC_LONGTEXT N_( \
132 "This is the audio codec that will be used.")
133 #define AB_TEXT N_("Audio bitrate")
134 #define AB_LONGTEXT N_( \
135 "Target bitrate of the transcoded audio stream." )
136 #define ARATE_TEXT N_("Audio sample rate")
137 #define ARATE_LONGTEXT N_( \
138 "Sample rate of the transcoded audio stream (11250, 22500, 44100 or 48000).")
139 #define ACHANS_TEXT N_("Audio channels")
140 #define ACHANS_LONGTEXT N_( \
141 "Number of audio channels in the transcoded streams." )
142 #define AFILTER_TEXT N_("Audio filter")
143 #define AFILTER_LONGTEXT N_( \
144 "Audio filters will be applied to the audio streams (after conversion " \
145 "filters are applied). You must enter a comma-separated list of filters." )
147 #define SENC_TEXT N_("Subtitles encoder")
148 #define SENC_LONGTEXT N_( \
149 "This is the subtitles encoder module that will be used (and its " \
150 "associated options)." )
151 #define SCODEC_TEXT N_("Destination subtitles codec")
152 #define SCODEC_LONGTEXT N_( \
153 "This is the subtitles codec that will be used." )
155 #define SFILTER_TEXT N_("Overlays")
156 #define SFILTER_LONGTEXT N_( \
157 "This allows you to add overlays (also known as \"subpictures\" on the "\
158 "transcoded video stream. The subpictures produced by the filters will "\
159 "be overlayed directly onto the video. You must specify a comma-separated "\
160 "list of subpicture modules" )
162 #define OSD_TEXT N_("OSD menu")
163 #define OSD_LONGTEXT N_(\
164 "Stream the On Screen Display menu (using the osdmenu subpicture module)." )
166 #define THREADS_TEXT N_("Number of threads")
167 #define THREADS_LONGTEXT N_( \
168 "Number of threads used for the transcoding." )
169 #define HP_TEXT N_("High priority")
170 #define HP_LONGTEXT N_( \
171 "Runs the optional encoder thread at the OUTPUT priority instead of " \
174 #define ASYNC_TEXT N_("Synchronise on audio track")
175 #define ASYNC_LONGTEXT N_( \
176 "This option will drop/duplicate video frames to synchronise the video " \
177 "track on the audio track." )
179 #define HURRYUP_TEXT N_( "Hurry up" )
180 #define HURRYUP_LONGTEXT N_( "The transcoder will drop frames if your CPU " \
181 "can't keep up with the encoding rate." )
183 static const char *ppsz_deinterlace_type[] =
185 "deinterlace", "ffmpeg-deinterlace"
188 static int Open ( vlc_object_t * );
189 static void Close( vlc_object_t * );
191 #define SOUT_CFG_PREFIX "sout-transcode-"
194 set_shortname( _("Transcode"));
195 set_description( _("Transcode stream output") );
196 set_capability( "sout stream", 50 );
197 add_shortcut( "transcode" );
198 set_callbacks( Open, Close );
199 set_category( CAT_SOUT );
200 set_subcategory( SUBCAT_SOUT_STREAM );
201 set_section( N_("Video"), NULL );
202 add_string( SOUT_CFG_PREFIX "venc", NULL, NULL, VENC_TEXT,
203 VENC_LONGTEXT, VLC_FALSE );
204 add_string( SOUT_CFG_PREFIX "vcodec", NULL, NULL, VCODEC_TEXT,
205 VCODEC_LONGTEXT, VLC_FALSE );
206 add_integer( SOUT_CFG_PREFIX "vb", 800 * 1000, NULL, VB_TEXT,
207 VB_LONGTEXT, VLC_FALSE );
208 add_float( SOUT_CFG_PREFIX "scale", 1, NULL, SCALE_TEXT,
209 SCALE_LONGTEXT, VLC_FALSE );
210 add_float( SOUT_CFG_PREFIX "fps", 0, NULL, FPS_TEXT,
211 FPS_LONGTEXT, VLC_FALSE );
212 add_bool( SOUT_CFG_PREFIX "hurry-up", VLC_TRUE, NULL, HURRYUP_TEXT,
213 HURRYUP_LONGTEXT, VLC_FALSE );
214 add_bool( SOUT_CFG_PREFIX "deinterlace", 0, NULL, DEINTERLACE_TEXT,
215 DEINTERLACE_LONGTEXT, VLC_FALSE );
216 add_string( SOUT_CFG_PREFIX "deinterlace-module", "deinterlace", NULL,
217 DEINTERLACE_MODULE_TEXT, DEINTERLACE_MODULE_LONGTEXT,
219 change_string_list( ppsz_deinterlace_type, 0, 0 );
220 add_integer( SOUT_CFG_PREFIX "width", 0, NULL, WIDTH_TEXT,
221 WIDTH_LONGTEXT, VLC_TRUE );
222 add_integer( SOUT_CFG_PREFIX "height", 0, NULL, HEIGHT_TEXT,
223 HEIGHT_LONGTEXT, VLC_TRUE );
224 add_integer( SOUT_CFG_PREFIX "maxwidth", 0, NULL, MAXWIDTH_TEXT,
225 MAXWIDTH_LONGTEXT, VLC_TRUE );
226 add_integer( SOUT_CFG_PREFIX "maxheight", 0, NULL, MAXHEIGHT_TEXT,
227 MAXHEIGHT_LONGTEXT, VLC_TRUE );
228 add_module_list( SOUT_CFG_PREFIX "vfilter", "video filter2",
230 VFILTER_TEXT, VFILTER_LONGTEXT, VLC_FALSE );
232 add_integer( SOUT_CFG_PREFIX "croptop", 0, NULL, CROPTOP_TEXT,
233 CROPTOP_LONGTEXT, VLC_TRUE );
234 add_integer( SOUT_CFG_PREFIX "cropleft", 0, NULL, CROPLEFT_TEXT,
235 CROPLEFT_LONGTEXT, VLC_TRUE );
236 add_integer( SOUT_CFG_PREFIX "cropbottom", 0, NULL, CROPBOTTOM_TEXT,
237 CROPBOTTOM_LONGTEXT, VLC_TRUE );
238 add_integer( SOUT_CFG_PREFIX "cropright", 0, NULL, CROPRIGHT_TEXT,
239 CROPRIGHT_LONGTEXT, VLC_TRUE );
241 add_integer( SOUT_CFG_PREFIX "paddtop", 0, NULL, PADDTOP_TEXT,
242 PADDTOP_LONGTEXT, VLC_TRUE );
243 add_integer( SOUT_CFG_PREFIX "paddleft", 0, NULL, PADDLEFT_TEXT,
244 PADDLEFT_LONGTEXT, VLC_TRUE );
245 add_integer( SOUT_CFG_PREFIX "paddbottom", 0, NULL, PADDBOTTOM_TEXT,
246 PADDBOTTOM_LONGTEXT, VLC_TRUE );
247 add_integer( SOUT_CFG_PREFIX "paddright", 0, NULL, PADDRIGHT_TEXT,
248 PADDRIGHT_LONGTEXT, VLC_TRUE );
250 add_integer( SOUT_CFG_PREFIX "canvas-width", 0, NULL, CANVAS_WIDTH_TEXT,
251 CANVAS_WIDTH_LONGTEXT, VLC_TRUE );
252 add_integer( SOUT_CFG_PREFIX "canvas-height", 0, NULL, CANVAS_HEIGHT_TEXT,
253 CANVAS_HEIGHT_LONGTEXT, VLC_TRUE );
254 add_string( SOUT_CFG_PREFIX "canvas-aspect", NULL, NULL, CANVAS_ASPECT_TEXT,
255 CANVAS_ASPECT_LONGTEXT, VLC_FALSE );
257 set_section( N_("Audio"), NULL );
258 add_string( SOUT_CFG_PREFIX "aenc", NULL, NULL, AENC_TEXT,
259 AENC_LONGTEXT, VLC_FALSE );
260 add_string( SOUT_CFG_PREFIX "acodec", NULL, NULL, ACODEC_TEXT,
261 ACODEC_LONGTEXT, VLC_FALSE );
262 add_integer( SOUT_CFG_PREFIX "ab", 0, NULL, AB_TEXT,
263 AB_LONGTEXT, VLC_FALSE );
264 add_integer( SOUT_CFG_PREFIX "channels", 0, NULL, ACHANS_TEXT,
265 ACHANS_LONGTEXT, VLC_FALSE );
266 add_integer( SOUT_CFG_PREFIX "samplerate", 0, NULL, ARATE_TEXT,
267 ARATE_LONGTEXT, VLC_TRUE );
268 add_bool( SOUT_CFG_PREFIX "audio-sync", 0, NULL, ASYNC_TEXT,
269 ASYNC_LONGTEXT, VLC_FALSE );
270 add_module_list( SOUT_CFG_PREFIX "afilter", "audio filter2",
272 AFILTER_TEXT, AFILTER_LONGTEXT, VLC_FALSE );
274 set_section( N_("Overlays/Subtitles"), NULL );
275 add_string( SOUT_CFG_PREFIX "senc", NULL, NULL, SENC_TEXT,
276 SENC_LONGTEXT, VLC_FALSE );
277 add_string( SOUT_CFG_PREFIX "scodec", NULL, NULL, SCODEC_TEXT,
278 SCODEC_LONGTEXT, VLC_FALSE );
279 add_bool( SOUT_CFG_PREFIX "soverlay", 0, NULL, SCODEC_TEXT,
280 SCODEC_LONGTEXT, VLC_FALSE );
281 add_module_list( SOUT_CFG_PREFIX "sfilter", "video filter",
283 SFILTER_TEXT, SFILTER_LONGTEXT, VLC_FALSE );
285 set_section( N_("On Screen Display"), NULL );
286 add_bool( SOUT_CFG_PREFIX "osd", 0, NULL, OSD_TEXT,
287 OSD_LONGTEXT, VLC_FALSE );
289 set_section( N_("Miscellaneous"), NULL );
290 add_integer( SOUT_CFG_PREFIX "threads", 0, NULL, THREADS_TEXT,
291 THREADS_LONGTEXT, VLC_TRUE );
292 add_bool( SOUT_CFG_PREFIX "high-priority", 0, NULL, HP_TEXT, HP_LONGTEXT,
297 static const char *ppsz_sout_options[] = {
298 "venc", "vcodec", "vb", "croptop", "cropbottom", "cropleft", "cropright",
299 "paddtop", "paddbottom", "paddleft", "paddright",
300 "canvas-width", "canvas-height", "canvas-aspect",
301 "scale", "fps", "width", "height", "vfilter", "deinterlace",
302 "deinterlace-module", "threads", "hurry-up", "aenc", "acodec", "ab",
303 "afilter", "samplerate", "channels", "senc", "scodec", "soverlay",
304 "sfilter", "osd", "audio-sync", "high-priority", "maxwidth", "maxheight",
308 /*****************************************************************************
309 * Exported prototypes
310 *****************************************************************************/
311 static sout_stream_id_t *Add ( sout_stream_t *, es_format_t * );
312 static int Del ( sout_stream_t *, sout_stream_id_t * );
313 static int Send( sout_stream_t *, sout_stream_id_t *, block_t* );
315 static int transcode_audio_new ( sout_stream_t *, sout_stream_id_t * );
316 static void transcode_audio_close ( sout_stream_id_t * );
317 static int transcode_audio_process( sout_stream_t *, sout_stream_id_t *,
318 block_t *, block_t ** );
320 static aout_buffer_t *audio_new_buffer( decoder_t *, int );
321 static void audio_del_buffer( decoder_t *, aout_buffer_t * );
323 static int transcode_video_new ( sout_stream_t *, sout_stream_id_t * );
324 static void transcode_video_close ( sout_stream_t *, sout_stream_id_t * );
325 static int transcode_video_encoder_open( sout_stream_t *, sout_stream_id_t *);
326 static int transcode_video_process( sout_stream_t *, sout_stream_id_t *,
327 block_t *, block_t ** );
329 static void video_del_buffer( vlc_object_t *, picture_t * );
330 static picture_t *video_new_buffer_decoder( decoder_t * );
331 static void video_del_buffer_decoder( decoder_t *, picture_t * );
332 static void video_link_picture_decoder( decoder_t *, picture_t * );
333 static void video_unlink_picture_decoder( decoder_t *, picture_t * );
334 static picture_t *video_new_buffer_filter( filter_t * );
335 static void video_del_buffer_filter( filter_t *, picture_t * );
337 static int transcode_spu_new ( sout_stream_t *, sout_stream_id_t * );
338 static void transcode_spu_close ( sout_stream_id_t * );
339 static int transcode_spu_process( sout_stream_t *, sout_stream_id_t *,
340 block_t *, block_t ** );
342 static int transcode_osd_new ( sout_stream_t *, sout_stream_id_t * );
343 static void transcode_osd_close ( sout_stream_t *, sout_stream_id_t * );
344 static int transcode_osd_process( sout_stream_t *, sout_stream_id_t *,
345 block_t *, block_t ** );
347 static int EncoderThread( struct sout_stream_sys_t * p_sys );
349 static int pi_channels_maps[6] =
352 AOUT_CHAN_CENTER, AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
353 AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
354 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
355 | AOUT_CHAN_REARRIGHT,
356 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
357 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
360 #define PICTURE_RING_SIZE 64
361 #define SUBPICTURE_RING_SIZE 20
362 #define TRANSCODE_FILTERS 10
364 struct sout_stream_sys_t
368 sout_stream_t *p_out;
369 sout_stream_id_t *id_video;
371 vlc_mutex_t lock_out;
373 picture_t * pp_pics[PICTURE_RING_SIZE];
374 int i_first_pic, i_last_pic;
377 vlc_fourcc_t i_acodec; /* codec audio (0 if not transcode) */
379 config_chain_t *p_audio_cfg;
380 uint32_t i_sample_rate;
383 char *psz_afilters[TRANSCODE_FILTERS];
384 config_chain_t *p_afilters_cfg[TRANSCODE_FILTERS];
388 vlc_fourcc_t i_vcodec; /* codec video (0 if not transcode) */
390 config_chain_t *p_video_cfg;
394 unsigned int i_width, i_maxwidth;
395 unsigned int i_height, i_maxheight;
396 vlc_bool_t b_deinterlace;
397 char *psz_deinterlace;
398 config_chain_t *p_deinterlace_cfg;
400 vlc_bool_t b_high_priority;
401 vlc_bool_t b_hurry_up;
402 char *psz_vfilters[TRANSCODE_FILTERS];
403 config_chain_t *p_vfilters_cfg[TRANSCODE_FILTERS];
420 /* Video, calculated */
432 vlc_fourcc_t i_scodec; /* codec spu (0 if not transcode) */
434 vlc_bool_t b_soverlay;
435 config_chain_t *p_spu_cfg;
439 vlc_fourcc_t i_osdcodec; /* codec osd menu (0 if not transcode) */
441 config_chain_t *p_osd_cfg;
442 vlc_bool_t b_osd; /* VLC_TRUE when osd es is registered */
445 vlc_bool_t b_master_sync;
446 mtime_t i_master_drift;
449 struct decoder_owner_sys_t
451 picture_t *pp_pics[PICTURE_RING_SIZE];
452 sout_stream_sys_t *p_sys;
454 struct filter_owner_sys_t
456 picture_t *pp_pics[PICTURE_RING_SIZE];
457 sout_stream_sys_t *p_sys;
460 /*****************************************************************************
462 *****************************************************************************/
463 static int Open( vlc_object_t *p_this )
465 sout_stream_t *p_stream = (sout_stream_t*)p_this;
466 sout_stream_sys_t *p_sys;
469 p_sys = vlc_object_create( p_this, sizeof( sout_stream_sys_t ) );
471 p_sys->p_out = sout_StreamNew( p_stream->p_sout, p_stream->psz_next );
474 msg_Err( p_stream, "cannot create chain" );
475 vlc_object_release( p_sys );
479 p_sys->i_master_drift = 0;
481 config_ChainParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
484 /* Audio transcoding parameters */
485 var_Get( p_stream, SOUT_CFG_PREFIX "aenc", &val );
486 p_sys->psz_aenc = NULL;
487 p_sys->p_audio_cfg = NULL;
488 if( val.psz_string && *val.psz_string )
491 psz_next = config_ChainCreate( &p_sys->psz_aenc, &p_sys->p_audio_cfg,
495 free( val.psz_string );
497 var_Get( p_stream, SOUT_CFG_PREFIX "acodec", &val );
499 if( val.psz_string && *val.psz_string )
502 memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
503 p_sys->i_acodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
505 free( val.psz_string );
507 var_Get( p_stream, SOUT_CFG_PREFIX "ab", &val );
508 p_sys->i_abitrate = val.i_int;
509 if( p_sys->i_abitrate < 4000 ) p_sys->i_abitrate *= 1000;
511 var_Get( p_stream, SOUT_CFG_PREFIX "samplerate", &val );
512 p_sys->i_sample_rate = val.i_int;
514 var_Get( p_stream, SOUT_CFG_PREFIX "channels", &val );
515 p_sys->i_channels = val.i_int;
517 if( p_sys->i_acodec )
519 if( p_sys->i_acodec == VLC_FOURCC('m','p','3',0) &&
520 p_sys->i_channels > 2 )
522 msg_Warn( p_stream, "%d channels invalid for mp3, forcing to 2",
524 p_sys->i_channels = 2;
526 msg_Dbg( p_stream, "codec audio=%4.4s %dHz %d channels %dKb/s",
527 (char *)&p_sys->i_acodec, p_sys->i_sample_rate,
528 p_sys->i_channels, p_sys->i_abitrate / 1000 );
531 var_Get( p_stream, SOUT_CFG_PREFIX "afilter", &val );
532 p_sys->i_afilters = 0;
533 if( val.psz_string && *val.psz_string )
535 char *psz_parser = val.psz_string;
537 while( (psz_parser != NULL) && (*psz_parser != '\0')
538 && (p_sys->i_afilters < TRANSCODE_FILTERS) )
540 psz_parser = config_ChainCreate(
541 &p_sys->psz_afilters[p_sys->i_afilters],
542 &p_sys->p_afilters_cfg[p_sys->i_afilters],
545 if( (psz_parser != NULL) && (*psz_parser != '\0') ) psz_parser++;
548 free( val.psz_string );
549 if( p_sys->i_afilters < TRANSCODE_FILTERS-1 )
551 p_sys->psz_afilters[p_sys->i_afilters] = NULL;
552 p_sys->p_afilters_cfg[p_sys->i_afilters] = NULL;
555 /* Video transcoding parameters */
556 var_Get( p_stream, SOUT_CFG_PREFIX "venc", &val );
557 p_sys->psz_venc = NULL;
558 p_sys->p_video_cfg = NULL;
559 if( val.psz_string && *val.psz_string )
562 psz_next = config_ChainCreate( &p_sys->psz_venc, &p_sys->p_video_cfg,
566 free( val.psz_string );
568 var_Get( p_stream, SOUT_CFG_PREFIX "vcodec", &val );
570 if( val.psz_string && *val.psz_string )
573 memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
574 p_sys->i_vcodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
576 free( val.psz_string );
578 var_Get( p_stream, SOUT_CFG_PREFIX "vb", &val );
579 p_sys->i_vbitrate = val.i_int;
580 if( p_sys->i_vbitrate < 16000 ) p_sys->i_vbitrate *= 1000;
582 var_Get( p_stream, SOUT_CFG_PREFIX "scale", &val );
583 p_sys->f_scale = val.f_float;
585 var_Get( p_stream, SOUT_CFG_PREFIX "fps", &val );
586 p_sys->f_fps = val.f_float;
588 var_Get( p_stream, SOUT_CFG_PREFIX "hurry-up", &val );
589 p_sys->b_hurry_up = val.b_bool;
591 var_Get( p_stream, SOUT_CFG_PREFIX "width", &val );
592 p_sys->i_width = val.i_int;
594 var_Get( p_stream, SOUT_CFG_PREFIX "height", &val );
595 p_sys->i_height = val.i_int;
597 var_Get( p_stream, SOUT_CFG_PREFIX "maxwidth", &val );
598 p_sys->i_maxwidth = val.i_int;
600 var_Get( p_stream, SOUT_CFG_PREFIX "maxheight", &val );
601 p_sys->i_maxheight = val.i_int;
603 var_Get( p_stream, SOUT_CFG_PREFIX "vfilter", &val );
604 p_sys->i_vfilters = 0;
605 if( val.psz_string && *val.psz_string )
607 char *psz_parser = val.psz_string;
609 while( (psz_parser != NULL) && (*psz_parser != '\0')
610 && (p_sys->i_vfilters < TRANSCODE_FILTERS) )
612 psz_parser = config_ChainCreate(
613 &p_sys->psz_vfilters[p_sys->i_vfilters],
614 &p_sys->p_vfilters_cfg[p_sys->i_vfilters],
617 if( psz_parser != NULL && *psz_parser != '\0' ) psz_parser++;
620 free( val.psz_string );
621 if( p_sys->i_vfilters < TRANSCODE_FILTERS-1 )
623 p_sys->psz_vfilters[p_sys->i_vfilters] = NULL;
624 p_sys->p_vfilters_cfg[p_sys->i_vfilters] = NULL;
627 var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace", &val );
628 p_sys->b_deinterlace = val.b_bool;
630 var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace-module", &val );
631 p_sys->psz_deinterlace = NULL;
632 p_sys->p_deinterlace_cfg = NULL;
633 if( val.psz_string && *val.psz_string )
636 psz_next = config_ChainCreate( &p_sys->psz_deinterlace,
637 &p_sys->p_deinterlace_cfg,
641 free( val.psz_string );
643 var_Get( p_stream, SOUT_CFG_PREFIX "croptop", &val );
644 p_sys->i_crop_top = val.i_int;
645 var_Get( p_stream, SOUT_CFG_PREFIX "cropbottom", &val );
646 p_sys->i_crop_bottom = val.i_int;
647 var_Get( p_stream, SOUT_CFG_PREFIX "cropleft", &val );
648 p_sys->i_crop_left = val.i_int;
649 var_Get( p_stream, SOUT_CFG_PREFIX "cropright", &val );
650 p_sys->i_crop_right = val.i_int;
652 var_Get( p_stream, SOUT_CFG_PREFIX "paddtop", &val );
653 p_sys->i_padd_top = val.i_int;
654 var_Get( p_stream, SOUT_CFG_PREFIX "paddbottom", &val );
655 p_sys->i_padd_bottom = val.i_int;
656 var_Get( p_stream, SOUT_CFG_PREFIX "paddleft", &val );
657 p_sys->i_padd_left = val.i_int;
658 var_Get( p_stream, SOUT_CFG_PREFIX "paddright", &val );
659 p_sys->i_padd_right = val.i_int;
661 var_Get( p_stream, SOUT_CFG_PREFIX "canvas-width", &val );
662 p_sys->i_canvas_width = val.i_int;
663 var_Get( p_stream, SOUT_CFG_PREFIX "canvas-height", &val );
664 p_sys->i_canvas_height = val.i_int;
666 var_Get( p_stream, SOUT_CFG_PREFIX "canvas-aspect", &val );
667 p_sys->i_canvas_aspect = 0;
668 if( val.psz_string && *val.psz_string )
670 char *psz_parser = strchr( val.psz_string, ':' );
673 *psz_parser++ = '\0';
674 p_sys->i_canvas_aspect = atoi( val.psz_string ) *
675 VOUT_ASPECT_FACTOR / atoi( psz_parser );
677 else msg_Warn( p_stream, "bad aspect ratio %s", val.psz_string );
680 free( val.psz_string );
682 var_Get( p_stream, SOUT_CFG_PREFIX "threads", &val );
683 p_sys->i_threads = val.i_int;
684 var_Get( p_stream, SOUT_CFG_PREFIX "high-priority", &val );
685 p_sys->b_high_priority = val.b_bool;
687 if( p_sys->i_vcodec )
689 msg_Dbg( p_stream, "codec video=%4.4s %dx%d scaling: %f %dkb/s",
690 (char *)&p_sys->i_vcodec, p_sys->i_width, p_sys->i_height,
691 p_sys->f_scale, p_sys->i_vbitrate / 1000 );
694 /* Subpictures transcoding parameters */
696 p_sys->psz_senc = NULL;
697 p_sys->p_spu_cfg = NULL;
700 var_Get( p_stream, SOUT_CFG_PREFIX "senc", &val );
701 if( val.psz_string && *val.psz_string )
704 psz_next = config_ChainCreate( &p_sys->psz_senc, &p_sys->p_spu_cfg,
708 free( val.psz_string );
710 var_Get( p_stream, SOUT_CFG_PREFIX "scodec", &val );
711 if( val.psz_string && *val.psz_string )
714 memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
715 p_sys->i_scodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
717 free( val.psz_string );
719 if( p_sys->i_scodec )
721 msg_Dbg( p_stream, "codec spu=%4.4s", (char *)&p_sys->i_scodec );
724 var_Get( p_stream, SOUT_CFG_PREFIX "soverlay", &val );
725 p_sys->b_soverlay = val.b_bool;
727 var_Get( p_stream, SOUT_CFG_PREFIX "sfilter", &val );
728 if( val.psz_string && *val.psz_string )
730 p_sys->p_spu = spu_Create( p_stream );
731 var_Create( p_sys->p_spu, "sub-filter", VLC_VAR_STRING );
732 var_Set( p_sys->p_spu, "sub-filter", val );
733 spu_Init( p_sys->p_spu );
735 free( val.psz_string );
737 /* OSD menu transcoding parameters */
738 p_sys->psz_osdenc = NULL;
739 p_sys->p_osd_cfg = NULL;
740 p_sys->i_osdcodec = 0;
741 p_sys->b_osd = VLC_FALSE;
743 var_Get( p_stream, SOUT_CFG_PREFIX "osd", &val );
749 psz_next = config_ChainCreate( &p_sys->psz_osdenc,
750 &p_sys->p_osd_cfg, strdup( "dvbsub") );
753 p_sys->i_osdcodec = VLC_FOURCC('Y','U','V','P' );
755 msg_Dbg( p_stream, "codec osd=%4.4s", (char *)&p_sys->i_osdcodec );
759 osd_val.psz_string = strdup("osdmenu");
760 p_sys->p_spu = spu_Create( p_stream );
761 var_Create( p_sys->p_spu, "sub-filter", VLC_VAR_STRING );
762 var_Set( p_sys->p_spu, "sub-filter", osd_val );
763 spu_Init( p_sys->p_spu );
764 free( osd_val.psz_string );
768 osd_val.psz_string = strdup("osdmenu");
769 var_Set( p_sys->p_spu, "sub-filter", osd_val );
770 free( osd_val.psz_string );
775 var_Get( p_stream, SOUT_CFG_PREFIX "audio-sync", &val );
776 p_sys->b_master_sync = val.b_bool;
777 if( p_sys->f_fps > 0 ) p_sys->b_master_sync = VLC_TRUE;
779 p_stream->pf_add = Add;
780 p_stream->pf_del = Del;
781 p_stream->pf_send = Send;
782 p_stream->p_sys = p_sys;
787 /*****************************************************************************
789 *****************************************************************************/
790 static void Close( vlc_object_t * p_this )
792 sout_stream_t *p_stream = (sout_stream_t*)p_this;
793 sout_stream_sys_t *p_sys = p_stream->p_sys;
795 sout_StreamDelete( p_sys->p_out );
797 while( p_sys->i_afilters )
800 free( p_sys->psz_afilters[p_sys->i_afilters] );
801 free( p_sys->p_afilters_cfg[p_sys->i_afilters] );
804 while( p_sys->p_audio_cfg != NULL )
806 config_chain_t *p_next = p_sys->p_audio_cfg->p_next;
808 free( p_sys->p_audio_cfg->psz_name );
809 free( p_sys->p_audio_cfg->psz_value );
810 free( p_sys->p_audio_cfg );
812 p_sys->p_audio_cfg = p_next;
814 free( p_sys->psz_aenc );
816 while( p_sys->i_vfilters )
819 free( p_sys->psz_vfilters[p_sys->i_vfilters] );
820 free( p_sys->p_vfilters_cfg[p_sys->i_vfilters] );
823 while( p_sys->p_video_cfg != NULL )
825 config_chain_t *p_next = p_sys->p_video_cfg->p_next;
827 free( p_sys->p_video_cfg->psz_name );
828 free( p_sys->p_video_cfg->psz_value );
829 free( p_sys->p_video_cfg );
831 p_sys->p_video_cfg = p_next;
833 free( p_sys->psz_venc );
835 while( p_sys->p_deinterlace_cfg != NULL )
837 config_chain_t *p_next = p_sys->p_deinterlace_cfg->p_next;
839 free( p_sys->p_deinterlace_cfg->psz_name );
840 free( p_sys->p_deinterlace_cfg->psz_value );
841 free( p_sys->p_deinterlace_cfg );
843 p_sys->p_deinterlace_cfg = p_next;
845 free( p_sys->psz_deinterlace );
847 while( p_sys->p_spu_cfg != NULL )
849 config_chain_t *p_next = p_sys->p_spu_cfg->p_next;
851 free( p_sys->p_spu_cfg->psz_name );
852 free( p_sys->p_spu_cfg->psz_value );
853 free( p_sys->p_spu_cfg );
855 p_sys->p_spu_cfg = p_next;
857 free( p_sys->psz_senc );
859 if( p_sys->p_spu ) spu_Destroy( p_sys->p_spu );
861 while( p_sys->p_osd_cfg != NULL )
863 config_chain_t *p_next = p_sys->p_osd_cfg->p_next;
865 free( p_sys->p_osd_cfg->psz_name );
866 free( p_sys->p_osd_cfg->psz_value );
867 free( p_sys->p_osd_cfg );
869 p_sys->p_osd_cfg = p_next;
871 free( p_sys->psz_osdenc );
873 vlc_object_release( p_sys );
876 struct sout_stream_id_t
878 vlc_fourcc_t b_transcode;
880 /* id of the out stream */
884 decoder_t *p_decoder;
887 filter_t *pp_filter[TRANSCODE_FILTERS];
889 /* User specified filters */
890 filter_t *pp_ufilter[TRANSCODE_FILTERS];
894 encoder_t *p_encoder;
897 date_t interpolated_pts;
900 static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
902 sout_stream_sys_t *p_sys = p_stream->p_sys;
903 sout_stream_id_t *id;
905 id = malloc( sizeof( sout_stream_id_t ) );
908 msg_Err( p_stream, "out of memory" );
911 memset( id, 0, sizeof(sout_stream_id_t) );
914 id->p_decoder = NULL;
915 id->p_encoder = NULL;
917 /* Create decoder object */
918 id->p_decoder = vlc_object_create( p_stream, VLC_OBJECT_DECODER );
921 msg_Err( p_stream, "out of memory" );
924 vlc_object_attach( id->p_decoder, p_stream );
925 id->p_decoder->p_module = NULL;
926 id->p_decoder->fmt_in = *p_fmt;
927 id->p_decoder->b_pace_control = VLC_TRUE;
929 /* Create encoder object */
930 id->p_encoder = vlc_object_create( p_stream, VLC_OBJECT_ENCODER );
933 msg_Err( p_stream, "out of memory" );
936 vlc_object_attach( id->p_encoder, p_stream );
937 id->p_encoder->p_module = NULL;
939 /* Create destination format */
940 es_format_Init( &id->p_encoder->fmt_out, p_fmt->i_cat, 0 );
941 id->p_encoder->fmt_out.i_id = p_fmt->i_id;
942 id->p_encoder->fmt_out.i_group = p_fmt->i_group;
943 if( p_fmt->psz_language )
944 id->p_encoder->fmt_out.psz_language = strdup( p_fmt->psz_language );
946 if( p_fmt->i_cat == AUDIO_ES && (p_sys->i_acodec || p_sys->psz_aenc) )
949 "creating audio transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
950 (char*)&p_fmt->i_codec, (char*)&p_sys->i_acodec );
952 /* Complete destination format */
953 id->p_encoder->fmt_out.i_codec = p_sys->i_acodec;
954 id->p_encoder->fmt_out.audio.i_rate = p_sys->i_sample_rate > 0 ?
955 p_sys->i_sample_rate : p_fmt->audio.i_rate;
956 id->p_encoder->fmt_out.i_bitrate = p_sys->i_abitrate;
957 id->p_encoder->fmt_out.audio.i_bitspersample =
958 p_fmt->audio.i_bitspersample;
959 id->p_encoder->fmt_out.audio.i_channels = p_sys->i_channels > 0 ?
960 p_sys->i_channels : p_fmt->audio.i_channels;
961 /* Sanity check for audio channels */
962 id->p_encoder->fmt_out.audio.i_channels =
963 __MIN( id->p_encoder->fmt_out.audio.i_channels,
964 id->p_decoder->fmt_in.audio.i_channels );
965 id->p_encoder->fmt_out.audio.i_original_channels =
966 id->p_decoder->fmt_in.audio.i_physical_channels;
967 if( id->p_decoder->fmt_in.audio.i_channels ==
968 id->p_encoder->fmt_out.audio.i_channels )
970 id->p_encoder->fmt_out.audio.i_physical_channels =
971 id->p_decoder->fmt_in.audio.i_physical_channels;
975 id->p_encoder->fmt_out.audio.i_physical_channels =
976 pi_channels_maps[id->p_encoder->fmt_out.audio.i_channels];
979 /* Build decoder -> filter -> encoder chain */
980 if( transcode_audio_new( p_stream, id ) )
982 msg_Err( p_stream, "cannot create audio chain" );
986 /* Open output stream */
987 id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
988 id->b_transcode = VLC_TRUE;
992 transcode_audio_close( id );
996 date_Init( &id->interpolated_pts, p_fmt->audio.i_rate, 1 );
998 else if( p_fmt->i_cat == VIDEO_ES &&
999 (p_sys->i_vcodec != 0 || p_sys->psz_venc) )
1002 "creating video transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
1003 (char*)&p_fmt->i_codec, (char*)&p_sys->i_vcodec );
1005 /* Complete destination format */
1006 id->p_encoder->fmt_out.i_codec = p_sys->i_vcodec;
1007 id->p_encoder->fmt_out.video.i_width = p_sys->i_width & ~1;
1008 id->p_encoder->fmt_out.video.i_height = p_sys->i_height & ~1;
1009 id->p_encoder->fmt_out.i_bitrate = p_sys->i_vbitrate;
1011 /* Build decoder -> filter -> encoder chain */
1012 if( transcode_video_new( p_stream, id ) )
1014 msg_Err( p_stream, "cannot create video chain" );
1018 /* Stream will be added later on because we don't know
1019 * all the characteristics of the decoded stream yet */
1020 id->b_transcode = VLC_TRUE;
1022 if( p_sys->f_fps > 0 )
1024 id->p_encoder->fmt_out.video.i_frame_rate =
1025 (p_sys->f_fps * 1001) + 0.5;
1026 id->p_encoder->fmt_out.video.i_frame_rate_base = 1001;
1029 else if( ( p_fmt->i_cat == SPU_ES ) &&
1030 ( p_sys->i_scodec || p_sys->psz_senc ) )
1032 msg_Dbg( p_stream, "creating subtitles transcoding from fcc=`%4.4s' "
1033 "to fcc=`%4.4s'", (char*)&p_fmt->i_codec,
1034 (char*)&p_sys->i_scodec );
1036 /* Complete destination format */
1037 id->p_encoder->fmt_out.i_codec = p_sys->i_scodec;
1039 /* build decoder -> filter -> encoder */
1040 if( transcode_spu_new( p_stream, id ) )
1042 msg_Err( p_stream, "cannot create subtitles chain" );
1046 /* open output stream */
1047 id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
1048 id->b_transcode = VLC_TRUE;
1052 transcode_spu_close( id );
1056 else if( p_fmt->i_cat == SPU_ES && p_sys->b_soverlay )
1058 msg_Dbg( p_stream, "subtitles (fcc=`%4.4s') overlaying",
1059 (char*)&p_fmt->i_codec );
1061 id->b_transcode = VLC_TRUE;
1063 /* Build decoder -> filter -> overlaying chain */
1064 if( transcode_spu_new( p_stream, id ) )
1066 msg_Err( p_stream, "cannot create subtitles chain" );
1070 else if( !p_sys->b_osd && (p_sys->i_osdcodec != 0 || p_sys->psz_osdenc) )
1072 msg_Dbg( p_stream, "creating osd transcoding from fcc=`%4.4s' "
1073 "to fcc=`%4.4s'", (char*)&p_fmt->i_codec,
1074 (char*)&p_sys->i_scodec );
1076 id->b_transcode = VLC_TRUE;
1078 /* Create a fake OSD menu elementary stream */
1079 if( transcode_osd_new( p_stream, id ) )
1081 msg_Err( p_stream, "cannot create osd chain" );
1084 p_sys->b_osd = VLC_TRUE;
1088 msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
1089 (char*)&p_fmt->i_codec );
1090 id->id = p_sys->p_out->pf_add( p_sys->p_out, p_fmt );
1091 id->b_transcode = VLC_FALSE;
1093 if( !id->id ) goto error;
1101 vlc_object_detach( id->p_decoder );
1102 vlc_object_release( id->p_decoder );
1103 id->p_decoder = NULL;
1108 vlc_object_detach( id->p_encoder );
1109 es_format_Clean( &id->p_encoder->fmt_out );
1110 vlc_object_release( id->p_encoder );
1111 id->p_encoder = NULL;
1118 static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
1120 sout_stream_sys_t *p_sys = p_stream->p_sys;
1122 if( id->b_transcode )
1124 switch( id->p_decoder->fmt_in.i_cat )
1127 transcode_audio_close( id );
1130 transcode_video_close( p_stream, id );
1134 transcode_osd_close( p_stream, id );
1136 transcode_spu_close( id );
1141 if( id->id ) p_sys->p_out->pf_del( p_sys->p_out, id->id );
1145 vlc_object_detach( id->p_decoder );
1146 vlc_object_release( id->p_decoder );
1147 id->p_decoder = NULL;
1152 vlc_object_detach( id->p_encoder );
1153 es_format_Clean( &id->p_encoder->fmt_out );
1154 vlc_object_release( id->p_encoder );
1155 id->p_encoder = NULL;
1162 static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
1165 sout_stream_sys_t *p_sys = p_stream->p_sys;
1166 block_t *p_out = NULL;
1168 if( !id->b_transcode && id->id )
1170 return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_buffer );
1172 else if( !id->b_transcode )
1174 block_Release( p_buffer );
1175 return VLC_EGENERIC;
1178 switch( id->p_decoder->fmt_in.i_cat )
1181 transcode_audio_process( p_stream, id, p_buffer, &p_out );
1185 if( transcode_video_process( p_stream, id, p_buffer, &p_out )
1188 return VLC_EGENERIC;
1193 /* Transcode OSD menu pictures. */
1196 if( transcode_osd_process( p_stream, id, p_buffer, &p_out ) !=
1199 return VLC_EGENERIC;
1202 else if ( transcode_spu_process( p_stream, id, p_buffer, &p_out ) !=
1205 return VLC_EGENERIC;
1211 block_Release( p_buffer );
1215 if( p_out ) return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_out );
1219 /****************************************************************************
1220 * decoder reencoder part
1221 ****************************************************************************/
1222 static int audio_BitsPerSample( vlc_fourcc_t i_format )
1226 case VLC_FOURCC('u','8',' ',' '):
1227 case VLC_FOURCC('s','8',' ',' '):
1230 case VLC_FOURCC('u','1','6','l'):
1231 case VLC_FOURCC('s','1','6','l'):
1232 case VLC_FOURCC('u','1','6','b'):
1233 case VLC_FOURCC('s','1','6','b'):
1236 case VLC_FOURCC('u','2','4','l'):
1237 case VLC_FOURCC('s','2','4','l'):
1238 case VLC_FOURCC('u','2','4','b'):
1239 case VLC_FOURCC('s','2','4','b'):
1242 case VLC_FOURCC('u','3','2','l'):
1243 case VLC_FOURCC('s','3','2','l'):
1244 case VLC_FOURCC('u','3','2','b'):
1245 case VLC_FOURCC('s','3','2','b'):
1246 case VLC_FOURCC('f','l','3','2'):
1247 case VLC_FOURCC('f','i','3','2'):
1250 case VLC_FOURCC('f','l','6','4'):
1257 static block_t *transcode_audio_alloc (filter_t *filter, int size)
1259 return block_New (filter, size);
1262 static filter_t *transcode_audio_filter_new( sout_stream_t *p_stream,
1263 sout_stream_id_t *id,
1264 es_format_t *p_fmt_in,
1265 es_format_t *p_fmt_out,
1268 sout_stream_sys_t *p_sys = p_stream->p_sys;
1269 filter_t *p_filter = vlc_object_create( p_stream, VLC_OBJECT_FILTER );
1271 vlc_object_attach( p_filter, p_stream );
1272 p_filter->pf_audio_buffer_new = transcode_audio_alloc;
1274 p_filter->fmt_in = *p_fmt_in;
1275 p_filter->fmt_out = *p_fmt_out;
1277 p_filter->p_cfg = p_sys->p_afilters_cfg[id->i_ufilter];
1279 p_filter->p_module = module_Need( p_filter, "audio filter2", psz_name,
1281 if( p_filter->p_module )
1283 p_filter->fmt_out.audio.i_bitspersample =
1284 audio_BitsPerSample( p_filter->fmt_out.i_codec );
1285 *p_fmt_in = p_filter->fmt_out;
1289 vlc_object_detach( p_filter );
1290 vlc_object_release( p_filter );
1297 static int transcode_audio_new( sout_stream_t *p_stream,
1298 sout_stream_id_t *id )
1300 sout_stream_sys_t *p_sys = p_stream->p_sys;
1301 es_format_t fmt_last;
1308 /* Initialization of decoder structures */
1309 id->p_decoder->fmt_out = id->p_decoder->fmt_in;
1310 id->p_decoder->fmt_out.i_extra = 0;
1311 id->p_decoder->fmt_out.p_extra = 0;
1312 id->p_decoder->pf_decode_audio = NULL;
1313 id->p_decoder->pf_aout_buffer_new = audio_new_buffer;
1314 id->p_decoder->pf_aout_buffer_del = audio_del_buffer;
1315 /* id->p_decoder->p_cfg = p_sys->p_audio_cfg; */
1317 id->p_decoder->p_module =
1318 module_Need( id->p_decoder, "decoder", "$codec", 0 );
1319 if( !id->p_decoder->p_module )
1321 msg_Err( p_stream, "cannot find decoder" );
1322 return VLC_EGENERIC;
1324 id->p_decoder->fmt_out.audio.i_bitspersample =
1325 audio_BitsPerSample( id->p_decoder->fmt_out.i_codec );
1326 fmt_last = id->p_decoder->fmt_out;
1327 /* Fix AAC SBR changing number of channels and sampling rate */
1328 if( !(id->p_decoder->fmt_in.i_codec == VLC_FOURCC('m','p','4','a') &&
1329 fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate &&
1330 fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels) )
1331 fmt_last.audio.i_rate = id->p_decoder->fmt_in.audio.i_rate;
1337 /* Initialization of encoder format structures */
1338 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1339 id->p_decoder->fmt_out.i_codec );
1340 id->p_encoder->fmt_in.audio.i_format = id->p_decoder->fmt_out.i_codec;
1342 if( ( id->p_encoder->fmt_out.i_codec == VLC_FOURCC('s','a','m','r') ) ||
1343 ( id->p_encoder->fmt_out.i_codec == VLC_FOURCC('s','a','w','b') ) )
1344 id->p_encoder->fmt_in.audio.i_rate = id->p_encoder->fmt_out.audio.i_rate;
1346 id->p_encoder->fmt_in.audio.i_rate = fmt_last.audio.i_rate;
1347 id->p_encoder->fmt_in.audio.i_physical_channels =
1348 id->p_encoder->fmt_out.audio.i_physical_channels;
1349 id->p_encoder->fmt_in.audio.i_original_channels =
1350 id->p_encoder->fmt_out.audio.i_original_channels;
1351 id->p_encoder->fmt_in.audio.i_channels =
1352 id->p_encoder->fmt_out.audio.i_channels;
1353 id->p_encoder->fmt_in.audio.i_bitspersample =
1354 audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1356 id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
1357 id->p_encoder->p_module =
1358 module_Need( id->p_encoder, "encoder", p_sys->psz_aenc, VLC_TRUE );
1359 if( !id->p_encoder->p_module )
1361 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_aenc );
1362 module_Unneed( id->p_decoder, id->p_decoder->p_module );
1363 id->p_decoder->p_module = NULL;
1364 return VLC_EGENERIC;
1366 id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
1367 id->p_encoder->fmt_in.audio.i_bitspersample =
1368 audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1370 /* Load conversion filters */
1371 if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels ||
1372 fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate )
1374 /* We'll have to go through fl32 first */
1375 es_format_t fmt_out = id->p_encoder->fmt_in;
1376 fmt_out.i_codec = fmt_out.audio.i_format = VLC_FOURCC('f','l','3','2');
1378 id->pp_filter[id->i_filter] =
1379 transcode_audio_filter_new( p_stream, id, &fmt_last, &fmt_out, NULL );
1381 if( id->pp_filter[id->i_filter] ) id->i_filter++;
1384 for( i = 0; i < TRANSCODE_FILTERS; i++ )
1386 if( (fmt_last.audio.i_channels !=
1387 id->p_encoder->fmt_in.audio.i_channels) ||
1388 (fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate) ||
1389 (fmt_last.i_codec != id->p_encoder->fmt_in.i_codec) )
1391 id->pp_filter[id->i_filter] =
1392 transcode_audio_filter_new( p_stream, id, &fmt_last,
1393 &id->p_encoder->fmt_in, NULL );
1395 if( id->pp_filter[id->i_filter] )
1402 /* Final checks to see if conversions were successful */
1403 if( fmt_last.i_codec != id->p_encoder->fmt_in.i_codec )
1405 msg_Err( p_stream, "no audio filter found (%4.4s->%4.4s)",
1406 (char *)&fmt_last.i_codec,
1407 (char *)&id->p_encoder->fmt_in.i_codec );
1408 transcode_audio_close( id );
1409 return VLC_EGENERIC;
1412 /* Load user specified audio filters now */
1413 for( i = 0; (i < p_sys->i_afilters) &&
1414 (id->i_ufilter < TRANSCODE_FILTERS); i++ )
1416 id->pp_ufilter[id->i_ufilter] =
1417 transcode_audio_filter_new( p_stream, id, &fmt_last,
1418 &id->p_encoder->fmt_in,
1419 p_sys->psz_afilters[i] );
1421 if( id->pp_ufilter[id->i_ufilter] )
1427 if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels )
1430 module_Unneed( id->p_encoder, id->p_encoder->p_module );
1431 id->p_encoder->p_module = NULL;
1433 /* This might work, but only if the encoder is restarted */
1434 id->p_encoder->fmt_in.audio.i_channels = fmt_last.audio.i_channels;
1435 id->p_encoder->fmt_out.audio.i_channels = fmt_last.audio.i_channels;
1437 id->p_encoder->fmt_in.audio.i_physical_channels =
1438 id->p_encoder->fmt_in.audio.i_original_channels =
1439 fmt_last.audio.i_physical_channels;
1440 id->p_encoder->fmt_out.audio.i_physical_channels =
1441 id->p_encoder->fmt_out.audio.i_original_channels =
1442 fmt_last.audio.i_physical_channels;
1444 msg_Dbg( p_stream, "number of audio channels for mixing changed, "
1445 "trying to reopen the encoder for mixing %i to %i channels",
1446 fmt_last.audio.i_channels,
1447 id->p_encoder->fmt_in.audio.i_channels );
1449 /* reload encoder */
1450 id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
1451 id->p_encoder->p_module =
1452 module_Need( id->p_encoder, "encoder", p_sys->psz_aenc, VLC_TRUE );
1453 if( !id->p_encoder->p_module )
1455 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_aenc );
1456 transcode_audio_close( id );
1457 return VLC_EGENERIC;
1459 id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
1460 id->p_encoder->fmt_in.audio.i_bitspersample =
1461 audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1463 msg_Err( p_stream, "no audio filter found for mixing from"
1464 " %i to %i channels", fmt_last.audio.i_channels,
1465 id->p_encoder->fmt_in.audio.i_channels );
1467 transcode_audio_close( id );
1468 return VLC_EGENERIC;
1472 if( fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate )
1474 msg_Err( p_stream, "no audio filter found for resampling from"
1475 " %iHz to %iHz", fmt_last.audio.i_rate,
1476 id->p_encoder->fmt_in.audio.i_rate );
1478 /* FIXME : this might work, but only if the encoder is restarted */
1479 id->p_encoder->fmt_in.audio.i_rate = fmt_last.audio.i_rate;
1480 id->p_encoder->fmt_out.audio.i_rate = fmt_last.audio.i_rate;
1482 transcode_audio_close( id );
1483 return VLC_EGENERIC;
1487 /* FIXME: Hack for mp3 transcoding support */
1488 if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC( 'm','p','3',' ' ) )
1489 id->p_encoder->fmt_out.i_codec = VLC_FOURCC( 'm','p','g','a' );
1494 static void transcode_audio_close( sout_stream_id_t *id )
1499 if( id->p_decoder->p_module )
1500 module_Unneed( id->p_decoder, id->p_decoder->p_module );
1501 id->p_decoder->p_module = NULL;
1504 if( id->p_encoder->p_module )
1505 module_Unneed( id->p_encoder, id->p_encoder->p_module );
1506 id->p_encoder->p_module = NULL;
1509 for( i = 0; i < id->i_filter; i++ )
1511 vlc_object_detach( id->pp_filter[i] );
1512 if( id->pp_filter[i]->p_module )
1513 module_Unneed( id->pp_filter[i], id->pp_filter[i]->p_module );
1514 vlc_object_release( id->pp_filter[i] );
1516 for( i = 0; i < id->i_ufilter; i++ )
1518 vlc_object_detach( id->pp_ufilter[i] );
1519 if( id->pp_ufilter[i]->p_module )
1520 module_Unneed( id->pp_ufilter[i], id->pp_ufilter[i]->p_module );
1521 vlc_object_release( id->pp_ufilter[i] );
1525 static int transcode_audio_process( sout_stream_t *p_stream,
1526 sout_stream_id_t *id,
1527 block_t *in, block_t **out )
1529 sout_stream_sys_t *p_sys = p_stream->p_sys;
1530 aout_buffer_t *p_audio_buf;
1531 block_t *p_block, *p_audio_block;
1535 while( (p_audio_buf = id->p_decoder->pf_decode_audio( id->p_decoder,
1538 sout_UpdateStatistic( p_stream->p_sout, SOUT_STATISTIC_DECODED_AUDIO, 1 );
1539 if( p_sys->b_master_sync )
1541 mtime_t i_dts = date_Get( &id->interpolated_pts ) + 1;
1542 if ( p_audio_buf->start_date - i_dts > MASTER_SYNC_MAX_DRIFT
1543 || p_audio_buf->start_date - i_dts < -MASTER_SYNC_MAX_DRIFT )
1545 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
1546 date_Set( &id->interpolated_pts, p_audio_buf->start_date );
1547 i_dts = p_audio_buf->start_date + 1;
1549 p_sys->i_master_drift = p_audio_buf->start_date - i_dts;
1550 date_Increment( &id->interpolated_pts, p_audio_buf->i_nb_samples );
1551 p_audio_buf->start_date -= p_sys->i_master_drift;
1552 p_audio_buf->end_date -= p_sys->i_master_drift;
1555 p_audio_block = p_audio_buf->p_sys;
1556 p_audio_block->i_buffer = p_audio_buf->i_nb_bytes;
1557 p_audio_block->i_dts = p_audio_block->i_pts =
1558 p_audio_buf->start_date;
1559 p_audio_block->i_length = p_audio_buf->end_date -
1560 p_audio_buf->start_date;
1561 p_audio_block->i_samples = p_audio_buf->i_nb_samples;
1563 /* Run filter chain */
1564 for( i = 0; i < id->i_filter; i++ )
1567 id->pp_filter[i]->pf_audio_filter( id->pp_filter[i],
1571 /* Run user specified filter chain */
1572 for( i = 0; i < id->i_ufilter; i++ )
1575 id->pp_ufilter[i]->pf_audio_filter( id->pp_ufilter[i],
1579 p_audio_buf->p_buffer = p_audio_block->p_buffer;
1580 p_audio_buf->i_nb_bytes = p_audio_block->i_buffer;
1581 p_audio_buf->i_nb_samples = p_audio_block->i_samples;
1582 p_audio_buf->start_date = p_audio_block->i_dts;
1583 p_audio_buf->end_date = p_audio_block->i_dts + p_audio_block->i_length;
1585 p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf );
1586 block_ChainAppend( out, p_block );
1587 block_Release( p_audio_block );
1588 free( p_audio_buf );
1594 static void audio_release_buffer( aout_buffer_t *p_buffer )
1596 if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
1600 static aout_buffer_t *audio_new_buffer( decoder_t *p_dec, int i_samples )
1602 aout_buffer_t *p_buffer;
1606 if( p_dec->fmt_out.audio.i_bitspersample )
1608 i_size = i_samples * p_dec->fmt_out.audio.i_bitspersample / 8 *
1609 p_dec->fmt_out.audio.i_channels;
1611 else if( p_dec->fmt_out.audio.i_bytes_per_frame &&
1612 p_dec->fmt_out.audio.i_frame_length )
1614 i_size = i_samples * p_dec->fmt_out.audio.i_bytes_per_frame /
1615 p_dec->fmt_out.audio.i_frame_length;
1619 i_size = i_samples * 4 * p_dec->fmt_out.audio.i_channels;
1622 p_buffer = malloc( sizeof(aout_buffer_t) );
1623 if( !p_buffer ) return NULL;
1624 p_buffer->b_discontinuity = VLC_FALSE;
1625 p_buffer->pf_release = audio_release_buffer;
1626 p_buffer->p_sys = p_block = block_New( p_dec, i_size );
1628 p_buffer->p_buffer = p_block->p_buffer;
1629 p_buffer->i_size = p_buffer->i_nb_bytes = p_block->i_buffer;
1630 p_buffer->i_nb_samples = i_samples;
1631 p_block->i_samples = i_samples;
1636 static void audio_del_buffer( decoder_t *p_dec, aout_buffer_t *p_buffer )
1639 if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
1647 static filter_t *transcode_video_filter_new( sout_stream_t *p_stream,
1648 es_format_t *p_fmt_in,
1649 es_format_t *p_fmt_out,
1650 config_chain_t *p_cfg,
1651 const char *psz_name )
1653 sout_stream_sys_t *p_sys = p_stream->p_sys;
1657 if( !p_stream || !p_fmt_in || !p_fmt_out ) return NULL;
1659 p_filter = vlc_object_create( p_stream, VLC_OBJECT_FILTER );
1660 vlc_object_attach( p_filter, p_stream );
1662 p_filter->pf_vout_buffer_new = video_new_buffer_filter;
1663 p_filter->pf_vout_buffer_del = video_del_buffer_filter;
1665 es_format_Copy( &p_filter->fmt_in, p_fmt_in );
1666 es_format_Copy( &p_filter->fmt_out, p_fmt_out );
1667 p_filter->p_cfg = p_cfg;
1669 p_filter->p_module = module_Need( p_filter, "video filter2",
1670 psz_name, VLC_TRUE );
1671 if( !p_filter->p_module )
1673 msg_Dbg( p_stream, "no video filter found" );
1674 vlc_object_detach( p_filter );
1675 vlc_object_release( p_filter );
1679 p_filter->p_owner = malloc( sizeof(filter_owner_sys_t) );
1680 if( !p_filter->p_owner )
1682 module_Unneed( p_filter,p_filter->p_module );
1683 vlc_object_detach( p_filter );
1684 vlc_object_release( p_filter );
1688 for( i = 0; i < PICTURE_RING_SIZE; i++ )
1689 p_filter->p_owner->pp_pics[i] = 0;
1690 p_filter->p_owner->p_sys = p_sys;
1695 static void transcode_video_filter_close( sout_stream_t *p_stream,
1696 filter_t *p_filter )
1700 if( !p_stream || !p_filter ) return;
1702 vlc_object_detach( p_filter );
1703 if( p_filter->p_module )
1704 module_Unneed( p_filter, p_filter->p_module );
1706 /* Clean-up pictures ring buffer */
1707 for( j = 0; j < PICTURE_RING_SIZE; j++ )
1709 if( p_filter->p_owner->pp_pics[j] )
1710 video_del_buffer( VLC_OBJECT(p_filter),
1711 p_filter->p_owner->pp_pics[j] );
1713 free( p_filter->p_owner );
1714 vlc_object_release( p_filter );
1718 static int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_t *id )
1720 sout_stream_sys_t *p_sys = p_stream->p_sys;
1724 * Initialization of decoder structures
1726 id->p_decoder->fmt_out = id->p_decoder->fmt_in;
1727 id->p_decoder->fmt_out.i_extra = 0;
1728 id->p_decoder->fmt_out.p_extra = 0;
1729 id->p_decoder->pf_decode_video = NULL;
1730 id->p_decoder->pf_get_cc = NULL;
1731 id->p_decoder->pf_get_cc = 0;
1732 id->p_decoder->pf_vout_buffer_new = video_new_buffer_decoder;
1733 id->p_decoder->pf_vout_buffer_del = video_del_buffer_decoder;
1734 id->p_decoder->pf_picture_link = video_link_picture_decoder;
1735 id->p_decoder->pf_picture_unlink = video_unlink_picture_decoder;
1736 id->p_decoder->p_owner = malloc( sizeof(decoder_owner_sys_t) );
1737 for( i = 0; i < PICTURE_RING_SIZE; i++ )
1738 id->p_decoder->p_owner->pp_pics[i] = 0;
1739 id->p_decoder->p_owner->p_sys = p_sys;
1740 /* id->p_decoder->p_cfg = p_sys->p_video_cfg; */
1742 id->p_decoder->p_module =
1743 module_Need( id->p_decoder, "decoder", "$codec", 0 );
1745 if( !id->p_decoder->p_module )
1747 msg_Err( p_stream, "cannot find decoder" );
1748 return VLC_EGENERIC;
1753 * Because some info about the decoded input will only be available
1754 * once the first frame is decoded, we actually only test the availability
1755 * of the encoder here.
1758 /* Initialization of encoder format structures */
1759 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1760 id->p_decoder->fmt_out.i_codec );
1761 id->p_encoder->fmt_in.video.i_chroma = id->p_decoder->fmt_out.i_codec;
1763 /* The dimensions will be set properly later on.
1764 * Just put sensible values so we can test an encoder is available. */
1765 id->p_encoder->fmt_in.video.i_width =
1766 id->p_encoder->fmt_out.video.i_width ?
1767 id->p_encoder->fmt_out.video.i_width :
1768 id->p_decoder->fmt_in.video.i_width ?
1769 id->p_decoder->fmt_in.video.i_width : 16;
1770 id->p_encoder->fmt_in.video.i_height =
1771 id->p_encoder->fmt_out.video.i_height ?
1772 id->p_encoder->fmt_out.video.i_height :
1773 id->p_decoder->fmt_in.video.i_height ?
1774 id->p_decoder->fmt_in.video.i_height : 16;
1775 id->p_encoder->fmt_in.video.i_frame_rate = 25;
1776 id->p_encoder->fmt_in.video.i_frame_rate_base = 1;
1778 id->p_encoder->i_threads = p_sys->i_threads;
1779 id->p_encoder->p_cfg = p_sys->p_video_cfg;
1781 id->p_encoder->p_module =
1782 module_Need( id->p_encoder, "encoder", p_sys->psz_venc, VLC_TRUE );
1783 if( !id->p_encoder->p_module )
1785 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_venc );
1786 module_Unneed( id->p_decoder, id->p_decoder->p_module );
1787 id->p_decoder->p_module = 0;
1788 return VLC_EGENERIC;
1791 /* Close the encoder.
1792 * We'll open it only when we have the first frame. */
1793 module_Unneed( id->p_encoder, id->p_encoder->p_module );
1794 if( id->p_encoder->fmt_out.p_extra )
1796 free( id->p_encoder->fmt_out.p_extra );
1797 id->p_encoder->fmt_out.p_extra = NULL;
1798 id->p_encoder->fmt_out.i_extra = 0;
1800 id->p_encoder->p_module = NULL;
1802 if( p_sys->i_threads >= 1 )
1804 int i_priority = p_sys->b_high_priority ? VLC_THREAD_PRIORITY_OUTPUT :
1805 VLC_THREAD_PRIORITY_VIDEO;
1806 p_sys->id_video = id;
1807 vlc_mutex_init( p_stream, &p_sys->lock_out );
1808 vlc_cond_init( p_stream, &p_sys->cond );
1809 memset( p_sys->pp_pics, 0, sizeof(p_sys->pp_pics) );
1810 p_sys->i_first_pic = 0;
1811 p_sys->i_last_pic = 0;
1812 p_sys->p_buffers = NULL;
1813 p_sys->b_die = p_sys->b_error = 0;
1814 if( vlc_thread_create( p_sys, "encoder", EncoderThread, i_priority,
1817 msg_Err( p_stream, "cannot spawn encoder thread" );
1818 module_Unneed( id->p_decoder, id->p_decoder->p_module );
1819 id->p_decoder->p_module = 0;
1820 return VLC_EGENERIC;
1827 static int transcode_video_encoder_open( sout_stream_t *p_stream,
1828 sout_stream_id_t *id )
1830 sout_stream_sys_t *p_sys = p_stream->p_sys;
1832 /* Calculate scaling, padding, cropping etc. */
1833 /* width/height of source */
1834 int i_src_width = id->p_decoder->fmt_out.video.i_width;
1835 int i_src_height = id->p_decoder->fmt_out.video.i_height;
1837 /* with/height scaling */
1838 float f_scale_width = 1;
1839 float f_scale_height = 1;
1841 /* width/height of output stream */
1846 float f_aspect = (float)id->p_decoder->fmt_out.video.i_aspect /
1849 msg_Dbg( p_stream, "decoder aspect is %i:%i",
1850 id->p_decoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
1852 /* Change f_aspect from source frame to source pixel */
1853 f_aspect = f_aspect * i_src_height / i_src_width;
1854 msg_Dbg( p_stream, "source pixel aspect is %f:1", f_aspect );
1856 /* width/height after cropping */
1857 p_sys->i_src_x_offset = p_sys->i_crop_left & ~1;
1858 p_sys->i_src_y_offset = p_sys->i_crop_top & ~1;
1859 p_sys->i_crop_width = i_src_width - ( p_sys->i_crop_left & ~1 ) -
1860 ( p_sys->i_crop_right & ~1 );
1861 p_sys->i_crop_height = i_src_height - ( p_sys->i_crop_top & ~1 ) -
1862 ( p_sys->i_crop_bottom & ~1 );
1864 /* Calculate scaling factor for specified parameters */
1865 if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1866 id->p_encoder->fmt_out.video.i_height <= 0 && p_sys->f_scale )
1868 /* Global scaling. Make sure width will remain a factor of 16 */
1871 int i_new_width = i_src_width * p_sys->f_scale;
1873 if( i_new_width % 16 <= 7 && i_new_width >= 16 )
1874 i_new_width -= i_new_width % 16;
1876 i_new_width += 16 - i_new_width % 16;
1878 f_real_scale = (float)( i_new_width ) / (float) i_src_width;
1880 i_new_height = __MAX( 16, i_src_height * (float)f_real_scale );
1882 f_scale_width = f_real_scale;
1883 f_scale_height = (float) i_new_height / (float) i_src_height;
1885 else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1886 id->p_encoder->fmt_out.video.i_height <= 0 )
1888 /* Only width specified */
1889 f_scale_width = (float)id->p_encoder->fmt_out.video.i_width /
1890 p_sys->i_crop_width;
1891 f_scale_height = f_scale_width;
1893 else if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1894 id->p_encoder->fmt_out.video.i_height > 0 )
1896 /* Only height specified */
1897 f_scale_height = (float)id->p_encoder->fmt_out.video.i_height /
1898 p_sys->i_crop_height;
1899 f_scale_width = f_scale_height;
1901 else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1902 id->p_encoder->fmt_out.video.i_height > 0 )
1904 /* Width and height specified */
1905 f_scale_width = (float)id->p_encoder->fmt_out.video.i_width
1906 / p_sys->i_crop_width;
1907 f_scale_height = (float)id->p_encoder->fmt_out.video.i_height
1908 / p_sys->i_crop_height;
1911 /* check maxwidth and maxheight
1912 * note: maxwidth and maxheight currently does not handle
1913 * canvas and padding, just scaling and cropping.
1915 if( p_sys->i_maxwidth && f_scale_width > (float)p_sys->i_maxwidth /
1916 p_sys->i_crop_width )
1918 f_scale_width = (float)p_sys->i_maxwidth / p_sys->i_crop_width;
1920 if( p_sys->i_maxheight && f_scale_height > (float)p_sys->i_maxheight /
1921 p_sys->i_crop_height )
1923 f_scale_height = (float)p_sys->i_maxheight / p_sys->i_crop_height;
1926 /* Change aspect ratio from source pixel to scaled pixel */
1927 f_aspect = f_aspect * f_scale_height / f_scale_width;
1928 msg_Dbg( p_stream, "scaled pixel aspect is %f:1", f_aspect );
1930 /* Correct scaling for target aspect ratio
1931 * Shrink video if necessary
1933 if ( p_sys->i_canvas_aspect > 0 )
1935 float f_target_aspect = (float)p_sys->i_canvas_aspect /
1938 if( p_sys->i_canvas_width > 0 && p_sys->i_canvas_height > 0)
1940 /* Calculate pixel aspect of canvas */
1941 f_target_aspect = f_target_aspect / p_sys->i_canvas_width *
1942 p_sys->i_canvas_height;
1944 if( f_target_aspect > f_aspect )
1946 /* Reduce width scale to increase aspect */
1947 f_scale_width = f_scale_width * f_aspect / f_target_aspect;
1951 /* Reduce height scale to decrease aspect */
1952 f_scale_height = f_scale_height * f_target_aspect / f_aspect;
1954 f_aspect = f_target_aspect;
1955 msg_Dbg( p_stream, "canvas scaled pixel aspect is %f:1", f_aspect );
1958 /* f_scale_width and f_scale_height are now final */
1959 /* Calculate width, height from scaling
1960 * Make sure its multiple of 2
1962 i_dst_width = 2 * (int)( p_sys->i_crop_width * f_scale_width / 2 + 0.5 );
1964 (int)( p_sys->i_crop_height * f_scale_height / 2 + 0.5 );
1966 p_sys->i_nopadd_width = i_dst_width;
1967 p_sys->i_nopadd_height = i_dst_height;
1968 p_sys->i_dst_x_offset = 0;
1969 p_sys->i_dst_y_offset = 0;
1971 /* Handle canvas and padding */
1972 if( p_sys->i_canvas_width <= 0 )
1974 /* No canvas width set, add explicit padding border */
1975 i_dst_width = p_sys->i_nopadd_width + ( p_sys->i_padd_left & ~1 ) +
1976 ( p_sys->i_padd_right & ~1 );
1977 p_sys->i_dst_x_offset = ( p_sys->i_padd_left & ~1 );
1981 /* Canvas set, check if we have to padd or crop */
1982 if( p_sys->i_canvas_width < p_sys->i_nopadd_width )
1984 /* need to crop more, but keep same scaling */
1985 int i_crop = 2 * (int)( ( p_sys->i_canvas_width & ~1 ) /
1986 f_scale_width / 2 + 0.5 );
1988 p_sys->i_src_x_offset += ( ( p_sys->i_crop_width - i_crop ) / 2 )
1990 p_sys->i_crop_width = i_crop;
1991 i_dst_width = p_sys->i_canvas_width & ~1;
1992 p_sys->i_nopadd_width = i_dst_width;
1994 else if( p_sys->i_canvas_width > p_sys->i_nopadd_width )
1997 i_dst_width = p_sys->i_canvas_width & ~1;
1998 p_sys->i_dst_x_offset = ( i_dst_width - p_sys->i_nopadd_width )/2;
1999 p_sys->i_dst_x_offset = p_sys->i_dst_x_offset & ~1;
2003 if( p_sys->i_canvas_height <= 0 )
2005 /* No canvas set, add padding border */
2006 i_dst_height = p_sys->i_nopadd_height + ( p_sys->i_padd_top & ~1 ) +
2007 ( p_sys->i_padd_bottom & ~1 );
2008 p_sys->i_dst_y_offset = ( p_sys->i_padd_top & ~1 );
2012 /* Canvas set, check if we have to padd or crop */
2013 if( p_sys->i_canvas_height < p_sys->i_nopadd_height )
2015 /* need to crop more, but keep same scaling */
2016 int i_crop = 2 * (int)( ( p_sys->i_canvas_height & ~1 ) /
2017 f_scale_height / 2 + 0.5 );
2019 p_sys->i_src_y_offset += ( ( p_sys->i_crop_height - i_crop ) / 2 )
2021 p_sys->i_crop_height = i_crop;
2022 i_dst_height = p_sys->i_canvas_height & ~1;
2023 p_sys->i_nopadd_height = i_dst_height;
2025 else if( p_sys->i_canvas_height > p_sys->i_nopadd_height )
2028 i_dst_height = p_sys->i_canvas_height & ~1;
2029 p_sys->i_dst_y_offset = ( i_dst_height - p_sys->i_nopadd_height )
2031 p_sys->i_dst_y_offset = p_sys->i_dst_y_offset & ~1;
2035 /* Change aspect ratio from scaled pixel to output frame */
2036 f_aspect = f_aspect * i_dst_width / i_dst_height;
2038 /* Store calculated values */
2039 id->p_encoder->fmt_out.video.i_width = i_dst_width;
2040 id->p_encoder->fmt_out.video.i_height = i_dst_height;
2042 id->p_encoder->fmt_in.video.i_width = i_dst_width;
2043 id->p_encoder->fmt_in.video.i_height = i_dst_height;
2045 msg_Dbg( p_stream, "source %ix%i, crop %ix%i, "
2046 "destination %ix%i, padding %ix%i",
2047 i_src_width, i_src_height,
2048 p_sys->i_crop_width, p_sys->i_crop_height,
2049 p_sys->i_nopadd_width, p_sys->i_nopadd_height,
2050 i_dst_width, i_dst_height
2053 /* Handle frame rate conversion */
2054 if( !id->p_encoder->fmt_out.video.i_frame_rate ||
2055 !id->p_encoder->fmt_out.video.i_frame_rate_base )
2057 if( id->p_decoder->fmt_out.video.i_frame_rate &&
2058 id->p_decoder->fmt_out.video.i_frame_rate_base )
2060 id->p_encoder->fmt_out.video.i_frame_rate =
2061 id->p_decoder->fmt_out.video.i_frame_rate;
2062 id->p_encoder->fmt_out.video.i_frame_rate_base =
2063 id->p_decoder->fmt_out.video.i_frame_rate_base;
2067 /* Pick a sensible default value */
2068 id->p_encoder->fmt_out.video.i_frame_rate = 25;
2069 id->p_encoder->fmt_out.video.i_frame_rate_base = 1;
2073 id->p_encoder->fmt_in.video.i_frame_rate =
2074 id->p_encoder->fmt_out.video.i_frame_rate;
2075 id->p_encoder->fmt_in.video.i_frame_rate_base =
2076 id->p_encoder->fmt_out.video.i_frame_rate_base;
2078 date_Init( &id->interpolated_pts,
2079 id->p_encoder->fmt_out.video.i_frame_rate,
2080 id->p_encoder->fmt_out.video.i_frame_rate_base );
2082 /* Check whether a particular aspect ratio was requested */
2083 if( !id->p_encoder->fmt_out.video.i_aspect )
2085 id->p_encoder->fmt_out.video.i_aspect = (int)( f_aspect * VOUT_ASPECT_FACTOR + 0.5 );
2087 id->p_encoder->fmt_in.video.i_aspect =
2088 id->p_encoder->fmt_out.video.i_aspect;
2090 msg_Dbg( p_stream, "encoder aspect is %i:%i", id->p_encoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
2092 id->p_encoder->p_module =
2093 module_Need( id->p_encoder, "encoder", p_sys->psz_venc, VLC_TRUE );
2094 if( !id->p_encoder->p_module )
2096 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_venc );
2097 return VLC_EGENERIC;
2100 id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
2102 /* Hack for mp2v/mp1v transcoding support */
2103 if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','1','v') ||
2104 id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','2','v') )
2106 id->p_encoder->fmt_out.i_codec = VLC_FOURCC('m','p','g','v');
2109 id->id = p_stream->p_sys->p_out->pf_add( p_stream->p_sys->p_out,
2110 &id->p_encoder->fmt_out );
2113 msg_Err( p_stream, "cannot add this stream" );
2114 return VLC_EGENERIC;
2120 static void transcode_video_close( sout_stream_t *p_stream,
2121 sout_stream_id_t *id )
2125 if( p_stream->p_sys->i_threads >= 1 )
2127 vlc_mutex_lock( &p_stream->p_sys->lock_out );
2128 vlc_object_kill( p_stream->p_sys );
2129 vlc_cond_signal( &p_stream->p_sys->cond );
2130 vlc_mutex_unlock( &p_stream->p_sys->lock_out );
2131 vlc_thread_join( p_stream->p_sys );
2132 vlc_mutex_destroy( &p_stream->p_sys->lock_out );
2133 vlc_cond_destroy( &p_stream->p_sys->cond );
2137 if( id->p_decoder->p_module )
2138 module_Unneed( id->p_decoder, id->p_decoder->p_module );
2140 if( id->p_decoder->p_owner )
2142 /* Clean-up pictures ring buffer */
2143 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2145 if( id->p_decoder->p_owner->pp_pics[i] )
2146 video_del_buffer( VLC_OBJECT(id->p_decoder),
2147 id->p_decoder->p_owner->pp_pics[i] );
2149 free( id->p_decoder->p_owner );
2153 if( id->p_encoder->p_module )
2154 module_Unneed( id->p_encoder, id->p_encoder->p_module );
2157 for( i = 0; i < id->i_filter; i++ )
2159 transcode_video_filter_close( p_stream, id->pp_filter[i] );
2160 id->pp_filter[i] = NULL;
2164 for( i = 0; i < id->i_ufilter; i++ )
2166 transcode_video_filter_close( p_stream, id->pp_ufilter[i] );
2167 id->pp_ufilter[i] = NULL;
2172 static int transcode_video_process( sout_stream_t *p_stream,
2173 sout_stream_id_t *id,
2174 block_t *in, block_t **out )
2176 sout_stream_sys_t *p_sys = p_stream->p_sys;
2177 int i_duplicate = 1, i;
2178 picture_t *p_pic, *p_pic2 = NULL;
2181 while( (p_pic = id->p_decoder->pf_decode_video( id->p_decoder, &in )) )
2183 subpicture_t *p_subpic = NULL;
2185 sout_UpdateStatistic( p_stream->p_sout, SOUT_STATISTIC_DECODED_VIDEO, 1 );
2187 if( p_stream->p_sout->i_out_pace_nocontrol && p_sys->b_hurry_up )
2189 mtime_t current_date = mdate();
2190 if( current_date + 50000 > p_pic->date )
2192 msg_Dbg( p_stream, "late picture skipped ("I64Fd")",
2193 current_date + 50000 - p_pic->date );
2194 p_pic->pf_release( p_pic );
2199 if( p_sys->b_master_sync )
2201 mtime_t i_video_drift;
2202 mtime_t i_master_drift = p_sys->i_master_drift;
2205 i_pts = date_Get( &id->interpolated_pts ) + 1;
2206 if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2207 || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2209 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2210 date_Set( &id->interpolated_pts, p_pic->date );
2211 i_pts = p_pic->date + 1;
2213 i_video_drift = p_pic->date - i_pts;
2216 /* Set the pts of the frame being encoded */
2217 p_pic->date = i_pts;
2219 if( i_video_drift < (i_master_drift - 50000) )
2222 msg_Dbg( p_stream, "dropping frame (%i)",
2223 (int)(i_video_drift - i_master_drift) );
2225 p_pic->pf_release( p_pic );
2228 else if( i_video_drift > (i_master_drift + 50000) )
2231 msg_Dbg( p_stream, "adding frame (%i)",
2232 (int)(i_video_drift - i_master_drift) );
2238 if( !id->p_encoder->p_module )
2240 if( transcode_video_encoder_open( p_stream, id ) != VLC_SUCCESS )
2242 p_pic->pf_release( p_pic );
2243 transcode_video_close( p_stream, id );
2244 id->b_transcode = VLC_FALSE;
2245 return VLC_EGENERIC;
2249 if( p_stream->p_sys->b_deinterlace )
2251 id->pp_filter[id->i_filter] =
2252 transcode_video_filter_new( p_stream,
2253 &id->p_decoder->fmt_out, &id->p_encoder->fmt_in,
2254 p_sys->p_deinterlace_cfg,
2255 p_sys->psz_deinterlace );
2257 if( id->pp_filter[id->i_filter] )
2261 #if (defined(HAVE_FFMPEG_SWSCALE_H) || defined(HAVE_LIBSWSCALE_TREE)) || defined(HAVE_LIBSWSCALE_SWSCALE_H)
2262 if( ( id->p_decoder->fmt_out.video.i_chroma !=
2263 id->p_encoder->fmt_in.video.i_chroma ) ||
2264 ( id->p_decoder->fmt_out.video.i_width !=
2265 id->p_encoder->fmt_out.video.i_width ) ||
2266 ( id->p_decoder->fmt_out.video.i_height !=
2267 id->p_encoder->fmt_out.video.i_height ) )
2269 id->pp_filter[id->i_filter] =
2270 transcode_video_filter_new( p_stream,
2271 &id->p_decoder->fmt_out, &id->p_encoder->fmt_in,
2273 if( !id->pp_filter[id->i_filter] )
2275 p_pic->pf_release( p_pic );
2276 transcode_video_close( p_stream, id );
2277 id->b_transcode = VLC_FALSE;
2278 return VLC_EGENERIC;
2283 /* we don't do chroma conversion or scaling in croppad */
2284 // es_format_t fmt_in, fmt_out;
2285 // es_format_Copy( &fmt_out, &id->p_encoder->fmt_in );
2286 // es_format_Copy( &fmt_in, &id->p_encoder->fmt_in );
2288 if( ( id->p_decoder->fmt_out.video.i_chroma ==
2289 id->p_encoder->fmt_in.video.i_chroma ) &&
2291 ( ( (int)id->p_decoder->fmt_out.video.i_width !=
2292 p_sys->i_crop_width ) ||
2293 ( p_sys->i_crop_width != p_sys->i_nopadd_width ) ||
2294 ( p_sys->i_nopadd_width !=
2295 (int)id->p_encoder->fmt_out.video.i_width ) ||
2297 ( (int)id->p_decoder->fmt_out.video.i_height !=
2298 p_sys->i_crop_height ) ||
2299 ( p_sys->i_crop_height != p_sys->i_nopadd_height ) ||
2300 ( p_sys->i_nopadd_height !=
2301 (int)id->p_encoder->fmt_out.video.i_height ) ) )
2303 id->pp_filter[id->i_filter] =
2304 transcode_video_filter_new( p_stream,
2305 &id->p_decoder->fmt_out, &id->p_encoder->fmt_in,
2307 if( id->pp_filter[id->i_filter] )
2309 /* Set crop and padding information */
2310 id->pp_filter[id->i_filter]->fmt_in.video.i_x_offset = p_sys->i_src_x_offset;
2311 id->pp_filter[id->i_filter]->fmt_in.video.i_y_offset = p_sys->i_src_y_offset;
2312 id->pp_filter[id->i_filter]->fmt_in.video.i_visible_width = p_sys->i_crop_width;
2313 id->pp_filter[id->i_filter]->fmt_in.video.i_visible_height = p_sys->i_crop_height;
2315 id->pp_filter[id->i_filter]->fmt_out.video.i_x_offset = p_sys->i_dst_x_offset;
2316 id->pp_filter[id->i_filter]->fmt_out.video.i_y_offset = p_sys->i_dst_y_offset;
2317 id->pp_filter[id->i_filter]->fmt_out.video.i_visible_width = p_sys->i_nopadd_width;
2318 id->pp_filter[id->i_filter]->fmt_out.video.i_visible_height = p_sys->i_nopadd_height;
2325 /* Check if we need a filter for chroma conversion or resizing */
2326 if( id->p_decoder->fmt_out.video.i_chroma !=
2327 id->p_encoder->fmt_in.video.i_chroma ||
2329 (int)id->p_decoder->fmt_out.video.i_width != p_sys->i_crop_width ||
2330 p_sys->i_crop_width != p_sys->i_nopadd_width ||
2331 p_sys->i_nopadd_width != (int)id->p_encoder->fmt_out.video.i_width ||
2333 (int)id->p_decoder->fmt_out.video.i_height != p_sys->i_crop_height ||
2334 p_sys->i_crop_height != p_sys->i_nopadd_height ||
2335 p_sys->i_nopadd_height != (int)id->p_encoder->fmt_out.video.i_height)
2337 id->pp_filter[id->i_filter] =
2338 transcode_video_filter_new( p_stream,
2339 &id->p_decoder->fmt_in, &id->p_encoder->fmt_in,
2340 NULL, "crop padd" );
2341 if( !id->pp_filter[id->i_filter] )
2343 p_pic->pf_release( p_pic );
2344 transcode_video_close( p_stream, id );
2345 id->b_transcode = VLC_FALSE;
2346 return VLC_EGENERIC;
2349 /* Set crop and padding information */
2350 id->pp_filter[id->i_filter]->fmt_in.video.i_x_offset = p_sys->i_src_x_offset;
2351 id->pp_filter[id->i_filter]->fmt_in.video.i_y_offset = p_sys->i_src_y_offset;
2352 id->pp_filter[id->i_filter]->fmt_in.video.i_visible_width = p_sys->i_crop_width;
2353 id->pp_filter[id->i_filter]->fmt_in.video.i_visible_height = p_sys->i_crop_height;
2355 id->pp_filter[id->i_filter]->fmt_out.video.i_x_offset = p_sys->i_dst_x_offset;
2356 id->pp_filter[id->i_filter]->fmt_out.video.i_y_offset = p_sys->i_dst_y_offset;
2357 id->pp_filter[id->i_filter]->fmt_out.video.i_visible_width = p_sys->i_nopadd_width;
2358 id->pp_filter[id->i_filter]->fmt_out.video.i_visible_height = p_sys->i_nopadd_height;
2363 for( i = 0; (i < p_sys->i_vfilters) && (id->i_ufilter < TRANSCODE_FILTERS); i++ )
2365 id->pp_ufilter[id->i_ufilter] =
2366 transcode_video_filter_new( p_stream,
2367 &id->p_decoder->fmt_out, &id->p_encoder->fmt_in,
2368 p_sys->p_vfilters_cfg[i], p_sys->psz_vfilters[i] );
2369 if( id->pp_ufilter[id->i_filter] )
2372 id->pp_ufilter[id->i_ufilter] = NULL;
2376 /* Run filter chain */
2377 for( i = 0; i < id->i_filter; i++ )
2379 p_pic = id->pp_filter[i]->pf_video_filter(id->pp_filter[i], p_pic);
2386 /* Check if we have a subpicture to overlay */
2389 p_subpic = spu_SortSubpictures( p_sys->p_spu, p_pic->date,
2390 VLC_FALSE /* Fixme: check if stream is paused */ );
2391 /* TODO: get another pic */
2394 /* Overlay subpicture */
2397 int i_scale_width, i_scale_height;
2398 video_format_t *p_fmt;
2400 i_scale_width = id->p_encoder->fmt_in.video.i_width * 1000 /
2401 id->p_decoder->fmt_out.video.i_width;
2402 i_scale_height = id->p_encoder->fmt_in.video.i_height * 1000 /
2403 id->p_decoder->fmt_out.video.i_height;
2405 if( p_pic->i_refcount && !id->i_filter )
2407 /* We can't modify the picture, we need to duplicate it */
2408 picture_t *p_tmp = video_new_buffer_decoder( id->p_decoder );
2411 vout_CopyPicture( p_stream, p_tmp, p_pic );
2412 p_pic->pf_release( p_pic );
2418 p_fmt = &id->pp_filter[id->i_filter -1]->fmt_out.video;
2420 p_fmt = &id->p_decoder->fmt_out.video;
2422 /* FIXME (shouldn't have to be done here) */
2423 p_fmt->i_sar_num = p_fmt->i_aspect *
2424 p_fmt->i_height / p_fmt->i_width;
2425 p_fmt->i_sar_den = VOUT_ASPECT_FACTOR;
2427 spu_RenderSubpictures( p_sys->p_spu, p_fmt, p_pic, p_pic, p_subpic,
2428 i_scale_width, i_scale_height );
2431 /* Run user specified filter chain */
2432 for( i = 0; i < id->i_ufilter; i++ )
2434 p_pic = id->pp_ufilter[i]->pf_video_filter( id->pp_ufilter[i],
2438 if( p_sys->i_threads == 0 )
2441 p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
2442 block_ChainAppend( out, p_block );
2445 if( p_sys->b_master_sync )
2447 mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
2448 if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2449 || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2451 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2452 date_Set( &id->interpolated_pts, p_pic->date );
2453 i_pts = p_pic->date + 1;
2455 date_Increment( &id->interpolated_pts, 1 );
2458 if( p_sys->b_master_sync && i_duplicate > 1 )
2460 mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
2461 if( (p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT)
2462 || ((p_pic->date - i_pts) < -MASTER_SYNC_MAX_DRIFT) )
2464 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2465 date_Set( &id->interpolated_pts, p_pic->date );
2466 i_pts = p_pic->date + 1;
2468 date_Increment( &id->interpolated_pts, 1 );
2470 if( p_sys->i_threads >= 1 )
2472 /* We can't modify the picture, we need to duplicate it */
2473 p_pic2 = video_new_buffer_decoder( id->p_decoder );
2474 if( p_pic2 != NULL )
2476 vout_CopyPicture( p_stream, p_pic2, p_pic );
2477 p_pic2->date = i_pts;
2483 p_pic->date = i_pts;
2484 p_block = id->p_encoder->pf_encode_video(id->p_encoder, p_pic);
2485 block_ChainAppend( out, p_block );
2489 if( p_sys->i_threads == 0 )
2491 p_pic->pf_release( p_pic );
2495 vlc_mutex_lock( &p_sys->lock_out );
2496 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic;
2497 p_sys->i_last_pic %= PICTURE_RING_SIZE;
2498 *out = p_sys->p_buffers;
2499 p_sys->p_buffers = NULL;
2500 if( p_pic2 != NULL )
2502 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic2;
2503 p_sys->i_last_pic %= PICTURE_RING_SIZE;
2505 vlc_cond_signal( &p_sys->cond );
2506 vlc_mutex_unlock( &p_sys->lock_out );
2513 static int EncoderThread( sout_stream_sys_t *p_sys )
2515 sout_stream_id_t *id = p_sys->id_video;
2518 while( !p_sys->b_die && !p_sys->b_error )
2522 vlc_mutex_lock( &p_sys->lock_out );
2523 while( p_sys->i_last_pic == p_sys->i_first_pic )
2525 vlc_cond_wait( &p_sys->cond, &p_sys->lock_out );
2526 if( p_sys->b_die || p_sys->b_error ) break;
2528 if( p_sys->b_die || p_sys->b_error )
2530 vlc_mutex_unlock( &p_sys->lock_out );
2534 p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2535 p_sys->i_first_pic %= PICTURE_RING_SIZE;
2536 vlc_mutex_unlock( &p_sys->lock_out );
2538 p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
2539 vlc_mutex_lock( &p_sys->lock_out );
2540 block_ChainAppend( &p_sys->p_buffers, p_block );
2542 vlc_mutex_unlock( &p_sys->lock_out );
2543 p_pic->pf_release( p_pic );
2546 while( p_sys->i_last_pic != p_sys->i_first_pic )
2548 p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2549 p_sys->i_first_pic %= PICTURE_RING_SIZE;
2550 p_pic->pf_release( p_pic );
2552 block_ChainRelease( p_sys->p_buffers );
2557 struct picture_sys_t
2559 vlc_object_t *p_owner;
2562 static void video_release_buffer( picture_t *p_pic )
2564 if( p_pic && !p_pic->i_refcount && p_pic->pf_release && p_pic->p_sys )
2566 video_del_buffer_decoder( (decoder_t *)p_pic->p_sys->p_owner, p_pic );
2568 else if( p_pic && p_pic->i_refcount > 0 ) p_pic->i_refcount--;
2571 static picture_t *video_new_buffer( vlc_object_t *p_this, picture_t **pp_ring,
2572 sout_stream_sys_t *p_sys )
2574 decoder_t *p_dec = (decoder_t *)p_this;
2578 /* Find an empty space in the picture ring buffer */
2579 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2581 if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
2583 pp_ring[i]->i_status = RESERVED_PICTURE;
2587 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2589 if( pp_ring[i] == 0 ) break;
2592 if( i == PICTURE_RING_SIZE && p_sys->i_threads >= 1 )
2594 int i_first_pic = p_sys->i_first_pic;
2596 if( p_sys->i_first_pic != p_sys->i_last_pic )
2598 /* Encoder still has stuff to encode, wait to clear-up the list */
2599 while( p_sys->i_first_pic == i_first_pic )
2603 /* Find an empty space in the picture ring buffer */
2604 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2606 if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
2608 pp_ring[i]->i_status = RESERVED_PICTURE;
2612 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2614 if( pp_ring[i] == 0 ) break;
2618 if( i == PICTURE_RING_SIZE )
2620 msg_Err( p_this, "decoder/filter is leaking pictures, "
2621 "resetting its ring buffer" );
2623 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2625 pp_ring[i]->pf_release( pp_ring[i] );
2631 p_pic = malloc( sizeof(picture_t) );
2632 if( !p_pic ) return NULL;
2633 p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
2634 vout_AllocatePicture( VLC_OBJECT(p_dec), p_pic,
2635 p_dec->fmt_out.video.i_chroma,
2636 p_dec->fmt_out.video.i_width,
2637 p_dec->fmt_out.video.i_height,
2638 p_dec->fmt_out.video.i_aspect );
2640 if( !p_pic->i_planes )
2646 p_pic->pf_release = video_release_buffer;
2647 p_pic->p_sys = malloc( sizeof(picture_sys_t) );
2654 p_pic->p_sys->p_owner = p_this;
2655 p_pic->i_status = RESERVED_PICTURE;
2661 static picture_t *video_new_buffer_decoder( decoder_t *p_dec )
2663 return video_new_buffer( VLC_OBJECT(p_dec),
2664 p_dec->p_owner->pp_pics, p_dec->p_owner->p_sys );
2667 static picture_t *video_new_buffer_filter( filter_t *p_filter )
2669 return video_new_buffer( VLC_OBJECT(p_filter),
2670 p_filter->p_owner->pp_pics,
2671 p_filter->p_owner->p_sys );
2674 static void video_del_buffer( vlc_object_t *p_this, picture_t *p_pic )
2679 free( p_pic->p_data_orig );
2680 free( p_pic->p_sys );
2685 static void video_del_buffer_decoder( decoder_t *p_decoder, picture_t *p_pic )
2687 VLC_UNUSED(p_decoder);
2688 p_pic->i_refcount = 0;
2689 p_pic->i_status = DESTROYED_PICTURE;
2692 static void video_del_buffer_filter( filter_t *p_filter, picture_t *p_pic )
2694 VLC_UNUSED(p_filter);
2695 p_pic->i_refcount = 0;
2696 p_pic->i_status = DESTROYED_PICTURE;
2699 static void video_link_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2702 p_pic->i_refcount++;
2705 static void video_unlink_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2708 video_release_buffer( p_pic );
2714 static subpicture_t *spu_new_buffer( decoder_t * );
2715 static void spu_del_buffer( decoder_t *, subpicture_t * );
2717 static int transcode_spu_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2719 sout_stream_sys_t *p_sys = p_stream->p_sys;
2725 /* Initialization of decoder structures */
2726 id->p_decoder->pf_decode_sub = NULL;
2727 id->p_decoder->pf_spu_buffer_new = spu_new_buffer;
2728 id->p_decoder->pf_spu_buffer_del = spu_del_buffer;
2729 id->p_decoder->p_owner = (decoder_owner_sys_t *)p_stream;
2730 /* id->p_decoder->p_cfg = p_sys->p_spu_cfg; */
2732 id->p_decoder->p_module =
2733 module_Need( id->p_decoder, "decoder", "$codec", 0 );
2735 if( !id->p_decoder->p_module )
2737 msg_Err( p_stream, "cannot find decoder" );
2738 return VLC_EGENERIC;
2741 if( !p_sys->b_soverlay )
2744 /* Initialization of encoder format structures */
2745 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
2746 id->p_decoder->fmt_in.i_codec );
2748 id->p_encoder->p_cfg = p_sys->p_spu_cfg;
2750 id->p_encoder->p_module =
2751 module_Need( id->p_encoder, "encoder", p_sys->psz_senc, VLC_TRUE );
2753 if( !id->p_encoder->p_module )
2755 module_Unneed( id->p_decoder, id->p_decoder->p_module );
2756 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_senc );
2757 return VLC_EGENERIC;
2763 p_sys->p_spu = spu_Create( p_stream );
2764 spu_Init( p_sys->p_spu );
2770 static void transcode_spu_close( sout_stream_id_t *id)
2773 if( id->p_decoder->p_module )
2774 module_Unneed( id->p_decoder, id->p_decoder->p_module );
2777 if( id->p_encoder->p_module )
2778 module_Unneed( id->p_encoder, id->p_encoder->p_module );
2781 static int transcode_spu_process( sout_stream_t *p_stream,
2782 sout_stream_id_t *id,
2783 block_t *in, block_t **out )
2785 sout_stream_sys_t *p_sys = p_stream->p_sys;
2786 subpicture_t *p_subpic;
2789 p_subpic = id->p_decoder->pf_decode_sub( id->p_decoder, &in );
2791 return VLC_EGENERIC;
2793 sout_UpdateStatistic( p_stream->p_sout, SOUT_STATISTIC_DECODED_SUBTITLE, 1 );
2795 if( p_sys->b_master_sync && p_sys->i_master_drift )
2797 p_subpic->i_start -= p_sys->i_master_drift;
2798 if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2801 if( p_sys->b_soverlay )
2803 spu_DisplaySubpicture( p_sys->p_spu, p_subpic );
2809 p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
2810 spu_del_buffer( id->p_decoder, p_subpic );
2813 block_ChainAppend( out, p_block );
2818 return VLC_EGENERIC;
2821 static subpicture_t *spu_new_buffer( decoder_t *p_dec )
2823 sout_stream_t *p_stream = (sout_stream_t *)p_dec->p_owner;
2824 return spu_CreateSubpicture( p_stream->p_sys->p_spu );
2827 static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_subpic )
2829 sout_stream_t *p_stream = (sout_stream_t *)p_dec->p_owner;
2830 spu_DestroySubpicture( p_stream->p_sys->p_spu, p_subpic );
2836 static int transcode_osd_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2838 sout_stream_sys_t *p_sys = p_stream->p_sys;
2840 id->p_decoder->fmt_in.i_cat = SPU_ES;
2841 id->p_encoder->fmt_out.psz_language = strdup( "osd" );
2843 if( p_sys->i_osdcodec != 0 || p_sys->psz_osdenc )
2845 msg_Dbg( p_stream, "creating osdmenu transcoding from fcc=`%4.4s' "
2846 "to fcc=`%4.4s'", (char*)&id->p_encoder->fmt_out.i_codec,
2847 (char*)&p_sys->i_osdcodec );
2849 /* Complete destination format */
2850 id->p_encoder->fmt_out.i_codec = p_sys->i_osdcodec;
2853 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
2854 VLC_FOURCC('Y','U','V','A') );
2855 id->p_encoder->fmt_in.psz_language = strdup( "osd" );
2857 id->p_encoder->p_cfg = p_sys->p_osd_cfg;
2859 id->p_encoder->p_module =
2860 module_Need( id->p_encoder, "encoder", p_sys->psz_osdenc, VLC_TRUE );
2862 if( !id->p_encoder->p_module )
2864 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_osdenc );
2868 /* open output stream */
2869 id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
2870 id->b_transcode = VLC_TRUE;
2872 if( !id->id ) goto error;
2876 msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
2877 (char*)&id->p_decoder->fmt_out.i_codec );
2878 id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_decoder->fmt_out );
2879 id->b_transcode = VLC_FALSE;
2881 if( !id->id ) goto error;
2886 p_sys->p_spu = spu_Create( p_stream );
2887 spu_Init( p_sys->p_spu );
2893 msg_Err( p_stream, "starting osd encoding thread failed" );
2894 if( id->p_encoder->p_module )
2895 module_Unneed( id->p_encoder, id->p_encoder->p_module );
2896 p_sys->b_osd = VLC_FALSE;
2897 return VLC_EGENERIC;
2900 static void transcode_osd_close( sout_stream_t *p_stream, sout_stream_id_t *id)
2902 sout_stream_sys_t *p_sys = p_stream->p_sys;
2905 if( p_sys->b_osd && id )
2907 if( id->p_encoder->p_module )
2908 module_Unneed( id->p_encoder, id->p_encoder->p_module );
2910 p_sys->b_osd = VLC_FALSE;
2913 static int transcode_osd_process( sout_stream_t *p_stream,
2914 sout_stream_id_t *id,
2915 block_t *in, block_t **out )
2917 sout_stream_sys_t *p_sys = p_stream->p_sys;
2918 subpicture_t *p_subpic = NULL;
2920 /* Check if we have a subpicture to send */
2921 if( p_sys->p_spu && in->i_dts > 0)
2923 p_subpic = spu_SortSubpictures( p_sys->p_spu, in->i_dts, VLC_FALSE );
2927 msg_Warn( p_stream, "spu channel not initialized, doing it now" );
2930 p_sys->p_spu = spu_Create( p_stream );
2931 spu_Init( p_sys->p_spu );
2937 block_t *p_block = NULL;
2939 if( p_sys->b_master_sync && p_sys->i_master_drift )
2941 p_subpic->i_start -= p_sys->i_master_drift;
2942 if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2945 p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
2946 spu_DestroySubpicture( p_sys->p_spu, p_subpic );
2949 p_block->i_dts = p_block->i_pts = in->i_dts;
2950 block_ChainAppend( out, p_block );
2954 return VLC_EGENERIC;