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, false );
204 add_string( SOUT_CFG_PREFIX "vcodec", NULL, NULL, VCODEC_TEXT,
205 VCODEC_LONGTEXT, false );
206 add_integer( SOUT_CFG_PREFIX "vb", 800 * 1000, NULL, VB_TEXT,
207 VB_LONGTEXT, false );
208 add_float( SOUT_CFG_PREFIX "scale", 1, NULL, SCALE_TEXT,
209 SCALE_LONGTEXT, false );
210 add_float( SOUT_CFG_PREFIX "fps", 0, NULL, FPS_TEXT,
211 FPS_LONGTEXT, false );
212 add_bool( SOUT_CFG_PREFIX "hurry-up", true, NULL, HURRYUP_TEXT,
213 HURRYUP_LONGTEXT, false );
214 add_bool( SOUT_CFG_PREFIX "deinterlace", 0, NULL, DEINTERLACE_TEXT,
215 DEINTERLACE_LONGTEXT, 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, true );
222 add_integer( SOUT_CFG_PREFIX "height", 0, NULL, HEIGHT_TEXT,
223 HEIGHT_LONGTEXT, true );
224 add_integer( SOUT_CFG_PREFIX "maxwidth", 0, NULL, MAXWIDTH_TEXT,
225 MAXWIDTH_LONGTEXT, true );
226 add_integer( SOUT_CFG_PREFIX "maxheight", 0, NULL, MAXHEIGHT_TEXT,
227 MAXHEIGHT_LONGTEXT, true );
228 add_module_list( SOUT_CFG_PREFIX "vfilter", "video filter2",
230 VFILTER_TEXT, VFILTER_LONGTEXT, false );
232 add_integer( SOUT_CFG_PREFIX "croptop", 0, NULL, CROPTOP_TEXT,
233 CROPTOP_LONGTEXT, true );
234 add_integer( SOUT_CFG_PREFIX "cropleft", 0, NULL, CROPLEFT_TEXT,
235 CROPLEFT_LONGTEXT, true );
236 add_integer( SOUT_CFG_PREFIX "cropbottom", 0, NULL, CROPBOTTOM_TEXT,
237 CROPBOTTOM_LONGTEXT, true );
238 add_integer( SOUT_CFG_PREFIX "cropright", 0, NULL, CROPRIGHT_TEXT,
239 CROPRIGHT_LONGTEXT, true );
241 add_integer( SOUT_CFG_PREFIX "paddtop", 0, NULL, PADDTOP_TEXT,
242 PADDTOP_LONGTEXT, true );
243 add_integer( SOUT_CFG_PREFIX "paddleft", 0, NULL, PADDLEFT_TEXT,
244 PADDLEFT_LONGTEXT, true );
245 add_integer( SOUT_CFG_PREFIX "paddbottom", 0, NULL, PADDBOTTOM_TEXT,
246 PADDBOTTOM_LONGTEXT, true );
247 add_integer( SOUT_CFG_PREFIX "paddright", 0, NULL, PADDRIGHT_TEXT,
248 PADDRIGHT_LONGTEXT, true );
250 add_integer( SOUT_CFG_PREFIX "canvas-width", 0, NULL, CANVAS_WIDTH_TEXT,
251 CANVAS_WIDTH_LONGTEXT, true );
252 add_integer( SOUT_CFG_PREFIX "canvas-height", 0, NULL, CANVAS_HEIGHT_TEXT,
253 CANVAS_HEIGHT_LONGTEXT, true );
254 add_string( SOUT_CFG_PREFIX "canvas-aspect", NULL, NULL, CANVAS_ASPECT_TEXT,
255 CANVAS_ASPECT_LONGTEXT, false );
257 set_section( N_("Audio"), NULL );
258 add_string( SOUT_CFG_PREFIX "aenc", NULL, NULL, AENC_TEXT,
259 AENC_LONGTEXT, false );
260 add_string( SOUT_CFG_PREFIX "acodec", NULL, NULL, ACODEC_TEXT,
261 ACODEC_LONGTEXT, false );
262 add_integer( SOUT_CFG_PREFIX "ab", 0, NULL, AB_TEXT,
263 AB_LONGTEXT, false );
264 add_integer( SOUT_CFG_PREFIX "channels", 0, NULL, ACHANS_TEXT,
265 ACHANS_LONGTEXT, false );
266 add_integer( SOUT_CFG_PREFIX "samplerate", 0, NULL, ARATE_TEXT,
267 ARATE_LONGTEXT, true );
268 add_bool( SOUT_CFG_PREFIX "audio-sync", 0, NULL, ASYNC_TEXT,
269 ASYNC_LONGTEXT, false );
270 add_module_list( SOUT_CFG_PREFIX "afilter", "audio filter2",
272 AFILTER_TEXT, AFILTER_LONGTEXT, false );
274 set_section( N_("Overlays/Subtitles"), NULL );
275 add_string( SOUT_CFG_PREFIX "senc", NULL, NULL, SENC_TEXT,
276 SENC_LONGTEXT, false );
277 add_string( SOUT_CFG_PREFIX "scodec", NULL, NULL, SCODEC_TEXT,
278 SCODEC_LONGTEXT, false );
279 add_bool( SOUT_CFG_PREFIX "soverlay", 0, NULL, SCODEC_TEXT,
280 SCODEC_LONGTEXT, false );
281 add_module_list( SOUT_CFG_PREFIX "sfilter", "video filter",
283 SFILTER_TEXT, SFILTER_LONGTEXT, false );
285 set_section( N_("On Screen Display"), NULL );
286 add_bool( SOUT_CFG_PREFIX "osd", 0, NULL, OSD_TEXT,
287 OSD_LONGTEXT, false );
289 set_section( N_("Miscellaneous"), NULL );
290 add_integer( SOUT_CFG_PREFIX "threads", 0, NULL, THREADS_TEXT,
291 THREADS_LONGTEXT, 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;
397 char *psz_deinterlace;
398 config_chain_t *p_deinterlace_cfg;
400 bool b_high_priority;
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) */
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 bool b_osd; /* true when osd es is registered */
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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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, 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, 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] );
1518 for( i = 0; i < id->i_ufilter; i++ )
1520 vlc_object_detach( id->pp_ufilter[i] );
1521 if( id->pp_ufilter[i]->p_module )
1522 module_Unneed( id->pp_ufilter[i], id->pp_ufilter[i]->p_module );
1523 vlc_object_release( id->pp_ufilter[i] );
1528 static int transcode_audio_process( sout_stream_t *p_stream,
1529 sout_stream_id_t *id,
1530 block_t *in, block_t **out )
1532 sout_stream_sys_t *p_sys = p_stream->p_sys;
1533 aout_buffer_t *p_audio_buf;
1534 block_t *p_block, *p_audio_block;
1538 while( (p_audio_buf = id->p_decoder->pf_decode_audio( id->p_decoder,
1541 sout_UpdateStatistic( p_stream->p_sout, SOUT_STATISTIC_DECODED_AUDIO, 1 );
1542 if( p_sys->b_master_sync )
1544 mtime_t i_dts = date_Get( &id->interpolated_pts ) + 1;
1545 if ( p_audio_buf->start_date - i_dts > MASTER_SYNC_MAX_DRIFT
1546 || p_audio_buf->start_date - i_dts < -MASTER_SYNC_MAX_DRIFT )
1548 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
1549 date_Set( &id->interpolated_pts, p_audio_buf->start_date );
1550 i_dts = p_audio_buf->start_date + 1;
1552 p_sys->i_master_drift = p_audio_buf->start_date - i_dts;
1553 date_Increment( &id->interpolated_pts, p_audio_buf->i_nb_samples );
1554 p_audio_buf->start_date -= p_sys->i_master_drift;
1555 p_audio_buf->end_date -= p_sys->i_master_drift;
1558 p_audio_block = p_audio_buf->p_sys;
1559 p_audio_block->i_buffer = p_audio_buf->i_nb_bytes;
1560 p_audio_block->i_dts = p_audio_block->i_pts =
1561 p_audio_buf->start_date;
1562 p_audio_block->i_length = p_audio_buf->end_date -
1563 p_audio_buf->start_date;
1564 p_audio_block->i_samples = p_audio_buf->i_nb_samples;
1566 /* Run filter chain */
1567 for( i = 0; i < id->i_filter; i++ )
1570 id->pp_filter[i]->pf_audio_filter( id->pp_filter[i],
1574 /* Run user specified filter chain */
1575 for( i = 0; i < id->i_ufilter; i++ )
1578 id->pp_ufilter[i]->pf_audio_filter( id->pp_ufilter[i],
1582 p_audio_buf->p_buffer = p_audio_block->p_buffer;
1583 p_audio_buf->i_nb_bytes = p_audio_block->i_buffer;
1584 p_audio_buf->i_nb_samples = p_audio_block->i_samples;
1585 p_audio_buf->start_date = p_audio_block->i_dts;
1586 p_audio_buf->end_date = p_audio_block->i_dts + p_audio_block->i_length;
1588 p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf );
1589 block_ChainAppend( out, p_block );
1590 block_Release( p_audio_block );
1591 free( p_audio_buf );
1597 static void audio_release_buffer( aout_buffer_t *p_buffer )
1599 if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
1603 static aout_buffer_t *audio_new_buffer( decoder_t *p_dec, int i_samples )
1605 aout_buffer_t *p_buffer;
1609 if( p_dec->fmt_out.audio.i_bitspersample )
1611 i_size = i_samples * p_dec->fmt_out.audio.i_bitspersample / 8 *
1612 p_dec->fmt_out.audio.i_channels;
1614 else if( p_dec->fmt_out.audio.i_bytes_per_frame &&
1615 p_dec->fmt_out.audio.i_frame_length )
1617 i_size = i_samples * p_dec->fmt_out.audio.i_bytes_per_frame /
1618 p_dec->fmt_out.audio.i_frame_length;
1622 i_size = i_samples * 4 * p_dec->fmt_out.audio.i_channels;
1625 p_buffer = malloc( sizeof(aout_buffer_t) );
1626 if( !p_buffer ) return NULL;
1627 p_buffer->b_discontinuity = false;
1628 p_buffer->pf_release = audio_release_buffer;
1629 p_buffer->p_sys = p_block = block_New( p_dec, i_size );
1631 p_buffer->p_buffer = p_block->p_buffer;
1632 p_buffer->i_size = p_buffer->i_nb_bytes = p_block->i_buffer;
1633 p_buffer->i_nb_samples = i_samples;
1634 p_block->i_samples = i_samples;
1639 static void audio_del_buffer( decoder_t *p_dec, aout_buffer_t *p_buffer )
1642 if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
1650 static filter_t *transcode_video_filter_new( sout_stream_t *p_stream,
1651 es_format_t *p_fmt_in,
1652 es_format_t *p_fmt_out,
1653 config_chain_t *p_cfg,
1654 const char *psz_name )
1656 sout_stream_sys_t *p_sys = p_stream->p_sys;
1660 if( !p_stream || !p_fmt_in || !p_fmt_out ) return NULL;
1662 p_filter = vlc_object_create( p_stream, VLC_OBJECT_FILTER );
1663 vlc_object_attach( p_filter, p_stream );
1665 p_filter->pf_vout_buffer_new = video_new_buffer_filter;
1666 p_filter->pf_vout_buffer_del = video_del_buffer_filter;
1668 es_format_Copy( &p_filter->fmt_in, p_fmt_in );
1669 es_format_Copy( &p_filter->fmt_out, p_fmt_out );
1670 p_filter->p_cfg = p_cfg;
1672 p_filter->p_module = module_Need( p_filter, "video filter2",
1674 if( !p_filter->p_module )
1676 msg_Dbg( p_stream, "no video filter found" );
1677 vlc_object_detach( p_filter );
1678 vlc_object_release( p_filter );
1682 p_filter->p_owner = malloc( sizeof(filter_owner_sys_t) );
1683 if( !p_filter->p_owner )
1685 module_Unneed( p_filter,p_filter->p_module );
1686 vlc_object_detach( p_filter );
1687 vlc_object_release( p_filter );
1691 for( i = 0; i < PICTURE_RING_SIZE; i++ )
1692 p_filter->p_owner->pp_pics[i] = 0;
1693 p_filter->p_owner->p_sys = p_sys;
1698 static void transcode_video_filter_close( sout_stream_t *p_stream,
1699 filter_t *p_filter )
1703 if( !p_stream || !p_filter ) return;
1705 vlc_object_detach( p_filter );
1706 if( p_filter->p_module )
1707 module_Unneed( p_filter, p_filter->p_module );
1709 /* Clean-up pictures ring buffer */
1710 for( j = 0; j < PICTURE_RING_SIZE; j++ )
1712 if( p_filter->p_owner->pp_pics[j] )
1713 video_del_buffer( VLC_OBJECT(p_filter),
1714 p_filter->p_owner->pp_pics[j] );
1716 free( p_filter->p_owner );
1717 vlc_object_release( p_filter );
1721 static int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_t *id )
1723 sout_stream_sys_t *p_sys = p_stream->p_sys;
1727 * Initialization of decoder structures
1729 id->p_decoder->fmt_out = id->p_decoder->fmt_in;
1730 id->p_decoder->fmt_out.i_extra = 0;
1731 id->p_decoder->fmt_out.p_extra = 0;
1732 id->p_decoder->pf_decode_video = NULL;
1733 id->p_decoder->pf_get_cc = NULL;
1734 id->p_decoder->pf_get_cc = 0;
1735 id->p_decoder->pf_vout_buffer_new = video_new_buffer_decoder;
1736 id->p_decoder->pf_vout_buffer_del = video_del_buffer_decoder;
1737 id->p_decoder->pf_picture_link = video_link_picture_decoder;
1738 id->p_decoder->pf_picture_unlink = video_unlink_picture_decoder;
1739 id->p_decoder->p_owner = malloc( sizeof(decoder_owner_sys_t) );
1740 for( i = 0; i < PICTURE_RING_SIZE; i++ )
1741 id->p_decoder->p_owner->pp_pics[i] = 0;
1742 id->p_decoder->p_owner->p_sys = p_sys;
1743 /* id->p_decoder->p_cfg = p_sys->p_video_cfg; */
1745 id->p_decoder->p_module =
1746 module_Need( id->p_decoder, "decoder", "$codec", 0 );
1748 if( !id->p_decoder->p_module )
1750 msg_Err( p_stream, "cannot find decoder" );
1751 return VLC_EGENERIC;
1756 * Because some info about the decoded input will only be available
1757 * once the first frame is decoded, we actually only test the availability
1758 * of the encoder here.
1761 /* Initialization of encoder format structures */
1762 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1763 id->p_decoder->fmt_out.i_codec );
1764 id->p_encoder->fmt_in.video.i_chroma = id->p_decoder->fmt_out.i_codec;
1766 /* The dimensions will be set properly later on.
1767 * Just put sensible values so we can test an encoder is available. */
1768 id->p_encoder->fmt_in.video.i_width =
1769 id->p_encoder->fmt_out.video.i_width ?
1770 id->p_encoder->fmt_out.video.i_width :
1771 id->p_decoder->fmt_in.video.i_width ?
1772 id->p_decoder->fmt_in.video.i_width : 16;
1773 id->p_encoder->fmt_in.video.i_height =
1774 id->p_encoder->fmt_out.video.i_height ?
1775 id->p_encoder->fmt_out.video.i_height :
1776 id->p_decoder->fmt_in.video.i_height ?
1777 id->p_decoder->fmt_in.video.i_height : 16;
1778 id->p_encoder->fmt_in.video.i_frame_rate = 25;
1779 id->p_encoder->fmt_in.video.i_frame_rate_base = 1;
1781 id->p_encoder->i_threads = p_sys->i_threads;
1782 id->p_encoder->p_cfg = p_sys->p_video_cfg;
1784 id->p_encoder->p_module =
1785 module_Need( id->p_encoder, "encoder", p_sys->psz_venc, true );
1786 if( !id->p_encoder->p_module )
1788 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_venc );
1789 module_Unneed( id->p_decoder, id->p_decoder->p_module );
1790 id->p_decoder->p_module = 0;
1791 return VLC_EGENERIC;
1794 /* Close the encoder.
1795 * We'll open it only when we have the first frame. */
1796 module_Unneed( id->p_encoder, id->p_encoder->p_module );
1797 if( id->p_encoder->fmt_out.p_extra )
1799 free( id->p_encoder->fmt_out.p_extra );
1800 id->p_encoder->fmt_out.p_extra = NULL;
1801 id->p_encoder->fmt_out.i_extra = 0;
1803 id->p_encoder->p_module = NULL;
1805 if( p_sys->i_threads >= 1 )
1807 int i_priority = p_sys->b_high_priority ? VLC_THREAD_PRIORITY_OUTPUT :
1808 VLC_THREAD_PRIORITY_VIDEO;
1809 p_sys->id_video = id;
1810 vlc_mutex_init( p_stream, &p_sys->lock_out );
1811 vlc_cond_init( p_stream, &p_sys->cond );
1812 memset( p_sys->pp_pics, 0, sizeof(p_sys->pp_pics) );
1813 p_sys->i_first_pic = 0;
1814 p_sys->i_last_pic = 0;
1815 p_sys->p_buffers = NULL;
1816 p_sys->b_die = p_sys->b_error = 0;
1817 if( vlc_thread_create( p_sys, "encoder", EncoderThread, i_priority,
1820 msg_Err( p_stream, "cannot spawn encoder thread" );
1821 module_Unneed( id->p_decoder, id->p_decoder->p_module );
1822 id->p_decoder->p_module = 0;
1823 return VLC_EGENERIC;
1830 static int transcode_video_encoder_open( sout_stream_t *p_stream,
1831 sout_stream_id_t *id )
1833 sout_stream_sys_t *p_sys = p_stream->p_sys;
1835 /* Calculate scaling, padding, cropping etc. */
1836 /* width/height of source */
1837 int i_src_width = id->p_decoder->fmt_out.video.i_width;
1838 int i_src_height = id->p_decoder->fmt_out.video.i_height;
1840 /* with/height scaling */
1841 float f_scale_width = 1;
1842 float f_scale_height = 1;
1844 /* width/height of output stream */
1849 float f_aspect = (float)id->p_decoder->fmt_out.video.i_aspect /
1852 msg_Dbg( p_stream, "decoder aspect is %i:%i",
1853 id->p_decoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
1855 /* Change f_aspect from source frame to source pixel */
1856 f_aspect = f_aspect * i_src_height / i_src_width;
1857 msg_Dbg( p_stream, "source pixel aspect is %f:1", f_aspect );
1859 /* width/height after cropping */
1860 p_sys->i_src_x_offset = p_sys->i_crop_left & ~1;
1861 p_sys->i_src_y_offset = p_sys->i_crop_top & ~1;
1862 p_sys->i_crop_width = i_src_width - ( p_sys->i_crop_left & ~1 ) -
1863 ( p_sys->i_crop_right & ~1 );
1864 p_sys->i_crop_height = i_src_height - ( p_sys->i_crop_top & ~1 ) -
1865 ( p_sys->i_crop_bottom & ~1 );
1867 /* Calculate scaling factor for specified parameters */
1868 if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1869 id->p_encoder->fmt_out.video.i_height <= 0 && p_sys->f_scale )
1871 /* Global scaling. Make sure width will remain a factor of 16 */
1874 int i_new_width = i_src_width * p_sys->f_scale;
1876 if( i_new_width % 16 <= 7 && i_new_width >= 16 )
1877 i_new_width -= i_new_width % 16;
1879 i_new_width += 16 - i_new_width % 16;
1881 f_real_scale = (float)( i_new_width ) / (float) i_src_width;
1883 i_new_height = __MAX( 16, i_src_height * (float)f_real_scale );
1885 f_scale_width = f_real_scale;
1886 f_scale_height = (float) i_new_height / (float) i_src_height;
1888 else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1889 id->p_encoder->fmt_out.video.i_height <= 0 )
1891 /* Only width specified */
1892 f_scale_width = (float)id->p_encoder->fmt_out.video.i_width /
1893 p_sys->i_crop_width;
1894 f_scale_height = f_scale_width;
1896 else if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1897 id->p_encoder->fmt_out.video.i_height > 0 )
1899 /* Only height specified */
1900 f_scale_height = (float)id->p_encoder->fmt_out.video.i_height /
1901 p_sys->i_crop_height;
1902 f_scale_width = f_scale_height;
1904 else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1905 id->p_encoder->fmt_out.video.i_height > 0 )
1907 /* Width and height specified */
1908 f_scale_width = (float)id->p_encoder->fmt_out.video.i_width
1909 / p_sys->i_crop_width;
1910 f_scale_height = (float)id->p_encoder->fmt_out.video.i_height
1911 / p_sys->i_crop_height;
1914 /* check maxwidth and maxheight
1915 * note: maxwidth and maxheight currently does not handle
1916 * canvas and padding, just scaling and cropping.
1918 if( p_sys->i_maxwidth && f_scale_width > (float)p_sys->i_maxwidth /
1919 p_sys->i_crop_width )
1921 f_scale_width = (float)p_sys->i_maxwidth / p_sys->i_crop_width;
1923 if( p_sys->i_maxheight && f_scale_height > (float)p_sys->i_maxheight /
1924 p_sys->i_crop_height )
1926 f_scale_height = (float)p_sys->i_maxheight / p_sys->i_crop_height;
1929 /* Change aspect ratio from source pixel to scaled pixel */
1930 f_aspect = f_aspect * f_scale_height / f_scale_width;
1931 msg_Dbg( p_stream, "scaled pixel aspect is %f:1", f_aspect );
1933 /* Correct scaling for target aspect ratio
1934 * Shrink video if necessary
1936 if ( p_sys->i_canvas_aspect > 0 )
1938 float f_target_aspect = (float)p_sys->i_canvas_aspect /
1941 if( p_sys->i_canvas_width > 0 && p_sys->i_canvas_height > 0)
1943 /* Calculate pixel aspect of canvas */
1944 f_target_aspect = f_target_aspect / p_sys->i_canvas_width *
1945 p_sys->i_canvas_height;
1947 if( f_target_aspect > f_aspect )
1949 /* Reduce width scale to increase aspect */
1950 f_scale_width = f_scale_width * f_aspect / f_target_aspect;
1954 /* Reduce height scale to decrease aspect */
1955 f_scale_height = f_scale_height * f_target_aspect / f_aspect;
1957 f_aspect = f_target_aspect;
1958 msg_Dbg( p_stream, "canvas scaled pixel aspect is %f:1", f_aspect );
1961 /* f_scale_width and f_scale_height are now final */
1962 /* Calculate width, height from scaling
1963 * Make sure its multiple of 2
1965 i_dst_width = 2 * (int)( p_sys->i_crop_width * f_scale_width / 2 + 0.5 );
1967 (int)( p_sys->i_crop_height * f_scale_height / 2 + 0.5 );
1969 p_sys->i_nopadd_width = i_dst_width;
1970 p_sys->i_nopadd_height = i_dst_height;
1971 p_sys->i_dst_x_offset = 0;
1972 p_sys->i_dst_y_offset = 0;
1974 /* Handle canvas and padding */
1975 if( p_sys->i_canvas_width <= 0 )
1977 /* No canvas width set, add explicit padding border */
1978 i_dst_width = p_sys->i_nopadd_width + ( p_sys->i_padd_left & ~1 ) +
1979 ( p_sys->i_padd_right & ~1 );
1980 p_sys->i_dst_x_offset = ( p_sys->i_padd_left & ~1 );
1984 /* Canvas set, check if we have to padd or crop */
1985 if( p_sys->i_canvas_width < p_sys->i_nopadd_width )
1987 /* need to crop more, but keep same scaling */
1988 int i_crop = 2 * (int)( ( p_sys->i_canvas_width & ~1 ) /
1989 f_scale_width / 2 + 0.5 );
1991 p_sys->i_src_x_offset += ( ( p_sys->i_crop_width - i_crop ) / 2 )
1993 p_sys->i_crop_width = i_crop;
1994 i_dst_width = p_sys->i_canvas_width & ~1;
1995 p_sys->i_nopadd_width = i_dst_width;
1997 else if( p_sys->i_canvas_width > p_sys->i_nopadd_width )
2000 i_dst_width = p_sys->i_canvas_width & ~1;
2001 p_sys->i_dst_x_offset = ( i_dst_width - p_sys->i_nopadd_width )/2;
2002 p_sys->i_dst_x_offset = p_sys->i_dst_x_offset & ~1;
2006 if( p_sys->i_canvas_height <= 0 )
2008 /* No canvas set, add padding border */
2009 i_dst_height = p_sys->i_nopadd_height + ( p_sys->i_padd_top & ~1 ) +
2010 ( p_sys->i_padd_bottom & ~1 );
2011 p_sys->i_dst_y_offset = ( p_sys->i_padd_top & ~1 );
2015 /* Canvas set, check if we have to padd or crop */
2016 if( p_sys->i_canvas_height < p_sys->i_nopadd_height )
2018 /* need to crop more, but keep same scaling */
2019 int i_crop = 2 * (int)( ( p_sys->i_canvas_height & ~1 ) /
2020 f_scale_height / 2 + 0.5 );
2022 p_sys->i_src_y_offset += ( ( p_sys->i_crop_height - i_crop ) / 2 )
2024 p_sys->i_crop_height = i_crop;
2025 i_dst_height = p_sys->i_canvas_height & ~1;
2026 p_sys->i_nopadd_height = i_dst_height;
2028 else if( p_sys->i_canvas_height > p_sys->i_nopadd_height )
2031 i_dst_height = p_sys->i_canvas_height & ~1;
2032 p_sys->i_dst_y_offset = ( i_dst_height - p_sys->i_nopadd_height )
2034 p_sys->i_dst_y_offset = p_sys->i_dst_y_offset & ~1;
2038 /* Change aspect ratio from scaled pixel to output frame */
2039 f_aspect = f_aspect * i_dst_width / i_dst_height;
2041 /* Store calculated values */
2042 id->p_encoder->fmt_out.video.i_width = i_dst_width;
2043 id->p_encoder->fmt_out.video.i_height = i_dst_height;
2045 id->p_encoder->fmt_in.video.i_width = i_dst_width;
2046 id->p_encoder->fmt_in.video.i_height = i_dst_height;
2048 msg_Dbg( p_stream, "source %ix%i, crop %ix%i, "
2049 "destination %ix%i, padding %ix%i",
2050 i_src_width, i_src_height,
2051 p_sys->i_crop_width, p_sys->i_crop_height,
2052 p_sys->i_nopadd_width, p_sys->i_nopadd_height,
2053 i_dst_width, i_dst_height
2056 /* Handle frame rate conversion */
2057 if( !id->p_encoder->fmt_out.video.i_frame_rate ||
2058 !id->p_encoder->fmt_out.video.i_frame_rate_base )
2060 if( id->p_decoder->fmt_out.video.i_frame_rate &&
2061 id->p_decoder->fmt_out.video.i_frame_rate_base )
2063 id->p_encoder->fmt_out.video.i_frame_rate =
2064 id->p_decoder->fmt_out.video.i_frame_rate;
2065 id->p_encoder->fmt_out.video.i_frame_rate_base =
2066 id->p_decoder->fmt_out.video.i_frame_rate_base;
2070 /* Pick a sensible default value */
2071 id->p_encoder->fmt_out.video.i_frame_rate = 25;
2072 id->p_encoder->fmt_out.video.i_frame_rate_base = 1;
2076 id->p_encoder->fmt_in.video.i_frame_rate =
2077 id->p_encoder->fmt_out.video.i_frame_rate;
2078 id->p_encoder->fmt_in.video.i_frame_rate_base =
2079 id->p_encoder->fmt_out.video.i_frame_rate_base;
2081 date_Init( &id->interpolated_pts,
2082 id->p_encoder->fmt_out.video.i_frame_rate,
2083 id->p_encoder->fmt_out.video.i_frame_rate_base );
2085 /* Check whether a particular aspect ratio was requested */
2086 if( !id->p_encoder->fmt_out.video.i_aspect )
2088 id->p_encoder->fmt_out.video.i_aspect = (int)( f_aspect * VOUT_ASPECT_FACTOR + 0.5 );
2090 id->p_encoder->fmt_in.video.i_aspect =
2091 id->p_encoder->fmt_out.video.i_aspect;
2093 msg_Dbg( p_stream, "encoder aspect is %i:%i", id->p_encoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
2095 id->p_encoder->p_module =
2096 module_Need( id->p_encoder, "encoder", p_sys->psz_venc, true );
2097 if( !id->p_encoder->p_module )
2099 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_venc );
2100 return VLC_EGENERIC;
2103 id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
2105 /* Hack for mp2v/mp1v transcoding support */
2106 if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','1','v') ||
2107 id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','2','v') )
2109 id->p_encoder->fmt_out.i_codec = VLC_FOURCC('m','p','g','v');
2112 id->id = p_stream->p_sys->p_out->pf_add( p_stream->p_sys->p_out,
2113 &id->p_encoder->fmt_out );
2116 msg_Err( p_stream, "cannot add this stream" );
2117 return VLC_EGENERIC;
2123 static void transcode_video_close( sout_stream_t *p_stream,
2124 sout_stream_id_t *id )
2128 if( p_stream->p_sys->i_threads >= 1 )
2130 vlc_mutex_lock( &p_stream->p_sys->lock_out );
2131 vlc_object_kill( p_stream->p_sys );
2132 vlc_cond_signal( &p_stream->p_sys->cond );
2133 vlc_mutex_unlock( &p_stream->p_sys->lock_out );
2134 vlc_thread_join( p_stream->p_sys );
2135 vlc_mutex_destroy( &p_stream->p_sys->lock_out );
2136 vlc_cond_destroy( &p_stream->p_sys->cond );
2140 if( id->p_decoder->p_module )
2141 module_Unneed( id->p_decoder, id->p_decoder->p_module );
2143 if( id->p_decoder->p_owner )
2145 /* Clean-up pictures ring buffer */
2146 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2148 if( id->p_decoder->p_owner->pp_pics[i] )
2149 video_del_buffer( VLC_OBJECT(id->p_decoder),
2150 id->p_decoder->p_owner->pp_pics[i] );
2152 free( id->p_decoder->p_owner );
2156 if( id->p_encoder->p_module )
2157 module_Unneed( id->p_encoder, id->p_encoder->p_module );
2160 for( i = 0; i < id->i_filter; i++ )
2162 transcode_video_filter_close( p_stream, id->pp_filter[i] );
2163 id->pp_filter[i] = NULL;
2167 for( i = 0; i < id->i_ufilter; i++ )
2169 transcode_video_filter_close( p_stream, id->pp_ufilter[i] );
2170 id->pp_ufilter[i] = NULL;
2175 static int transcode_video_process( sout_stream_t *p_stream,
2176 sout_stream_id_t *id,
2177 block_t *in, block_t **out )
2179 sout_stream_sys_t *p_sys = p_stream->p_sys;
2180 int i_duplicate = 1, i;
2181 picture_t *p_pic, *p_pic2 = NULL;
2184 while( (p_pic = id->p_decoder->pf_decode_video( id->p_decoder, &in )) )
2186 subpicture_t *p_subpic = NULL;
2188 sout_UpdateStatistic( p_stream->p_sout, SOUT_STATISTIC_DECODED_VIDEO, 1 );
2190 if( p_stream->p_sout->i_out_pace_nocontrol && p_sys->b_hurry_up )
2192 mtime_t current_date = mdate();
2193 if( current_date + 50000 > p_pic->date )
2195 msg_Dbg( p_stream, "late picture skipped (%"PRId64")",
2196 current_date + 50000 - p_pic->date );
2197 p_pic->pf_release( p_pic );
2202 if( p_sys->b_master_sync )
2204 mtime_t i_video_drift;
2205 mtime_t i_master_drift = p_sys->i_master_drift;
2208 i_pts = date_Get( &id->interpolated_pts ) + 1;
2209 if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2210 || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2212 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2213 date_Set( &id->interpolated_pts, p_pic->date );
2214 i_pts = p_pic->date + 1;
2216 i_video_drift = p_pic->date - i_pts;
2219 /* Set the pts of the frame being encoded */
2220 p_pic->date = i_pts;
2222 if( i_video_drift < (i_master_drift - 50000) )
2225 msg_Dbg( p_stream, "dropping frame (%i)",
2226 (int)(i_video_drift - i_master_drift) );
2228 p_pic->pf_release( p_pic );
2231 else if( i_video_drift > (i_master_drift + 50000) )
2234 msg_Dbg( p_stream, "adding frame (%i)",
2235 (int)(i_video_drift - i_master_drift) );
2241 if( !id->p_encoder->p_module )
2243 if( transcode_video_encoder_open( p_stream, id ) != VLC_SUCCESS )
2245 p_pic->pf_release( p_pic );
2246 transcode_video_close( p_stream, id );
2247 id->b_transcode = false;
2248 return VLC_EGENERIC;
2252 if( p_stream->p_sys->b_deinterlace )
2254 id->pp_filter[id->i_filter] =
2255 transcode_video_filter_new( p_stream,
2256 &id->p_decoder->fmt_out, &id->p_decoder->fmt_out,
2257 p_sys->p_deinterlace_cfg,
2258 p_sys->psz_deinterlace );
2260 if( id->pp_filter[id->i_filter] )
2264 #if (defined(HAVE_FFMPEG_SWSCALE_H) || defined(HAVE_LIBSWSCALE_TREE)) || defined(HAVE_LIBSWSCALE_SWSCALE_H)
2265 if( ( id->p_decoder->fmt_out.video.i_chroma !=
2266 id->p_encoder->fmt_in.video.i_chroma ) ||
2267 ( id->p_decoder->fmt_out.video.i_width !=
2268 id->p_encoder->fmt_out.video.i_width ) ||
2269 ( id->p_decoder->fmt_out.video.i_height !=
2270 id->p_encoder->fmt_out.video.i_height ) )
2272 id->pp_filter[id->i_filter] =
2273 transcode_video_filter_new( p_stream,
2274 &id->p_decoder->fmt_out, &id->p_encoder->fmt_in,
2276 if( !id->pp_filter[id->i_filter] )
2278 p_pic->pf_release( p_pic );
2279 transcode_video_close( p_stream, id );
2280 id->b_transcode = false;
2281 return VLC_EGENERIC;
2286 /* we don't do chroma conversion or scaling in croppad */
2287 // es_format_t fmt_in, fmt_out;
2288 // es_format_Copy( &fmt_out, &id->p_encoder->fmt_in );
2289 // es_format_Copy( &fmt_in, &id->p_encoder->fmt_in );
2291 if( ( id->p_decoder->fmt_out.video.i_chroma ==
2292 id->p_encoder->fmt_in.video.i_chroma ) &&
2294 ( ( (int)id->p_decoder->fmt_out.video.i_width !=
2295 p_sys->i_crop_width ) ||
2296 ( p_sys->i_crop_width != p_sys->i_nopadd_width ) ||
2297 ( p_sys->i_nopadd_width !=
2298 (int)id->p_encoder->fmt_out.video.i_width ) ||
2300 ( (int)id->p_decoder->fmt_out.video.i_height !=
2301 p_sys->i_crop_height ) ||
2302 ( p_sys->i_crop_height != p_sys->i_nopadd_height ) ||
2303 ( p_sys->i_nopadd_height !=
2304 (int)id->p_encoder->fmt_out.video.i_height ) ) )
2306 id->pp_filter[id->i_filter] =
2307 transcode_video_filter_new( p_stream,
2308 &id->p_decoder->fmt_out, &id->p_encoder->fmt_in,
2310 if( id->pp_filter[id->i_filter] )
2312 /* Set crop and padding information */
2313 id->pp_filter[id->i_filter]->fmt_in.video.i_x_offset = p_sys->i_src_x_offset;
2314 id->pp_filter[id->i_filter]->fmt_in.video.i_y_offset = p_sys->i_src_y_offset;
2315 id->pp_filter[id->i_filter]->fmt_in.video.i_visible_width = p_sys->i_crop_width;
2316 id->pp_filter[id->i_filter]->fmt_in.video.i_visible_height = p_sys->i_crop_height;
2318 id->pp_filter[id->i_filter]->fmt_out.video.i_x_offset = p_sys->i_dst_x_offset;
2319 id->pp_filter[id->i_filter]->fmt_out.video.i_y_offset = p_sys->i_dst_y_offset;
2320 id->pp_filter[id->i_filter]->fmt_out.video.i_visible_width = p_sys->i_nopadd_width;
2321 id->pp_filter[id->i_filter]->fmt_out.video.i_visible_height = p_sys->i_nopadd_height;
2328 /* Check if we need a filter for chroma conversion or resizing */
2329 if( id->p_decoder->fmt_out.video.i_chroma !=
2330 id->p_encoder->fmt_in.video.i_chroma ||
2332 (int)id->p_decoder->fmt_out.video.i_width != p_sys->i_crop_width ||
2333 p_sys->i_crop_width != p_sys->i_nopadd_width ||
2334 p_sys->i_nopadd_width != (int)id->p_encoder->fmt_out.video.i_width ||
2336 (int)id->p_decoder->fmt_out.video.i_height != p_sys->i_crop_height ||
2337 p_sys->i_crop_height != p_sys->i_nopadd_height ||
2338 p_sys->i_nopadd_height != (int)id->p_encoder->fmt_out.video.i_height)
2340 id->pp_filter[id->i_filter] =
2341 transcode_video_filter_new( p_stream,
2342 &id->p_decoder->fmt_out, &id->p_encoder->fmt_in,
2343 NULL, "crop padd" );
2344 if( !id->pp_filter[id->i_filter] )
2346 p_pic->pf_release( p_pic );
2347 transcode_video_close( p_stream, id );
2348 id->b_transcode = false;
2349 return VLC_EGENERIC;
2352 /* Set crop and padding information */
2353 id->pp_filter[id->i_filter]->fmt_in.video.i_x_offset = p_sys->i_src_x_offset;
2354 id->pp_filter[id->i_filter]->fmt_in.video.i_y_offset = p_sys->i_src_y_offset;
2355 id->pp_filter[id->i_filter]->fmt_in.video.i_visible_width = p_sys->i_crop_width;
2356 id->pp_filter[id->i_filter]->fmt_in.video.i_visible_height = p_sys->i_crop_height;
2358 id->pp_filter[id->i_filter]->fmt_out.video.i_x_offset = p_sys->i_dst_x_offset;
2359 id->pp_filter[id->i_filter]->fmt_out.video.i_y_offset = p_sys->i_dst_y_offset;
2360 id->pp_filter[id->i_filter]->fmt_out.video.i_visible_width = p_sys->i_nopadd_width;
2361 id->pp_filter[id->i_filter]->fmt_out.video.i_visible_height = p_sys->i_nopadd_height;
2366 for( i = 0; (i < p_sys->i_vfilters) && (id->i_ufilter < TRANSCODE_FILTERS); i++ )
2368 id->pp_ufilter[id->i_ufilter] =
2369 transcode_video_filter_new( p_stream,
2370 &id->p_decoder->fmt_out, &id->p_encoder->fmt_in,
2371 p_sys->p_vfilters_cfg[i], p_sys->psz_vfilters[i] );
2372 if( id->pp_ufilter[id->i_filter] )
2375 id->pp_ufilter[id->i_ufilter] = NULL;
2379 /* Run filter chain */
2380 for( i = 0; i < id->i_filter; i++ )
2382 p_pic = id->pp_filter[i]->pf_video_filter(id->pp_filter[i], p_pic);
2389 /* Check if we have a subpicture to overlay */
2392 p_subpic = spu_SortSubpictures( p_sys->p_spu, p_pic->date,
2393 false /* Fixme: check if stream is paused */ );
2394 /* TODO: get another pic */
2397 /* Overlay subpicture */
2400 int i_scale_width, i_scale_height;
2401 video_format_t *p_fmt;
2403 i_scale_width = id->p_encoder->fmt_in.video.i_width * 1000 /
2404 id->p_decoder->fmt_out.video.i_width;
2405 i_scale_height = id->p_encoder->fmt_in.video.i_height * 1000 /
2406 id->p_decoder->fmt_out.video.i_height;
2408 if( p_pic->i_refcount && !id->i_filter )
2410 /* We can't modify the picture, we need to duplicate it */
2411 picture_t *p_tmp = video_new_buffer_decoder( id->p_decoder );
2414 vout_CopyPicture( p_stream, p_tmp, p_pic );
2415 p_pic->pf_release( p_pic );
2421 p_fmt = &id->pp_filter[id->i_filter -1]->fmt_out.video;
2423 p_fmt = &id->p_decoder->fmt_out.video;
2425 /* FIXME (shouldn't have to be done here) */
2426 p_fmt->i_sar_num = p_fmt->i_aspect *
2427 p_fmt->i_height / p_fmt->i_width;
2428 p_fmt->i_sar_den = VOUT_ASPECT_FACTOR;
2430 spu_RenderSubpictures( p_sys->p_spu, p_fmt, p_pic, p_pic, p_subpic,
2431 i_scale_width, i_scale_height );
2434 /* Run user specified filter chain */
2435 for( i = 0; i < id->i_ufilter; i++ )
2437 p_pic = id->pp_ufilter[i]->pf_video_filter( id->pp_ufilter[i],
2441 if( p_sys->i_threads == 0 )
2444 p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
2445 block_ChainAppend( out, p_block );
2448 if( p_sys->b_master_sync )
2450 mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
2451 if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2452 || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2454 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2455 date_Set( &id->interpolated_pts, p_pic->date );
2456 i_pts = p_pic->date + 1;
2458 date_Increment( &id->interpolated_pts, 1 );
2461 if( p_sys->b_master_sync && i_duplicate > 1 )
2463 mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
2464 if( (p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT)
2465 || ((p_pic->date - i_pts) < -MASTER_SYNC_MAX_DRIFT) )
2467 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2468 date_Set( &id->interpolated_pts, p_pic->date );
2469 i_pts = p_pic->date + 1;
2471 date_Increment( &id->interpolated_pts, 1 );
2473 if( p_sys->i_threads >= 1 )
2475 /* We can't modify the picture, we need to duplicate it */
2476 p_pic2 = video_new_buffer_decoder( id->p_decoder );
2477 if( p_pic2 != NULL )
2479 vout_CopyPicture( p_stream, p_pic2, p_pic );
2480 p_pic2->date = i_pts;
2486 p_pic->date = i_pts;
2487 p_block = id->p_encoder->pf_encode_video(id->p_encoder, p_pic);
2488 block_ChainAppend( out, p_block );
2492 if( p_sys->i_threads == 0 )
2494 p_pic->pf_release( p_pic );
2498 vlc_mutex_lock( &p_sys->lock_out );
2499 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic;
2500 p_sys->i_last_pic %= PICTURE_RING_SIZE;
2501 *out = p_sys->p_buffers;
2502 p_sys->p_buffers = NULL;
2503 if( p_pic2 != NULL )
2505 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic2;
2506 p_sys->i_last_pic %= PICTURE_RING_SIZE;
2508 vlc_cond_signal( &p_sys->cond );
2509 vlc_mutex_unlock( &p_sys->lock_out );
2516 static int EncoderThread( sout_stream_sys_t *p_sys )
2518 sout_stream_id_t *id = p_sys->id_video;
2521 while( !p_sys->b_die && !p_sys->b_error )
2525 vlc_mutex_lock( &p_sys->lock_out );
2526 while( p_sys->i_last_pic == p_sys->i_first_pic )
2528 vlc_cond_wait( &p_sys->cond, &p_sys->lock_out );
2529 if( p_sys->b_die || p_sys->b_error ) break;
2531 if( p_sys->b_die || p_sys->b_error )
2533 vlc_mutex_unlock( &p_sys->lock_out );
2537 p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2538 p_sys->i_first_pic %= PICTURE_RING_SIZE;
2539 vlc_mutex_unlock( &p_sys->lock_out );
2541 p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
2542 vlc_mutex_lock( &p_sys->lock_out );
2543 block_ChainAppend( &p_sys->p_buffers, p_block );
2545 vlc_mutex_unlock( &p_sys->lock_out );
2546 p_pic->pf_release( p_pic );
2549 while( p_sys->i_last_pic != p_sys->i_first_pic )
2551 p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2552 p_sys->i_first_pic %= PICTURE_RING_SIZE;
2553 p_pic->pf_release( p_pic );
2555 block_ChainRelease( p_sys->p_buffers );
2560 struct picture_sys_t
2562 vlc_object_t *p_owner;
2565 static void video_release_buffer( picture_t *p_pic )
2567 if( p_pic && !p_pic->i_refcount && p_pic->pf_release && p_pic->p_sys )
2569 video_del_buffer_decoder( (decoder_t *)p_pic->p_sys->p_owner, p_pic );
2571 else if( p_pic && p_pic->i_refcount > 0 ) p_pic->i_refcount--;
2574 static picture_t *video_new_buffer( vlc_object_t *p_this, picture_t **pp_ring,
2575 sout_stream_sys_t *p_sys )
2577 decoder_t *p_dec = (decoder_t *)p_this;
2581 /* Find an empty space in the picture ring buffer */
2582 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2584 if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
2586 pp_ring[i]->i_status = RESERVED_PICTURE;
2590 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2592 if( pp_ring[i] == 0 ) break;
2595 if( i == PICTURE_RING_SIZE && p_sys->i_threads >= 1 )
2597 int i_first_pic = p_sys->i_first_pic;
2599 if( p_sys->i_first_pic != p_sys->i_last_pic )
2601 /* Encoder still has stuff to encode, wait to clear-up the list */
2602 while( p_sys->i_first_pic == i_first_pic )
2606 /* Find an empty space in the picture ring buffer */
2607 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2609 if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
2611 pp_ring[i]->i_status = RESERVED_PICTURE;
2615 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2617 if( pp_ring[i] == 0 ) break;
2621 if( i == PICTURE_RING_SIZE )
2623 msg_Err( p_this, "decoder/filter is leaking pictures, "
2624 "resetting its ring buffer" );
2626 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2628 pp_ring[i]->pf_release( pp_ring[i] );
2634 p_pic = malloc( sizeof(picture_t) );
2635 if( !p_pic ) return NULL;
2636 p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
2637 vout_AllocatePicture( VLC_OBJECT(p_dec), p_pic,
2638 p_dec->fmt_out.video.i_chroma,
2639 p_dec->fmt_out.video.i_width,
2640 p_dec->fmt_out.video.i_height,
2641 p_dec->fmt_out.video.i_aspect );
2643 if( !p_pic->i_planes )
2649 p_pic->pf_release = video_release_buffer;
2650 p_pic->p_sys = malloc( sizeof(picture_sys_t) );
2657 p_pic->p_sys->p_owner = p_this;
2658 p_pic->i_status = RESERVED_PICTURE;
2664 static picture_t *video_new_buffer_decoder( decoder_t *p_dec )
2666 return video_new_buffer( VLC_OBJECT(p_dec),
2667 p_dec->p_owner->pp_pics, p_dec->p_owner->p_sys );
2670 static picture_t *video_new_buffer_filter( filter_t *p_filter )
2672 return video_new_buffer( VLC_OBJECT(p_filter),
2673 p_filter->p_owner->pp_pics,
2674 p_filter->p_owner->p_sys );
2677 static void video_del_buffer( vlc_object_t *p_this, picture_t *p_pic )
2682 free( p_pic->p_data_orig );
2683 free( p_pic->p_sys );
2688 static void video_del_buffer_decoder( decoder_t *p_decoder, picture_t *p_pic )
2690 VLC_UNUSED(p_decoder);
2691 p_pic->i_refcount = 0;
2692 p_pic->i_status = DESTROYED_PICTURE;
2695 static void video_del_buffer_filter( filter_t *p_filter, picture_t *p_pic )
2697 VLC_UNUSED(p_filter);
2698 p_pic->i_refcount = 0;
2699 p_pic->i_status = DESTROYED_PICTURE;
2702 static void video_link_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2705 p_pic->i_refcount++;
2708 static void video_unlink_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2711 video_release_buffer( p_pic );
2717 static subpicture_t *spu_new_buffer( decoder_t * );
2718 static void spu_del_buffer( decoder_t *, subpicture_t * );
2720 static int transcode_spu_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2722 sout_stream_sys_t *p_sys = p_stream->p_sys;
2728 /* Initialization of decoder structures */
2729 id->p_decoder->pf_decode_sub = NULL;
2730 id->p_decoder->pf_spu_buffer_new = spu_new_buffer;
2731 id->p_decoder->pf_spu_buffer_del = spu_del_buffer;
2732 id->p_decoder->p_owner = (decoder_owner_sys_t *)p_stream;
2733 /* id->p_decoder->p_cfg = p_sys->p_spu_cfg; */
2735 id->p_decoder->p_module =
2736 module_Need( id->p_decoder, "decoder", "$codec", 0 );
2738 if( !id->p_decoder->p_module )
2740 msg_Err( p_stream, "cannot find decoder" );
2741 return VLC_EGENERIC;
2744 if( !p_sys->b_soverlay )
2747 /* Initialization of encoder format structures */
2748 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
2749 id->p_decoder->fmt_in.i_codec );
2751 id->p_encoder->p_cfg = p_sys->p_spu_cfg;
2753 id->p_encoder->p_module =
2754 module_Need( id->p_encoder, "encoder", p_sys->psz_senc, true );
2756 if( !id->p_encoder->p_module )
2758 module_Unneed( id->p_decoder, id->p_decoder->p_module );
2759 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_senc );
2760 return VLC_EGENERIC;
2766 p_sys->p_spu = spu_Create( p_stream );
2767 spu_Init( p_sys->p_spu );
2773 static void transcode_spu_close( sout_stream_id_t *id)
2776 if( id->p_decoder->p_module )
2777 module_Unneed( id->p_decoder, id->p_decoder->p_module );
2780 if( id->p_encoder->p_module )
2781 module_Unneed( id->p_encoder, id->p_encoder->p_module );
2784 static int transcode_spu_process( sout_stream_t *p_stream,
2785 sout_stream_id_t *id,
2786 block_t *in, block_t **out )
2788 sout_stream_sys_t *p_sys = p_stream->p_sys;
2789 subpicture_t *p_subpic;
2792 p_subpic = id->p_decoder->pf_decode_sub( id->p_decoder, &in );
2794 return VLC_EGENERIC;
2796 sout_UpdateStatistic( p_stream->p_sout, SOUT_STATISTIC_DECODED_SUBTITLE, 1 );
2798 if( p_sys->b_master_sync && p_sys->i_master_drift )
2800 p_subpic->i_start -= p_sys->i_master_drift;
2801 if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2804 if( p_sys->b_soverlay )
2806 spu_DisplaySubpicture( p_sys->p_spu, p_subpic );
2812 p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
2813 spu_del_buffer( id->p_decoder, p_subpic );
2816 block_ChainAppend( out, p_block );
2821 return VLC_EGENERIC;
2824 static subpicture_t *spu_new_buffer( decoder_t *p_dec )
2826 sout_stream_t *p_stream = (sout_stream_t *)p_dec->p_owner;
2827 return spu_CreateSubpicture( p_stream->p_sys->p_spu );
2830 static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_subpic )
2832 sout_stream_t *p_stream = (sout_stream_t *)p_dec->p_owner;
2833 spu_DestroySubpicture( p_stream->p_sys->p_spu, p_subpic );
2839 static int transcode_osd_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2841 sout_stream_sys_t *p_sys = p_stream->p_sys;
2843 id->p_decoder->fmt_in.i_cat = SPU_ES;
2844 id->p_encoder->fmt_out.psz_language = strdup( "osd" );
2846 if( p_sys->i_osdcodec != 0 || p_sys->psz_osdenc )
2848 msg_Dbg( p_stream, "creating osdmenu transcoding from fcc=`%4.4s' "
2849 "to fcc=`%4.4s'", (char*)&id->p_encoder->fmt_out.i_codec,
2850 (char*)&p_sys->i_osdcodec );
2852 /* Complete destination format */
2853 id->p_encoder->fmt_out.i_codec = p_sys->i_osdcodec;
2856 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
2857 VLC_FOURCC('Y','U','V','A') );
2858 id->p_encoder->fmt_in.psz_language = strdup( "osd" );
2860 id->p_encoder->p_cfg = p_sys->p_osd_cfg;
2862 id->p_encoder->p_module =
2863 module_Need( id->p_encoder, "encoder", p_sys->psz_osdenc, true );
2865 if( !id->p_encoder->p_module )
2867 msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_osdenc );
2871 /* open output stream */
2872 id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
2873 id->b_transcode = true;
2875 if( !id->id ) goto error;
2879 msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
2880 (char*)&id->p_decoder->fmt_out.i_codec );
2881 id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_decoder->fmt_out );
2882 id->b_transcode = false;
2884 if( !id->id ) goto error;
2889 p_sys->p_spu = spu_Create( p_stream );
2890 spu_Init( p_sys->p_spu );
2896 msg_Err( p_stream, "starting osd encoding thread failed" );
2897 if( id->p_encoder->p_module )
2898 module_Unneed( id->p_encoder, id->p_encoder->p_module );
2899 p_sys->b_osd = false;
2900 return VLC_EGENERIC;
2903 static void transcode_osd_close( sout_stream_t *p_stream, sout_stream_id_t *id)
2905 sout_stream_sys_t *p_sys = p_stream->p_sys;
2908 if( p_sys->b_osd && id )
2910 if( id->p_encoder->p_module )
2911 module_Unneed( id->p_encoder, id->p_encoder->p_module );
2913 p_sys->b_osd = false;
2916 static int transcode_osd_process( sout_stream_t *p_stream,
2917 sout_stream_id_t *id,
2918 block_t *in, block_t **out )
2920 sout_stream_sys_t *p_sys = p_stream->p_sys;
2921 subpicture_t *p_subpic = NULL;
2923 /* Check if we have a subpicture to send */
2924 if( p_sys->p_spu && in->i_dts > 0)
2926 p_subpic = spu_SortSubpictures( p_sys->p_spu, in->i_dts, false );
2930 msg_Warn( p_stream, "spu channel not initialized, doing it now" );
2933 p_sys->p_spu = spu_Create( p_stream );
2934 spu_Init( p_sys->p_spu );
2940 block_t *p_block = NULL;
2942 if( p_sys->b_master_sync && p_sys->i_master_drift )
2944 p_subpic->i_start -= p_sys->i_master_drift;
2945 if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2948 p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
2949 spu_DestroySubpicture( p_sys->p_spu, p_subpic );
2952 p_block->i_dts = p_block->i_pts = in->i_dts;
2953 block_ChainAppend( out, p_block );
2957 return VLC_EGENERIC;