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>
10 * Antoine Cellerier <dionoea at videolan dot org>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25 *****************************************************************************/
27 /*****************************************************************************
29 *****************************************************************************/
34 #include <vlc_common.h>
35 #include <vlc_plugin.h>
36 #include <vlc_input.h>
40 #include <vlc_codec.h>
42 #include <vlc_block.h>
43 #include <vlc_filter.h>
48 #define MASTER_SYNC_MAX_DRIFT 100000
52 /*****************************************************************************
54 *****************************************************************************/
55 #define VENC_TEXT N_("Video encoder")
56 #define VENC_LONGTEXT N_( \
57 "This is the video encoder module that will be used (and its associated "\
59 #define VCODEC_TEXT N_("Destination video codec")
60 #define VCODEC_LONGTEXT N_( \
61 "This is the video codec that will be used.")
62 #define VB_TEXT N_("Video bitrate")
63 #define VB_LONGTEXT N_( \
64 "Target bitrate of the transcoded video stream." )
65 #define SCALE_TEXT N_("Video scaling")
66 #define SCALE_LONGTEXT N_( \
67 "Scale factor to apply to the video while transcoding (eg: 0.25)")
68 #define FPS_TEXT N_("Video frame-rate")
69 #define FPS_LONGTEXT N_( \
70 "Target output frame rate for the video stream." )
71 #define DEINTERLACE_TEXT N_("Deinterlace video")
72 #define DEINTERLACE_LONGTEXT N_( \
73 "Deinterlace the video before encoding." )
74 #define DEINTERLACE_MODULE_TEXT N_("Deinterlace module")
75 #define DEINTERLACE_MODULE_LONGTEXT N_( \
76 "Specify the deinterlace module to use." )
77 #define WIDTH_TEXT N_("Video width")
78 #define WIDTH_LONGTEXT N_( \
79 "Output video width." )
80 #define HEIGHT_TEXT N_("Video height")
81 #define HEIGHT_LONGTEXT N_( \
82 "Output video height." )
83 #define MAXWIDTH_TEXT N_("Maximum video width")
84 #define MAXWIDTH_LONGTEXT N_( \
85 "Maximum output video width." )
86 #define MAXHEIGHT_TEXT N_("Maximum video height")
87 #define MAXHEIGHT_LONGTEXT N_( \
88 "Maximum output video height." )
89 #define VFILTER_TEXT N_("Video filter")
90 #define VFILTER_LONGTEXT N_( \
91 "Video filters will be applied to the video streams (after overlays " \
92 "are applied). You must enter a comma-separated list of filters." )
94 #define AENC_TEXT N_("Audio encoder")
95 #define AENC_LONGTEXT N_( \
96 "This is the audio encoder module that will be used (and its associated "\
98 #define ACODEC_TEXT N_("Destination audio codec")
99 #define ACODEC_LONGTEXT N_( \
100 "This is the audio codec that will be used.")
101 #define AB_TEXT N_("Audio bitrate")
102 #define AB_LONGTEXT N_( \
103 "Target bitrate of the transcoded audio stream." )
104 #define ARATE_TEXT N_("Audio sample rate")
105 #define ARATE_LONGTEXT N_( \
106 "Sample rate of the transcoded audio stream (11250, 22500, 44100 or 48000).")
107 #define ACHANS_TEXT N_("Audio channels")
108 #define ACHANS_LONGTEXT N_( \
109 "Number of audio channels in the transcoded streams." )
110 #define AFILTER_TEXT N_("Audio filter")
111 #define AFILTER_LONGTEXT N_( \
112 "Audio filters will be applied to the audio streams (after conversion " \
113 "filters are applied). You must enter a comma-separated list of filters." )
115 #define SENC_TEXT N_("Subtitles encoder")
116 #define SENC_LONGTEXT N_( \
117 "This is the subtitles encoder module that will be used (and its " \
118 "associated options)." )
119 #define SCODEC_TEXT N_("Destination subtitles codec")
120 #define SCODEC_LONGTEXT N_( \
121 "This is the subtitles codec that will be used." )
123 #define SFILTER_TEXT N_("Overlays")
124 #define SFILTER_LONGTEXT N_( \
125 "This allows you to add overlays (also known as \"subpictures\" on the "\
126 "transcoded video stream. The subpictures produced by the filters will "\
127 "be overlayed directly onto the video. You must specify a comma-separated "\
128 "list of subpicture modules" )
130 #define OSD_TEXT N_("OSD menu")
131 #define OSD_LONGTEXT N_(\
132 "Stream the On Screen Display menu (using the osdmenu subpicture module)." )
134 #define THREADS_TEXT N_("Number of threads")
135 #define THREADS_LONGTEXT N_( \
136 "Number of threads used for the transcoding." )
137 #define HP_TEXT N_("High priority")
138 #define HP_LONGTEXT N_( \
139 "Runs the optional encoder thread at the OUTPUT priority instead of " \
142 #define ASYNC_TEXT N_("Synchronise on audio track")
143 #define ASYNC_LONGTEXT N_( \
144 "This option will drop/duplicate video frames to synchronise the video " \
145 "track on the audio track." )
147 #define HURRYUP_TEXT N_( "Hurry up" )
148 #define HURRYUP_LONGTEXT N_( "The transcoder will drop frames if your CPU " \
149 "can't keep up with the encoding rate." )
151 static const char *const ppsz_deinterlace_type[] =
153 "deinterlace", "ffmpeg-deinterlace"
156 static int Open ( vlc_object_t * );
157 static void Close( vlc_object_t * );
159 #define SOUT_CFG_PREFIX "sout-transcode-"
162 set_shortname( N_("Transcode"))
163 set_description( N_("Transcode stream output") )
164 set_capability( "sout stream", 50 )
165 add_shortcut( "transcode" )
166 set_callbacks( Open, Close )
167 set_category( CAT_SOUT )
168 set_subcategory( SUBCAT_SOUT_STREAM )
169 set_section( N_("Video"), NULL )
170 add_module( SOUT_CFG_PREFIX "venc", "encoder", NULL, NULL, VENC_TEXT,
171 VENC_LONGTEXT, false )
172 add_string( SOUT_CFG_PREFIX "vcodec", NULL, NULL, VCODEC_TEXT,
173 VCODEC_LONGTEXT, false )
174 add_integer( SOUT_CFG_PREFIX "vb", 800 * 1000, NULL, VB_TEXT,
176 add_float( SOUT_CFG_PREFIX "scale", 1, NULL, SCALE_TEXT,
177 SCALE_LONGTEXT, false )
178 add_float( SOUT_CFG_PREFIX "fps", 0, NULL, FPS_TEXT,
179 FPS_LONGTEXT, false )
180 add_bool( SOUT_CFG_PREFIX "hurry-up", true, NULL, HURRYUP_TEXT,
181 HURRYUP_LONGTEXT, false )
182 add_bool( SOUT_CFG_PREFIX "deinterlace", 0, NULL, DEINTERLACE_TEXT,
183 DEINTERLACE_LONGTEXT, false )
184 add_string( SOUT_CFG_PREFIX "deinterlace-module", "deinterlace", NULL,
185 DEINTERLACE_MODULE_TEXT, DEINTERLACE_MODULE_LONGTEXT,
187 change_string_list( ppsz_deinterlace_type, 0, 0 )
188 add_integer( SOUT_CFG_PREFIX "width", 0, NULL, WIDTH_TEXT,
189 WIDTH_LONGTEXT, true )
190 add_integer( SOUT_CFG_PREFIX "height", 0, NULL, HEIGHT_TEXT,
191 HEIGHT_LONGTEXT, true )
192 add_integer( SOUT_CFG_PREFIX "maxwidth", 0, NULL, MAXWIDTH_TEXT,
193 MAXWIDTH_LONGTEXT, true )
194 add_integer( SOUT_CFG_PREFIX "maxheight", 0, NULL, MAXHEIGHT_TEXT,
195 MAXHEIGHT_LONGTEXT, true )
196 add_module_list( SOUT_CFG_PREFIX "vfilter", "video filter2",
198 VFILTER_TEXT, VFILTER_LONGTEXT, false )
200 set_section( N_("Audio"), NULL )
201 add_module( SOUT_CFG_PREFIX "aenc", "encoder", NULL, NULL, AENC_TEXT,
202 AENC_LONGTEXT, false )
203 add_string( SOUT_CFG_PREFIX "acodec", NULL, NULL, ACODEC_TEXT,
204 ACODEC_LONGTEXT, false )
205 add_integer( SOUT_CFG_PREFIX "ab", 0, NULL, AB_TEXT,
207 add_integer( SOUT_CFG_PREFIX "channels", 0, NULL, ACHANS_TEXT,
208 ACHANS_LONGTEXT, false )
209 add_integer( SOUT_CFG_PREFIX "samplerate", 0, NULL, ARATE_TEXT,
210 ARATE_LONGTEXT, true )
211 add_bool( SOUT_CFG_PREFIX "audio-sync", 0, NULL, ASYNC_TEXT,
212 ASYNC_LONGTEXT, false )
213 add_module_list( SOUT_CFG_PREFIX "afilter", "audio filter2",
215 AFILTER_TEXT, AFILTER_LONGTEXT, false )
217 set_section( N_("Overlays/Subtitles"), NULL )
218 add_module( SOUT_CFG_PREFIX "senc", "encoder", NULL, NULL, SENC_TEXT,
219 SENC_LONGTEXT, false )
220 add_string( SOUT_CFG_PREFIX "scodec", NULL, NULL, SCODEC_TEXT,
221 SCODEC_LONGTEXT, false )
222 add_bool( SOUT_CFG_PREFIX "soverlay", 0, NULL, SCODEC_TEXT,
223 SCODEC_LONGTEXT, false )
224 add_module_list( SOUT_CFG_PREFIX "sfilter", "video filter",
226 SFILTER_TEXT, SFILTER_LONGTEXT, false )
228 set_section( N_("On Screen Display"), NULL )
229 add_bool( SOUT_CFG_PREFIX "osd", 0, NULL, OSD_TEXT,
230 OSD_LONGTEXT, false )
232 set_section( N_("Miscellaneous"), NULL )
233 add_integer( SOUT_CFG_PREFIX "threads", 0, NULL, THREADS_TEXT,
234 THREADS_LONGTEXT, true )
235 add_bool( SOUT_CFG_PREFIX "high-priority", 0, NULL, HP_TEXT, HP_LONGTEXT,
240 static const char *const ppsz_sout_options[] = {
241 "venc", "vcodec", "vb",
242 "scale", "fps", "width", "height", "vfilter", "deinterlace",
243 "deinterlace-module", "threads", "hurry-up", "aenc", "acodec", "ab",
244 "afilter", "samplerate", "channels", "senc", "scodec", "soverlay",
245 "sfilter", "osd", "audio-sync", "high-priority", "maxwidth", "maxheight",
249 /*****************************************************************************
250 * Exported prototypes
251 *****************************************************************************/
252 static sout_stream_id_t *Add ( sout_stream_t *, es_format_t * );
253 static int Del ( sout_stream_t *, sout_stream_id_t * );
254 static int Send( sout_stream_t *, sout_stream_id_t *, block_t* );
256 static int transcode_audio_new ( sout_stream_t *, sout_stream_id_t * );
257 static void transcode_audio_close ( sout_stream_id_t * );
258 static int transcode_audio_process( sout_stream_t *, sout_stream_id_t *,
259 block_t *, block_t ** );
261 static aout_buffer_t *audio_new_buffer( decoder_t *, int );
262 static void audio_del_buffer( decoder_t *, aout_buffer_t * );
264 static int transcode_video_new ( sout_stream_t *, sout_stream_id_t * );
265 static void transcode_video_close ( sout_stream_t *, sout_stream_id_t * );
266 static void transcode_video_encoder_init( sout_stream_t *, sout_stream_id_t *);
267 static int transcode_video_encoder_open( sout_stream_t *, sout_stream_id_t *);
268 static int transcode_video_process( sout_stream_t *, sout_stream_id_t *,
269 block_t *, block_t ** );
271 static void video_del_buffer( vlc_object_t *, picture_t * );
272 static picture_t *video_new_buffer_decoder( decoder_t * );
273 static void video_del_buffer_decoder( decoder_t *, picture_t * );
274 static void video_link_picture_decoder( decoder_t *, picture_t * );
275 static void video_unlink_picture_decoder( decoder_t *, picture_t * );
276 static picture_t *video_new_buffer_filter( filter_t * );
277 static void video_del_buffer_filter( filter_t *, picture_t * );
279 static int transcode_spu_new ( sout_stream_t *, sout_stream_id_t * );
280 static void transcode_spu_close ( sout_stream_id_t * );
281 static int transcode_spu_process( sout_stream_t *, sout_stream_id_t *,
282 block_t *, block_t ** );
284 static int transcode_osd_new ( sout_stream_t *, sout_stream_id_t * );
285 static void transcode_osd_close ( sout_stream_t *, sout_stream_id_t * );
286 static int transcode_osd_process( sout_stream_t *, sout_stream_id_t *,
287 block_t *, block_t ** );
289 static void* EncoderThread( vlc_object_t * p_this );
291 static const int pi_channels_maps[6] =
294 AOUT_CHAN_CENTER, AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
295 AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
296 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
297 | AOUT_CHAN_REARRIGHT,
298 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
299 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
302 #define PICTURE_RING_SIZE 64
303 #define SUBPICTURE_RING_SIZE 20
305 #define ENC_FRAMERATE (25 * 1000 + .5)
306 #define ENC_FRAMERATE_BASE 1000
308 struct sout_stream_sys_t
312 sout_stream_t *p_out;
313 sout_stream_id_t *id_video;
315 vlc_mutex_t lock_out;
317 picture_t * pp_pics[PICTURE_RING_SIZE];
318 int i_first_pic, i_last_pic;
321 vlc_fourcc_t i_acodec; /* codec audio (0 if not transcode) */
323 config_chain_t *p_audio_cfg;
324 uint32_t i_sample_rate;
331 vlc_fourcc_t i_vcodec; /* codec video (0 if not transcode) */
333 config_chain_t *p_video_cfg;
337 unsigned int i_width, i_maxwidth;
338 unsigned int i_height, i_maxheight;
340 char *psz_deinterlace;
341 config_chain_t *p_deinterlace_cfg;
343 bool b_high_priority;
349 vlc_fourcc_t i_scodec; /* codec spu (0 if not transcode) */
352 config_chain_t *p_spu_cfg;
356 vlc_fourcc_t i_osdcodec; /* codec osd menu (0 if not transcode) */
358 config_chain_t *p_osd_cfg;
359 bool b_osd; /* true when osd es is registered */
363 mtime_t i_master_drift;
366 struct decoder_owner_sys_t
368 picture_t *pp_pics[PICTURE_RING_SIZE];
369 sout_stream_sys_t *p_sys;
371 struct filter_owner_sys_t
373 picture_t *pp_pics[PICTURE_RING_SIZE];
374 sout_stream_sys_t *p_sys;
377 /*****************************************************************************
379 *****************************************************************************/
380 static int Open( vlc_object_t *p_this )
382 sout_stream_t *p_stream = (sout_stream_t*)p_this;
383 sout_stream_sys_t *p_sys;
386 p_sys = vlc_object_create( p_this, sizeof( sout_stream_sys_t ) );
388 p_sys->p_out = sout_StreamNew( p_stream->p_sout, p_stream->psz_next );
391 msg_Err( p_stream, "cannot create chain" );
392 vlc_object_release( p_sys );
396 p_sys->i_master_drift = 0;
398 config_ChainParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
401 /* Audio transcoding parameters */
402 var_Get( p_stream, SOUT_CFG_PREFIX "aenc", &val );
403 p_sys->psz_aenc = NULL;
404 p_sys->p_audio_cfg = NULL;
405 if( val.psz_string && *val.psz_string )
408 psz_next = config_ChainCreate( &p_sys->psz_aenc, &p_sys->p_audio_cfg,
412 free( val.psz_string );
414 var_Get( p_stream, SOUT_CFG_PREFIX "acodec", &val );
416 if( val.psz_string && *val.psz_string )
419 memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
420 p_sys->i_acodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
422 free( val.psz_string );
424 var_Get( p_stream, SOUT_CFG_PREFIX "ab", &val );
425 p_sys->i_abitrate = val.i_int;
426 if( p_sys->i_abitrate < 4000 ) p_sys->i_abitrate *= 1000;
428 var_Get( p_stream, SOUT_CFG_PREFIX "samplerate", &val );
429 p_sys->i_sample_rate = val.i_int;
431 var_Get( p_stream, SOUT_CFG_PREFIX "channels", &val );
432 p_sys->i_channels = val.i_int;
434 if( p_sys->i_acodec )
436 if( p_sys->i_acodec == VLC_FOURCC('m','p','3',0) &&
437 p_sys->i_channels > 2 )
439 msg_Warn( p_stream, "%d channels invalid for mp3, forcing to 2",
441 p_sys->i_channels = 2;
443 msg_Dbg( p_stream, "codec audio=%4.4s %dHz %d channels %dKb/s",
444 (char *)&p_sys->i_acodec, p_sys->i_sample_rate,
445 p_sys->i_channels, p_sys->i_abitrate / 1000 );
448 var_Get( p_stream, SOUT_CFG_PREFIX "afilter", &val );
449 if( val.psz_string && *val.psz_string )
450 p_sys->psz_af2 = val.psz_string;
453 free( val.psz_string );
454 p_sys->psz_af2 = NULL;
457 /* Video transcoding parameters */
458 var_Get( p_stream, SOUT_CFG_PREFIX "venc", &val );
459 p_sys->psz_venc = NULL;
460 p_sys->p_video_cfg = NULL;
461 if( val.psz_string && *val.psz_string )
464 psz_next = config_ChainCreate( &p_sys->psz_venc, &p_sys->p_video_cfg,
468 free( val.psz_string );
470 var_Get( p_stream, SOUT_CFG_PREFIX "vcodec", &val );
472 if( val.psz_string && *val.psz_string )
475 memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
476 p_sys->i_vcodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
478 free( val.psz_string );
480 var_Get( p_stream, SOUT_CFG_PREFIX "vb", &val );
481 p_sys->i_vbitrate = val.i_int;
482 if( p_sys->i_vbitrate < 16000 ) p_sys->i_vbitrate *= 1000;
484 var_Get( p_stream, SOUT_CFG_PREFIX "scale", &val );
485 p_sys->f_scale = val.f_float;
487 var_Get( p_stream, SOUT_CFG_PREFIX "fps", &val );
488 p_sys->f_fps = val.f_float;
490 var_Get( p_stream, SOUT_CFG_PREFIX "hurry-up", &val );
491 p_sys->b_hurry_up = val.b_bool;
493 var_Get( p_stream, SOUT_CFG_PREFIX "width", &val );
494 p_sys->i_width = val.i_int;
496 var_Get( p_stream, SOUT_CFG_PREFIX "height", &val );
497 p_sys->i_height = val.i_int;
499 var_Get( p_stream, SOUT_CFG_PREFIX "maxwidth", &val );
500 p_sys->i_maxwidth = val.i_int;
502 var_Get( p_stream, SOUT_CFG_PREFIX "maxheight", &val );
503 p_sys->i_maxheight = val.i_int;
505 var_Get( p_stream, SOUT_CFG_PREFIX "vfilter", &val );
506 if( val.psz_string && *val.psz_string )
507 p_sys->psz_vf2 = val.psz_string;
510 free( val.psz_string );
511 p_sys->psz_vf2 = NULL;
514 var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace", &val );
515 p_sys->b_deinterlace = val.b_bool;
517 var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace-module", &val );
518 p_sys->psz_deinterlace = NULL;
519 p_sys->p_deinterlace_cfg = NULL;
520 if( val.psz_string && *val.psz_string )
523 psz_next = config_ChainCreate( &p_sys->psz_deinterlace,
524 &p_sys->p_deinterlace_cfg,
528 free( val.psz_string );
530 var_Get( p_stream, SOUT_CFG_PREFIX "threads", &val );
531 p_sys->i_threads = val.i_int;
532 var_Get( p_stream, SOUT_CFG_PREFIX "high-priority", &val );
533 p_sys->b_high_priority = val.b_bool;
535 if( p_sys->i_vcodec )
537 msg_Dbg( p_stream, "codec video=%4.4s %dx%d scaling: %f %dkb/s",
538 (char *)&p_sys->i_vcodec, p_sys->i_width, p_sys->i_height,
539 p_sys->f_scale, p_sys->i_vbitrate / 1000 );
542 /* Subpictures transcoding parameters */
544 p_sys->psz_senc = NULL;
545 p_sys->p_spu_cfg = NULL;
548 var_Get( p_stream, SOUT_CFG_PREFIX "senc", &val );
549 if( val.psz_string && *val.psz_string )
552 psz_next = config_ChainCreate( &p_sys->psz_senc, &p_sys->p_spu_cfg,
556 free( val.psz_string );
558 var_Get( p_stream, SOUT_CFG_PREFIX "scodec", &val );
559 if( val.psz_string && *val.psz_string )
562 memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
563 p_sys->i_scodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
565 free( val.psz_string );
567 if( p_sys->i_scodec )
569 msg_Dbg( p_stream, "codec spu=%4.4s", (char *)&p_sys->i_scodec );
572 var_Get( p_stream, SOUT_CFG_PREFIX "soverlay", &val );
573 p_sys->b_soverlay = val.b_bool;
575 var_Get( p_stream, SOUT_CFG_PREFIX "sfilter", &val );
576 if( val.psz_string && *val.psz_string )
578 p_sys->p_spu = spu_Create( p_stream );
579 var_Create( p_sys->p_spu, "sub-filter", VLC_VAR_STRING );
580 var_Set( p_sys->p_spu, "sub-filter", val );
581 spu_Init( p_sys->p_spu );
583 free( val.psz_string );
585 /* OSD menu transcoding parameters */
586 p_sys->psz_osdenc = NULL;
587 p_sys->p_osd_cfg = NULL;
588 p_sys->i_osdcodec = 0;
589 p_sys->b_osd = false;
591 var_Get( p_stream, SOUT_CFG_PREFIX "osd", &val );
597 psz_next = config_ChainCreate( &p_sys->psz_osdenc,
598 &p_sys->p_osd_cfg, strdup( "dvbsub") );
601 p_sys->i_osdcodec = VLC_FOURCC('Y','U','V','P' );
603 msg_Dbg( p_stream, "codec osd=%4.4s", (char *)&p_sys->i_osdcodec );
607 osd_val.psz_string = strdup("osdmenu");
608 p_sys->p_spu = spu_Create( p_stream );
609 var_Create( p_sys->p_spu, "sub-filter", VLC_VAR_STRING );
610 var_Set( p_sys->p_spu, "sub-filter", osd_val );
611 spu_Init( p_sys->p_spu );
612 free( osd_val.psz_string );
616 osd_val.psz_string = strdup("osdmenu");
617 var_Set( p_sys->p_spu, "sub-filter", osd_val );
618 free( osd_val.psz_string );
623 var_Get( p_stream, SOUT_CFG_PREFIX "audio-sync", &val );
624 p_sys->b_master_sync = val.b_bool;
625 if( p_sys->f_fps > 0 ) p_sys->b_master_sync = true;
627 p_stream->pf_add = Add;
628 p_stream->pf_del = Del;
629 p_stream->pf_send = Send;
630 p_stream->p_sys = p_sys;
635 /*****************************************************************************
637 *****************************************************************************/
638 static void Close( vlc_object_t * p_this )
640 sout_stream_t *p_stream = (sout_stream_t*)p_this;
641 sout_stream_sys_t *p_sys = p_stream->p_sys;
643 sout_StreamDelete( p_sys->p_out );
645 free( p_sys->psz_af2 );
647 config_ChainDestroy( p_sys->p_audio_cfg );
648 free( p_sys->psz_aenc );
650 free( p_sys->psz_vf2 );
652 config_ChainDestroy( p_sys->p_video_cfg );
653 free( p_sys->psz_venc );
655 config_ChainDestroy( p_sys->p_deinterlace_cfg );
656 free( p_sys->psz_deinterlace );
658 config_ChainDestroy( p_sys->p_spu_cfg );
659 free( p_sys->psz_senc );
661 if( p_sys->p_spu ) spu_Destroy( p_sys->p_spu );
663 config_ChainDestroy( p_sys->p_osd_cfg );
664 free( p_sys->psz_osdenc );
666 vlc_object_release( p_sys );
669 struct sout_stream_id_t
673 /* id of the out stream */
677 decoder_t *p_decoder;
680 filter_chain_t *p_f_chain;
681 /* User specified filters */
682 filter_chain_t *p_uf_chain;
685 encoder_t *p_encoder;
688 date_t interpolated_pts;
691 static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
693 sout_stream_sys_t *p_sys = p_stream->p_sys;
694 sout_stream_id_t *id;
696 id = calloc( 1, sizeof( sout_stream_id_t ) );
701 id->p_decoder = NULL;
702 id->p_encoder = NULL;
704 /* Create decoder object */
705 id->p_decoder = vlc_object_create( p_stream, VLC_OBJECT_DECODER );
708 vlc_object_attach( id->p_decoder, p_stream );
709 id->p_decoder->p_module = NULL;
710 id->p_decoder->fmt_in = *p_fmt;
711 id->p_decoder->b_pace_control = true;
713 /* Create encoder object */
714 id->p_encoder = sout_EncoderCreate( p_stream );
717 vlc_object_attach( id->p_encoder, p_stream );
718 id->p_encoder->p_module = NULL;
720 /* Create destination format */
721 es_format_Init( &id->p_encoder->fmt_out, p_fmt->i_cat, 0 );
722 id->p_encoder->fmt_out.i_id = p_fmt->i_id;
723 id->p_encoder->fmt_out.i_group = p_fmt->i_group;
724 if( p_fmt->psz_language )
725 id->p_encoder->fmt_out.psz_language = strdup( p_fmt->psz_language );
727 if( p_fmt->i_cat == AUDIO_ES && (p_sys->i_acodec || p_sys->psz_aenc) )
730 "creating audio transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
731 (char*)&p_fmt->i_codec, (char*)&p_sys->i_acodec );
733 /* Complete destination format */
734 id->p_encoder->fmt_out.i_codec = p_sys->i_acodec;
735 id->p_encoder->fmt_out.audio.i_rate = p_sys->i_sample_rate > 0 ?
736 p_sys->i_sample_rate : p_fmt->audio.i_rate;
737 id->p_encoder->fmt_out.i_bitrate = p_sys->i_abitrate;
738 id->p_encoder->fmt_out.audio.i_bitspersample =
739 p_fmt->audio.i_bitspersample;
740 id->p_encoder->fmt_out.audio.i_channels = p_sys->i_channels > 0 ?
741 p_sys->i_channels : p_fmt->audio.i_channels;
742 /* Sanity check for audio channels */
743 id->p_encoder->fmt_out.audio.i_channels =
744 __MIN( id->p_encoder->fmt_out.audio.i_channels,
745 id->p_decoder->fmt_in.audio.i_channels );
746 id->p_encoder->fmt_out.audio.i_original_channels =
747 id->p_decoder->fmt_in.audio.i_physical_channels;
748 if( id->p_decoder->fmt_in.audio.i_channels ==
749 id->p_encoder->fmt_out.audio.i_channels )
751 id->p_encoder->fmt_out.audio.i_physical_channels =
752 id->p_decoder->fmt_in.audio.i_physical_channels;
756 id->p_encoder->fmt_out.audio.i_physical_channels =
757 pi_channels_maps[id->p_encoder->fmt_out.audio.i_channels];
760 /* Build decoder -> filter -> encoder chain */
761 if( transcode_audio_new( p_stream, id ) )
763 msg_Err( p_stream, "cannot create audio chain" );
767 /* Open output stream */
768 id->id = sout_StreamIdAdd( p_sys->p_out, &id->p_encoder->fmt_out );
769 id->b_transcode = true;
773 transcode_audio_close( id );
777 date_Init( &id->interpolated_pts, p_fmt->audio.i_rate, 1 );
779 else if( p_fmt->i_cat == VIDEO_ES &&
780 (p_sys->i_vcodec != 0 || p_sys->psz_venc) )
783 "creating video transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
784 (char*)&p_fmt->i_codec, (char*)&p_sys->i_vcodec );
786 /* Complete destination format */
787 id->p_encoder->fmt_out.i_codec = p_sys->i_vcodec;
788 id->p_encoder->fmt_out.video.i_width = p_sys->i_width & ~1;
789 id->p_encoder->fmt_out.video.i_height = p_sys->i_height & ~1;
790 id->p_encoder->fmt_out.i_bitrate = p_sys->i_vbitrate;
792 /* Build decoder -> filter -> encoder chain */
793 if( transcode_video_new( p_stream, id ) )
795 msg_Err( p_stream, "cannot create video chain" );
799 /* Stream will be added later on because we don't know
800 * all the characteristics of the decoded stream yet */
801 id->b_transcode = true;
803 if( p_sys->f_fps > 0 )
805 id->p_encoder->fmt_out.video.i_frame_rate =
806 (p_sys->f_fps * 1000) + 0.5;
807 id->p_encoder->fmt_out.video.i_frame_rate_base =
811 else if( ( p_fmt->i_cat == SPU_ES ) &&
812 ( p_sys->i_scodec || p_sys->psz_senc ) )
814 msg_Dbg( p_stream, "creating subtitles transcoding from fcc=`%4.4s' "
815 "to fcc=`%4.4s'", (char*)&p_fmt->i_codec,
816 (char*)&p_sys->i_scodec );
818 /* Complete destination format */
819 id->p_encoder->fmt_out.i_codec = p_sys->i_scodec;
821 /* build decoder -> filter -> encoder */
822 if( transcode_spu_new( p_stream, id ) )
824 msg_Err( p_stream, "cannot create subtitles chain" );
828 /* open output stream */
829 id->id = sout_StreamIdAdd( p_sys->p_out, &id->p_encoder->fmt_out );
830 id->b_transcode = true;
834 transcode_spu_close( id );
838 else if( p_fmt->i_cat == SPU_ES && p_sys->b_soverlay )
840 msg_Dbg( p_stream, "subtitles (fcc=`%4.4s') overlaying",
841 (char*)&p_fmt->i_codec );
843 id->b_transcode = true;
845 /* Build decoder -> filter -> overlaying chain */
846 if( transcode_spu_new( p_stream, id ) )
848 msg_Err( p_stream, "cannot create subtitles chain" );
852 else if( !p_sys->b_osd && (p_sys->i_osdcodec != 0 || p_sys->psz_osdenc) )
854 msg_Dbg( p_stream, "creating osd transcoding from fcc=`%4.4s' "
855 "to fcc=`%4.4s'", (char*)&p_fmt->i_codec,
856 (char*)&p_sys->i_scodec );
858 id->b_transcode = true;
860 /* Create a fake OSD menu elementary stream */
861 if( transcode_osd_new( p_stream, id ) )
863 msg_Err( p_stream, "cannot create osd chain" );
870 msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
871 (char*)&p_fmt->i_codec );
872 id->id = sout_StreamIdAdd( p_sys->p_out, p_fmt );
873 id->b_transcode = false;
875 if( !id->id ) goto error;
885 vlc_object_detach( id->p_decoder );
886 vlc_object_release( id->p_decoder );
887 id->p_decoder = NULL;
892 vlc_object_detach( id->p_encoder );
893 es_format_Clean( &id->p_encoder->fmt_out );
894 vlc_object_release( id->p_encoder );
895 id->p_encoder = NULL;
903 static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
905 sout_stream_sys_t *p_sys = p_stream->p_sys;
907 if( id->b_transcode )
909 switch( id->p_decoder->fmt_in.i_cat )
912 transcode_audio_close( id );
915 transcode_video_close( p_stream, id );
919 transcode_osd_close( p_stream, id );
921 transcode_spu_close( id );
926 if( id->id ) sout_StreamIdDel( p_sys->p_out, id->id );
930 vlc_object_detach( id->p_decoder );
931 vlc_object_release( id->p_decoder );
932 id->p_decoder = NULL;
937 vlc_object_detach( id->p_encoder );
938 es_format_Clean( &id->p_encoder->fmt_out );
939 vlc_object_release( id->p_encoder );
940 id->p_encoder = NULL;
947 static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
950 sout_stream_sys_t *p_sys = p_stream->p_sys;
951 block_t *p_out = NULL;
953 if( !id->b_transcode )
956 return sout_StreamIdSend( p_sys->p_out, id->id, p_buffer );
958 block_Release( p_buffer );
962 switch( id->p_decoder->fmt_in.i_cat )
965 transcode_audio_process( p_stream, id, p_buffer, &p_out );
969 if( transcode_video_process( p_stream, id, p_buffer, &p_out )
977 /* Transcode OSD menu pictures. */
980 if( transcode_osd_process( p_stream, id, p_buffer, &p_out ) !=
986 else if ( transcode_spu_process( p_stream, id, p_buffer, &p_out ) !=
995 block_Release( p_buffer );
1000 return sout_StreamIdSend( p_sys->p_out, id->id, p_out );
1004 /****************************************************************************
1006 ****************************************************************************/
1007 static inline void video_timer_start( encoder_t * p_encoder )
1009 stats_TimerStart( p_encoder, "encoding video frame",
1010 STATS_TIMER_VIDEO_FRAME_ENCODING );
1013 static inline void video_timer_stop( encoder_t * p_encoder )
1015 stats_TimerStop( p_encoder, STATS_TIMER_VIDEO_FRAME_ENCODING );
1018 static inline void video_timer_close( encoder_t * p_encoder )
1020 stats_TimerDump( p_encoder, STATS_TIMER_VIDEO_FRAME_ENCODING );
1021 stats_TimerClean( p_encoder, STATS_TIMER_VIDEO_FRAME_ENCODING );
1024 static inline void audio_timer_start( encoder_t * p_encoder )
1026 stats_TimerStart( p_encoder, "encoding audio frame",
1027 STATS_TIMER_AUDIO_FRAME_ENCODING );
1030 static inline void audio_timer_stop( encoder_t * p_encoder )
1032 stats_TimerStop( p_encoder, STATS_TIMER_AUDIO_FRAME_ENCODING );
1035 static inline void audio_timer_close( encoder_t * p_encoder )
1037 stats_TimerDump( p_encoder, STATS_TIMER_AUDIO_FRAME_ENCODING );
1038 stats_TimerClean( p_encoder, STATS_TIMER_AUDIO_FRAME_ENCODING );
1041 /****************************************************************************
1042 * decoder reencoder part
1043 ****************************************************************************/
1045 static block_t *transcode_audio_alloc( filter_t *p_filter, int size )
1047 VLC_UNUSED( p_filter );
1048 return block_Alloc( size );
1051 static int transcode_audio_filter_allocation_init( filter_t *p_filter,
1055 p_filter->pf_audio_buffer_new = transcode_audio_alloc;
1059 static bool transcode_audio_filter_needed( const es_format_t *p_fmt1, const es_format_t *p_fmt2 )
1061 if( p_fmt1->i_codec != p_fmt2->i_codec ||
1062 p_fmt1->audio.i_channels != p_fmt2->audio.i_channels ||
1063 p_fmt1->audio.i_rate != p_fmt2->audio.i_rate )
1067 static int transcode_audio_filter_chain_build( sout_stream_t *p_stream, filter_chain_t *p_chain,
1068 const es_format_t *p_dst, const es_format_t *p_src )
1070 if( !transcode_audio_filter_needed( p_dst, p_src ) )
1073 es_format_t current = *p_src;
1075 msg_Dbg( p_stream, "Looking for filter "
1076 "(%4.4s->%4.4s, channels %d->%d, rate %d->%d)",
1077 (const char *)&p_src->i_codec,
1078 (const char *)&p_dst->i_codec,
1079 p_src->audio.i_channels,
1080 p_dst->audio.i_channels,
1081 p_src->audio.i_rate,
1082 p_dst->audio.i_rate );
1084 /* If any filter is needed, convert to fl32 */
1085 if( current.i_codec != VLC_FOURCC('f','l','3','2') )
1087 /* First step, convert to fl32 */
1089 current.audio.i_format = VLC_FOURCC('f','l','3','2');
1091 if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, ¤t ) )
1093 msg_Err( p_stream, "Failed to find conversion filter to fl32" );
1094 return VLC_EGENERIC;
1096 current = *filter_chain_GetFmtOut( p_chain );
1099 /* Fix sample rate */
1100 if( current.audio.i_rate != p_dst->audio.i_rate )
1102 current.audio.i_rate = p_dst->audio.i_rate;
1103 if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, ¤t ) )
1105 msg_Err( p_stream, "Failed to find conversion filter for resampling" );
1106 return VLC_EGENERIC;
1108 current = *filter_chain_GetFmtOut( p_chain );
1112 if( current.audio.i_channels != p_dst->audio.i_channels )
1114 current.audio.i_channels = p_dst->audio.i_channels;
1115 current.audio.i_physical_channels = p_dst->audio.i_physical_channels;
1116 current.audio.i_original_channels = p_dst->audio.i_original_channels;
1118 if( ( !current.audio.i_physical_channels || !current.audio.i_original_channels ) &&
1119 current.audio.i_channels < 6 )
1120 current.audio.i_physical_channels =
1121 current.audio.i_original_channels = pi_channels_maps[current.audio.i_channels];
1123 if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, ¤t ) )
1125 msg_Err( p_stream, "Failed to find conversion filter for channel mixing" );
1126 return VLC_EGENERIC;
1128 current = *filter_chain_GetFmtOut( p_chain );
1131 /* And last step, convert to the requested codec */
1132 if( current.i_codec != p_dst->i_codec )
1134 current.i_codec = p_dst->i_codec;
1135 if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, ¤t ) )
1137 msg_Err( p_stream, "Failed to find conversion filter to %4.4s",
1138 (const char*)&p_dst->i_codec);
1139 return VLC_EGENERIC;
1141 current = *filter_chain_GetFmtOut( p_chain );
1144 if( transcode_audio_filter_needed( p_dst, ¤t ) )
1146 /* Weird case, a filter has side effects, doomed */
1147 msg_Err( p_stream, "Failed to create a valid audio filter chain" );
1148 return VLC_EGENERIC;
1151 msg_Dbg( p_stream, "Got complete audio filter chain" );
1155 static int transcode_audio_new( sout_stream_t *p_stream,
1156 sout_stream_id_t *id )
1158 sout_stream_sys_t *p_sys = p_stream->p_sys;
1159 es_format_t fmt_last;
1165 /* Initialization of decoder structures */
1166 id->p_decoder->fmt_out = id->p_decoder->fmt_in;
1167 id->p_decoder->fmt_out.i_extra = 0;
1168 id->p_decoder->fmt_out.p_extra = 0;
1169 id->p_decoder->pf_decode_audio = NULL;
1170 id->p_decoder->pf_aout_buffer_new = audio_new_buffer;
1171 id->p_decoder->pf_aout_buffer_del = audio_del_buffer;
1172 /* id->p_decoder->p_cfg = p_sys->p_audio_cfg; */
1174 id->p_decoder->p_module =
1175 module_need( id->p_decoder, "decoder", "$codec", false );
1176 if( !id->p_decoder->p_module )
1178 msg_Err( p_stream, "cannot find audio decoder" );
1179 return VLC_EGENERIC;
1181 id->p_decoder->fmt_out.audio.i_bitspersample =
1182 aout_BitsPerSample( id->p_decoder->fmt_out.i_codec );
1183 fmt_last = id->p_decoder->fmt_out;
1184 /* Fix AAC SBR changing number of channels and sampling rate */
1185 if( !(id->p_decoder->fmt_in.i_codec == VLC_FOURCC('m','p','4','a') &&
1186 fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate &&
1187 fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels) )
1188 fmt_last.audio.i_rate = id->p_decoder->fmt_in.audio.i_rate;
1194 /* Initialization of encoder format structures */
1195 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1196 id->p_decoder->fmt_out.i_codec );
1197 id->p_encoder->fmt_in.audio.i_format = id->p_decoder->fmt_out.i_codec;
1199 id->p_encoder->fmt_in.audio.i_rate = id->p_encoder->fmt_out.audio.i_rate;
1200 id->p_encoder->fmt_in.audio.i_physical_channels =
1201 id->p_encoder->fmt_out.audio.i_physical_channels;
1202 id->p_encoder->fmt_in.audio.i_original_channels =
1203 id->p_encoder->fmt_out.audio.i_original_channels;
1204 id->p_encoder->fmt_in.audio.i_channels =
1205 id->p_encoder->fmt_out.audio.i_channels;
1206 id->p_encoder->fmt_in.audio.i_bitspersample =
1207 aout_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1209 id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
1210 id->p_encoder->p_module =
1211 module_need( id->p_encoder, "encoder", p_sys->psz_aenc, true );
1212 if( !id->p_encoder->p_module )
1214 msg_Err( p_stream, "cannot find audio encoder (module:%s fourcc:%4.4s)",
1215 p_sys->psz_aenc ? p_sys->psz_aenc : "any",
1216 (char *)&p_sys->i_acodec );
1217 module_unneed( id->p_decoder, id->p_decoder->p_module );
1218 id->p_decoder->p_module = NULL;
1219 return VLC_EGENERIC;
1221 id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
1222 id->p_encoder->fmt_in.audio.i_bitspersample =
1223 aout_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1225 /* Load user specified audio filters */
1226 if( p_sys->psz_af2 )
1228 es_format_t fmt_fl32 = fmt_last;
1230 fmt_fl32.audio.i_format = VLC_FOURCC('f','l','3','2');
1231 if( transcode_audio_filter_chain_build( p_stream, id->p_uf_chain,
1232 &fmt_fl32, &fmt_last ) )
1234 transcode_audio_close( id );
1235 return VLC_EGENERIC;
1237 fmt_last = fmt_fl32;
1239 id->p_uf_chain = filter_chain_New( p_stream, "audio filter2", false,
1240 transcode_audio_filter_allocation_init, NULL, NULL );
1241 filter_chain_Reset( id->p_uf_chain, &fmt_last, &fmt_fl32 );
1242 if( filter_chain_AppendFromString( id->p_uf_chain, p_sys->psz_af2 ) > 0 )
1243 fmt_last = *filter_chain_GetFmtOut( id->p_uf_chain );
1246 /* Load conversion filters */
1247 id->p_f_chain = filter_chain_New( p_stream, "audio filter2", true,
1248 transcode_audio_filter_allocation_init, NULL, NULL );
1249 filter_chain_Reset( id->p_f_chain, &fmt_last, &id->p_encoder->fmt_in );
1251 if( transcode_audio_filter_chain_build( p_stream, id->p_f_chain,
1252 &id->p_encoder->fmt_in, &fmt_last ) )
1254 transcode_audio_close( id );
1255 return VLC_EGENERIC;
1257 fmt_last = id->p_encoder->fmt_in;
1259 /* FIXME: Hack for mp3 transcoding support */
1260 if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC( 'm','p','3',' ' ) )
1261 id->p_encoder->fmt_out.i_codec = VLC_FOURCC( 'm','p','g','a' );
1266 static void transcode_audio_close( sout_stream_id_t *id )
1268 audio_timer_close( id->p_encoder );
1271 if( id->p_decoder->p_module )
1272 module_unneed( id->p_decoder, id->p_decoder->p_module );
1273 id->p_decoder->p_module = NULL;
1275 if( id->p_decoder->p_description )
1276 vlc_meta_Delete( id->p_decoder->p_description );
1277 id->p_decoder->p_description = NULL;
1280 if( id->p_encoder->p_module )
1281 module_unneed( id->p_encoder, id->p_encoder->p_module );
1282 id->p_encoder->p_module = NULL;
1285 if( id->p_uf_chain )
1286 filter_chain_Delete( id->p_uf_chain );
1288 filter_chain_Delete( id->p_f_chain );
1291 static int transcode_audio_process( sout_stream_t *p_stream,
1292 sout_stream_id_t *id,
1293 block_t *in, block_t **out )
1295 sout_stream_sys_t *p_sys = p_stream->p_sys;
1296 aout_buffer_t *p_audio_buf;
1297 block_t *p_block, *p_audio_block;
1300 while( (p_audio_buf = id->p_decoder->pf_decode_audio( id->p_decoder,
1303 sout_UpdateStatistic( p_stream->p_sout, SOUT_STATISTIC_DECODED_AUDIO, 1 );
1304 if( p_sys->b_master_sync )
1306 mtime_t i_dts = date_Get( &id->interpolated_pts ) + 1;
1307 if ( p_audio_buf->start_date - i_dts > MASTER_SYNC_MAX_DRIFT
1308 || p_audio_buf->start_date - i_dts < -MASTER_SYNC_MAX_DRIFT )
1310 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
1311 date_Set( &id->interpolated_pts, p_audio_buf->start_date );
1312 i_dts = p_audio_buf->start_date + 1;
1314 p_sys->i_master_drift = p_audio_buf->start_date - i_dts;
1315 date_Increment( &id->interpolated_pts, p_audio_buf->i_nb_samples );
1316 p_audio_buf->start_date -= p_sys->i_master_drift;
1317 p_audio_buf->end_date -= p_sys->i_master_drift;
1320 p_audio_block = p_audio_buf->p_sys;
1321 p_audio_block->i_buffer = p_audio_buf->i_nb_bytes;
1322 p_audio_block->i_dts = p_audio_block->i_pts =
1323 p_audio_buf->start_date;
1324 p_audio_block->i_length = p_audio_buf->end_date -
1325 p_audio_buf->start_date;
1326 p_audio_block->i_samples = p_audio_buf->i_nb_samples;
1328 /* Run filter chain */
1329 if( id->p_uf_chain )
1331 p_audio_block = filter_chain_AudioFilter( id->p_uf_chain, p_audio_block );
1332 assert( p_audio_block );
1335 p_audio_block = filter_chain_AudioFilter( id->p_f_chain, p_audio_block );
1336 assert( p_audio_block );
1338 p_audio_buf->p_buffer = p_audio_block->p_buffer;
1339 p_audio_buf->i_nb_bytes = p_audio_block->i_buffer;
1340 p_audio_buf->i_nb_samples = p_audio_block->i_samples;
1341 p_audio_buf->start_date = p_audio_block->i_dts;
1342 p_audio_buf->end_date = p_audio_block->i_dts + p_audio_block->i_length;
1344 audio_timer_start( id->p_encoder );
1345 p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf );
1346 audio_timer_stop( id->p_encoder );
1348 block_ChainAppend( out, p_block );
1349 block_Release( p_audio_block );
1350 free( p_audio_buf );
1356 static void audio_release_buffer( aout_buffer_t *p_buffer )
1358 if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
1362 static aout_buffer_t *audio_new_buffer( decoder_t *p_dec, int i_samples )
1364 aout_buffer_t *p_buffer;
1368 if( p_dec->fmt_out.audio.i_bitspersample )
1370 i_size = i_samples * p_dec->fmt_out.audio.i_bitspersample / 8 *
1371 p_dec->fmt_out.audio.i_channels;
1373 else if( p_dec->fmt_out.audio.i_bytes_per_frame &&
1374 p_dec->fmt_out.audio.i_frame_length )
1376 i_size = i_samples * p_dec->fmt_out.audio.i_bytes_per_frame /
1377 p_dec->fmt_out.audio.i_frame_length;
1381 i_size = i_samples * 4 * p_dec->fmt_out.audio.i_channels;
1384 p_buffer = malloc( sizeof(aout_buffer_t) );
1385 if( !p_buffer ) return NULL;
1386 p_buffer->b_discontinuity = false;
1387 p_buffer->pf_release = audio_release_buffer;
1388 p_buffer->p_sys = p_block = block_New( p_dec, i_size );
1390 p_buffer->p_buffer = p_block->p_buffer;
1391 p_buffer->i_size = p_buffer->i_nb_bytes = p_block->i_buffer;
1392 p_buffer->i_nb_samples = i_samples;
1393 p_block->i_samples = i_samples;
1398 static void audio_del_buffer( decoder_t *p_dec, aout_buffer_t *p_buffer )
1401 if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
1409 static int transcode_video_filter_allocation_init( filter_t *p_filter,
1412 sout_stream_sys_t *p_sys = (sout_stream_sys_t*)p_data;
1415 p_filter->pf_vout_buffer_new = video_new_buffer_filter;
1416 p_filter->pf_vout_buffer_del = video_del_buffer_filter;
1418 p_filter->p_owner = malloc( sizeof(filter_owner_sys_t) );
1419 if( !p_filter->p_owner )
1420 return VLC_EGENERIC;
1422 for( i = 0; i < PICTURE_RING_SIZE; i++ )
1423 p_filter->p_owner->pp_pics[i] = 0;
1424 p_filter->p_owner->p_sys = p_sys;
1429 static void transcode_video_filter_allocation_clear( filter_t *p_filter )
1433 /* Clean-up pictures ring buffer */
1434 for( j = 0; j < PICTURE_RING_SIZE; j++ )
1436 if( p_filter->p_owner->pp_pics[j] )
1437 video_del_buffer( VLC_OBJECT(p_filter),
1438 p_filter->p_owner->pp_pics[j] );
1440 free( p_filter->p_owner );
1443 static int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_t *id )
1445 sout_stream_sys_t *p_sys = p_stream->p_sys;
1449 * Initialization of decoder structures
1451 id->p_decoder->fmt_out = id->p_decoder->fmt_in;
1452 id->p_decoder->fmt_out.i_extra = 0;
1453 id->p_decoder->fmt_out.p_extra = 0;
1454 id->p_decoder->pf_decode_video = NULL;
1455 id->p_decoder->pf_get_cc = NULL;
1456 id->p_decoder->pf_get_cc = 0;
1457 id->p_decoder->pf_vout_buffer_new = video_new_buffer_decoder;
1458 id->p_decoder->pf_vout_buffer_del = video_del_buffer_decoder;
1459 id->p_decoder->pf_picture_link = video_link_picture_decoder;
1460 id->p_decoder->pf_picture_unlink = video_unlink_picture_decoder;
1461 id->p_decoder->p_owner = malloc( sizeof(decoder_owner_sys_t) );
1462 if( !id->p_decoder->p_owner )
1463 return VLC_EGENERIC;
1465 for( i = 0; i < PICTURE_RING_SIZE; i++ )
1466 id->p_decoder->p_owner->pp_pics[i] = 0;
1467 id->p_decoder->p_owner->p_sys = p_sys;
1468 /* id->p_decoder->p_cfg = p_sys->p_video_cfg; */
1470 id->p_decoder->p_module =
1471 module_need( id->p_decoder, "decoder", "$codec", false );
1473 if( !id->p_decoder->p_module )
1475 msg_Err( p_stream, "cannot find video decoder" );
1476 free( id->p_decoder->p_owner );
1477 return VLC_EGENERIC;
1482 * Because some info about the decoded input will only be available
1483 * once the first frame is decoded, we actually only test the availability
1484 * of the encoder here.
1487 /* Initialization of encoder format structures */
1488 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1489 id->p_decoder->fmt_out.i_codec );
1490 id->p_encoder->fmt_in.video.i_chroma = id->p_decoder->fmt_out.i_codec;
1492 /* The dimensions will be set properly later on.
1493 * Just put sensible values so we can test an encoder is available. */
1494 id->p_encoder->fmt_in.video.i_width =
1495 id->p_encoder->fmt_out.video.i_width
1496 ? id->p_encoder->fmt_out.video.i_width
1497 : id->p_decoder->fmt_in.video.i_width
1498 ? id->p_decoder->fmt_in.video.i_width : 16;
1499 id->p_encoder->fmt_in.video.i_height =
1500 id->p_encoder->fmt_out.video.i_height
1501 ? id->p_encoder->fmt_out.video.i_height
1502 : id->p_decoder->fmt_in.video.i_height
1503 ? id->p_decoder->fmt_in.video.i_height : 16;
1504 id->p_encoder->fmt_in.video.i_frame_rate = ENC_FRAMERATE;
1505 id->p_encoder->fmt_in.video.i_frame_rate_base = ENC_FRAMERATE_BASE;
1507 id->p_encoder->i_threads = p_sys->i_threads;
1508 id->p_encoder->p_cfg = p_sys->p_video_cfg;
1510 id->p_encoder->p_module =
1511 module_need( id->p_encoder, "encoder", p_sys->psz_venc, true );
1512 if( !id->p_encoder->p_module )
1514 msg_Err( p_stream, "cannot find video encoder (module:%s fourcc:%4.4s)",
1515 p_sys->psz_venc ? p_sys->psz_venc : "any",
1516 (char *)&p_sys->i_vcodec );
1517 module_unneed( id->p_decoder, id->p_decoder->p_module );
1518 id->p_decoder->p_module = 0;
1519 free( id->p_decoder->p_owner );
1520 return VLC_EGENERIC;
1523 /* Close the encoder.
1524 * We'll open it only when we have the first frame. */
1525 module_unneed( id->p_encoder, id->p_encoder->p_module );
1526 if( id->p_encoder->fmt_out.p_extra )
1528 free( id->p_encoder->fmt_out.p_extra );
1529 id->p_encoder->fmt_out.p_extra = NULL;
1530 id->p_encoder->fmt_out.i_extra = 0;
1532 id->p_encoder->p_module = NULL;
1534 if( p_sys->i_threads >= 1 )
1536 int i_priority = p_sys->b_high_priority ? VLC_THREAD_PRIORITY_OUTPUT :
1537 VLC_THREAD_PRIORITY_VIDEO;
1538 p_sys->id_video = id;
1539 vlc_mutex_init( &p_sys->lock_out );
1540 vlc_cond_init( &p_sys->cond );
1541 memset( p_sys->pp_pics, 0, sizeof(p_sys->pp_pics) );
1542 p_sys->i_first_pic = 0;
1543 p_sys->i_last_pic = 0;
1544 p_sys->p_buffers = NULL;
1545 p_sys->b_die = p_sys->b_error = 0;
1546 if( vlc_thread_create( p_sys, "encoder", EncoderThread, i_priority ) )
1548 msg_Err( p_stream, "cannot spawn encoder thread" );
1549 module_unneed( id->p_decoder, id->p_decoder->p_module );
1550 id->p_decoder->p_module = 0;
1551 free( id->p_decoder->p_owner );
1552 return VLC_EGENERIC;
1559 static void transcode_video_encoder_init( sout_stream_t *p_stream,
1560 sout_stream_id_t *id )
1562 sout_stream_sys_t *p_sys = p_stream->p_sys;
1564 /* Calculate scaling
1565 * width/height of source */
1566 int i_src_width = id->p_decoder->fmt_out.video.i_width;
1567 int i_src_height = id->p_decoder->fmt_out.video.i_height;
1569 /* with/height scaling */
1570 float f_scale_width = 1;
1571 float f_scale_height = 1;
1573 /* width/height of output stream */
1578 float f_aspect = (float)id->p_decoder->fmt_out.video.i_aspect /
1581 msg_Dbg( p_stream, "decoder aspect is %i:%i",
1582 id->p_decoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
1584 /* Change f_aspect from source frame to source pixel */
1585 f_aspect = f_aspect * i_src_height / i_src_width;
1586 msg_Dbg( p_stream, "source pixel aspect is %f:1", f_aspect );
1588 /* Calculate scaling factor for specified parameters */
1589 if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1590 id->p_encoder->fmt_out.video.i_height <= 0 && p_sys->f_scale )
1592 /* Global scaling. Make sure width will remain a factor of 16 */
1595 int i_new_width = i_src_width * p_sys->f_scale;
1597 if( i_new_width % 16 <= 7 && i_new_width >= 16 )
1598 i_new_width -= i_new_width % 16;
1600 i_new_width += 16 - i_new_width % 16;
1602 f_real_scale = (float)( i_new_width ) / (float) i_src_width;
1604 i_new_height = __MAX( 16, i_src_height * (float)f_real_scale );
1606 f_scale_width = f_real_scale;
1607 f_scale_height = (float) i_new_height / (float) i_src_height;
1609 else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1610 id->p_encoder->fmt_out.video.i_height <= 0 )
1612 /* Only width specified */
1613 f_scale_width = (float)id->p_encoder->fmt_out.video.i_width/i_src_width;
1614 f_scale_height = f_scale_width;
1616 else if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1617 id->p_encoder->fmt_out.video.i_height > 0 )
1619 /* Only height specified */
1620 f_scale_height = (float)id->p_encoder->fmt_out.video.i_height/i_src_height;
1621 f_scale_width = f_scale_height;
1623 else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1624 id->p_encoder->fmt_out.video.i_height > 0 )
1626 /* Width and height specified */
1627 f_scale_width = (float)id->p_encoder->fmt_out.video.i_width/i_src_width;
1628 f_scale_height = (float)id->p_encoder->fmt_out.video.i_height/i_src_height;
1631 /* check maxwidth and maxheight
1633 if( p_sys->i_maxwidth && f_scale_width > (float)p_sys->i_maxwidth /
1636 f_scale_width = (float)p_sys->i_maxwidth / i_src_width;
1639 if( p_sys->i_maxheight && f_scale_height > (float)p_sys->i_maxheight /
1642 f_scale_height = (float)p_sys->i_maxheight / i_src_height;
1646 /* Change aspect ratio from source pixel to scaled pixel */
1647 f_aspect = f_aspect * f_scale_height / f_scale_width;
1648 msg_Dbg( p_stream, "scaled pixel aspect is %f:1", f_aspect );
1650 /* f_scale_width and f_scale_height are now final */
1651 /* Calculate width, height from scaling
1652 * Make sure its multiple of 2
1654 i_dst_width = 2 * (int)(f_scale_width*i_src_width/2+0.5);
1655 i_dst_height = 2 * (int)(f_scale_height*i_src_height/2+0.5);
1657 /* Change aspect ratio from scaled pixel to output frame */
1658 f_aspect = f_aspect * i_dst_width / i_dst_height;
1660 /* Store calculated values */
1661 id->p_encoder->fmt_out.video.i_width =
1662 id->p_encoder->fmt_out.video.i_visible_width = i_dst_width;
1663 id->p_encoder->fmt_out.video.i_height =
1664 id->p_encoder->fmt_out.video.i_visible_height = i_dst_height;
1666 id->p_encoder->fmt_in.video.i_width =
1667 id->p_encoder->fmt_in.video.i_visible_width = i_dst_width;
1668 id->p_encoder->fmt_in.video.i_height =
1669 id->p_encoder->fmt_in.video.i_visible_height = i_dst_height;
1671 msg_Dbg( p_stream, "source %ix%i, destination %ix%i",
1672 i_src_width, i_src_height,
1673 i_dst_width, i_dst_height
1676 /* Handle frame rate conversion */
1677 if( !id->p_encoder->fmt_out.video.i_frame_rate ||
1678 !id->p_encoder->fmt_out.video.i_frame_rate_base )
1680 if( id->p_decoder->fmt_out.video.i_frame_rate &&
1681 id->p_decoder->fmt_out.video.i_frame_rate_base )
1683 id->p_encoder->fmt_out.video.i_frame_rate =
1684 id->p_decoder->fmt_out.video.i_frame_rate;
1685 id->p_encoder->fmt_out.video.i_frame_rate_base =
1686 id->p_decoder->fmt_out.video.i_frame_rate_base;
1690 /* Pick a sensible default value */
1691 id->p_encoder->fmt_out.video.i_frame_rate = ENC_FRAMERATE;
1692 id->p_encoder->fmt_out.video.i_frame_rate_base = ENC_FRAMERATE_BASE;
1696 id->p_encoder->fmt_in.video.i_frame_rate =
1697 id->p_encoder->fmt_out.video.i_frame_rate;
1698 id->p_encoder->fmt_in.video.i_frame_rate_base =
1699 id->p_encoder->fmt_out.video.i_frame_rate_base;
1701 date_Init( &id->interpolated_pts,
1702 id->p_encoder->fmt_out.video.i_frame_rate,
1703 id->p_encoder->fmt_out.video.i_frame_rate_base );
1705 /* Check whether a particular aspect ratio was requested */
1706 if( !id->p_encoder->fmt_out.video.i_aspect )
1708 id->p_encoder->fmt_out.video.i_aspect =
1709 (int)( f_aspect * VOUT_ASPECT_FACTOR + 0.5 );
1711 id->p_encoder->fmt_in.video.i_aspect =
1712 id->p_encoder->fmt_out.video.i_aspect;
1714 msg_Dbg( p_stream, "encoder aspect is %i:%i",
1715 id->p_encoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
1717 id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
1720 static int transcode_video_encoder_open( sout_stream_t *p_stream,
1721 sout_stream_id_t *id )
1723 sout_stream_sys_t *p_sys = p_stream->p_sys;
1726 msg_Dbg( p_stream, "destination (after video filters) %ix%i",
1727 id->p_encoder->fmt_in.video.i_width,
1728 id->p_encoder->fmt_in.video.i_height );
1730 id->p_encoder->p_module =
1731 module_need( id->p_encoder, "encoder", p_sys->psz_venc, true );
1732 if( !id->p_encoder->p_module )
1734 msg_Err( p_stream, "cannot find video encoder (module:%s fourcc:%4.4s)",
1735 p_sys->psz_venc ? p_sys->psz_venc : "any",
1736 (char *)&p_sys->i_vcodec );
1737 return VLC_EGENERIC;
1740 id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
1742 /* Hack for mp2v/mp1v transcoding support */
1743 if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','1','v') ||
1744 id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','2','v') )
1746 id->p_encoder->fmt_out.i_codec = VLC_FOURCC('m','p','g','v');
1749 id->id = sout_StreamIdAdd( p_stream->p_sys->p_out,
1750 &id->p_encoder->fmt_out );
1753 msg_Err( p_stream, "cannot add this stream" );
1754 return VLC_EGENERIC;
1760 static void transcode_video_close( sout_stream_t *p_stream,
1761 sout_stream_id_t *id )
1765 if( p_stream->p_sys->i_threads >= 1 )
1767 vlc_mutex_lock( &p_stream->p_sys->lock_out );
1768 vlc_object_kill( p_stream->p_sys );
1769 vlc_cond_signal( &p_stream->p_sys->cond );
1770 vlc_mutex_unlock( &p_stream->p_sys->lock_out );
1771 vlc_thread_join( p_stream->p_sys );
1772 vlc_mutex_destroy( &p_stream->p_sys->lock_out );
1773 vlc_cond_destroy( &p_stream->p_sys->cond );
1776 video_timer_close( id->p_encoder );
1779 if( id->p_decoder->p_module )
1780 module_unneed( id->p_decoder, id->p_decoder->p_module );
1781 if( id->p_decoder->p_description )
1782 vlc_meta_Delete( id->p_decoder->p_description );
1784 if( id->p_decoder->p_owner )
1786 /* Clean-up pictures ring buffer */
1787 for( i = 0; i < PICTURE_RING_SIZE; i++ )
1789 if( id->p_decoder->p_owner->pp_pics[i] )
1790 video_del_buffer( VLC_OBJECT(id->p_decoder),
1791 id->p_decoder->p_owner->pp_pics[i] );
1793 free( id->p_decoder->p_owner );
1797 if( id->p_encoder->p_module )
1798 module_unneed( id->p_encoder, id->p_encoder->p_module );
1802 filter_chain_Delete( id->p_f_chain );
1803 if( id->p_uf_chain )
1804 filter_chain_Delete( id->p_uf_chain );
1807 static int transcode_video_process( sout_stream_t *p_stream,
1808 sout_stream_id_t *id,
1809 block_t *in, block_t **out )
1811 sout_stream_sys_t *p_sys = p_stream->p_sys;
1812 int i_duplicate = 1;
1813 picture_t *p_pic, *p_pic2 = NULL;
1816 while( (p_pic = id->p_decoder->pf_decode_video( id->p_decoder, &in )) )
1818 subpicture_t *p_subpic = NULL;
1820 sout_UpdateStatistic( p_stream->p_sout, SOUT_STATISTIC_DECODED_VIDEO, 1 );
1822 if( p_stream->p_sout->i_out_pace_nocontrol && p_sys->b_hurry_up )
1824 mtime_t current_date = mdate();
1825 if( current_date + 50000 > p_pic->date )
1827 msg_Dbg( p_stream, "late picture skipped (%"PRId64")",
1828 current_date + 50000 - p_pic->date );
1829 p_pic->pf_release( p_pic );
1834 if( p_sys->b_master_sync )
1836 mtime_t i_video_drift;
1837 mtime_t i_master_drift = p_sys->i_master_drift;
1840 i_pts = date_Get( &id->interpolated_pts ) + 1;
1841 if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
1842 || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
1844 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
1845 date_Set( &id->interpolated_pts, p_pic->date );
1846 i_pts = p_pic->date + 1;
1848 i_video_drift = p_pic->date - i_pts;
1851 /* Set the pts of the frame being encoded */
1852 p_pic->date = i_pts;
1854 if( i_video_drift < (i_master_drift - 50000) )
1857 msg_Dbg( p_stream, "dropping frame (%i)",
1858 (int)(i_video_drift - i_master_drift) );
1860 p_pic->pf_release( p_pic );
1863 else if( i_video_drift > (i_master_drift + 50000) )
1866 msg_Dbg( p_stream, "adding frame (%i)",
1867 (int)(i_video_drift - i_master_drift) );
1873 if( !id->p_encoder->p_module )
1875 transcode_video_encoder_init( p_stream, id );
1877 id->p_f_chain = filter_chain_New( p_stream, "video filter2",
1879 transcode_video_filter_allocation_init,
1880 transcode_video_filter_allocation_clear,
1884 if( p_stream->p_sys->b_deinterlace )
1886 filter_chain_AppendFilter( id->p_f_chain,
1887 p_sys->psz_deinterlace,
1888 p_sys->p_deinterlace_cfg,
1889 &id->p_decoder->fmt_out,
1890 &id->p_decoder->fmt_out );
1893 /* Take care of the scaling and chroma conversions */
1894 if( ( id->p_decoder->fmt_out.video.i_chroma !=
1895 id->p_encoder->fmt_in.video.i_chroma ) ||
1896 ( id->p_decoder->fmt_out.video.i_width !=
1897 id->p_encoder->fmt_in.video.i_width ) ||
1898 ( id->p_decoder->fmt_out.video.i_height !=
1899 id->p_encoder->fmt_in.video.i_height ) )
1901 filter_chain_AppendFilter( id->p_f_chain,
1903 &id->p_decoder->fmt_out,
1904 &id->p_encoder->fmt_in );
1907 if( p_sys->psz_vf2 )
1909 const es_format_t *p_fmt_out;
1910 id->p_uf_chain = filter_chain_New( p_stream, "video filter2",
1912 transcode_video_filter_allocation_init,
1913 transcode_video_filter_allocation_clear,
1915 filter_chain_Reset( id->p_uf_chain, &id->p_encoder->fmt_in,
1916 &id->p_encoder->fmt_in );
1917 filter_chain_AppendFromString( id->p_uf_chain, p_sys->psz_vf2 );
1918 p_fmt_out = filter_chain_GetFmtOut( id->p_uf_chain );
1919 es_format_Copy( &id->p_encoder->fmt_in, p_fmt_out );
1920 id->p_encoder->fmt_out.video.i_width =
1921 id->p_encoder->fmt_in.video.i_width;
1922 id->p_encoder->fmt_out.video.i_height =
1923 id->p_encoder->fmt_in.video.i_height;
1924 id->p_encoder->fmt_out.video.i_aspect =
1925 id->p_encoder->fmt_in.video.i_aspect;
1928 if( transcode_video_encoder_open( p_stream, id ) != VLC_SUCCESS )
1930 p_pic->pf_release( p_pic );
1931 transcode_video_close( p_stream, id );
1932 id->b_transcode = false;
1933 return VLC_EGENERIC;
1937 /* Run filter chain */
1939 p_pic = filter_chain_VideoFilter( id->p_f_chain, p_pic );
1945 /* Check if we have a subpicture to overlay */
1948 p_subpic = spu_SortSubpictures( p_sys->p_spu, p_pic->date,
1949 false /* Fixme: check if stream is paused */, false );
1950 /* TODO: get another pic */
1953 /* Overlay subpicture */
1958 if( p_pic->i_refcount && !filter_chain_GetLength( id->p_f_chain ) )
1960 /* We can't modify the picture, we need to duplicate it */
1961 picture_t *p_tmp = video_new_buffer_decoder( id->p_decoder );
1964 picture_Copy( p_tmp, p_pic );
1965 p_pic->pf_release( p_pic );
1970 if( filter_chain_GetLength( id->p_f_chain ) > 0 )
1971 fmt = filter_chain_GetFmtOut( id->p_f_chain )->video;
1973 fmt = id->p_decoder->fmt_out.video;
1975 /* FIXME (shouldn't have to be done here) */
1976 fmt.i_sar_num = fmt.i_aspect * fmt.i_height / fmt.i_width;
1977 fmt.i_sar_den = VOUT_ASPECT_FACTOR;
1979 spu_RenderSubpictures( p_sys->p_spu, p_pic, &fmt,
1980 p_subpic, &id->p_decoder->fmt_out.video, false );
1983 /* Run user specified filter chain */
1984 if( id->p_uf_chain )
1985 p_pic = filter_chain_VideoFilter( id->p_uf_chain, p_pic );
1987 if( p_sys->i_threads == 0 )
1991 video_timer_start( id->p_encoder );
1992 p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
1993 video_timer_stop( id->p_encoder );
1995 block_ChainAppend( out, p_block );
1998 if( p_sys->b_master_sync )
2000 mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
2001 if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2002 || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2004 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2005 date_Set( &id->interpolated_pts, p_pic->date );
2006 i_pts = p_pic->date + 1;
2008 date_Increment( &id->interpolated_pts, 1 );
2011 if( p_sys->b_master_sync && i_duplicate > 1 )
2013 mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
2014 if( (p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT)
2015 || ((p_pic->date - i_pts) < -MASTER_SYNC_MAX_DRIFT) )
2017 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2018 date_Set( &id->interpolated_pts, p_pic->date );
2019 i_pts = p_pic->date + 1;
2021 date_Increment( &id->interpolated_pts, 1 );
2023 if( p_sys->i_threads >= 1 )
2025 /* We can't modify the picture, we need to duplicate it */
2026 p_pic2 = video_new_buffer_decoder( id->p_decoder );
2027 if( p_pic2 != NULL )
2029 picture_Copy( p_pic2, p_pic );
2030 p_pic2->date = i_pts;
2036 p_pic->date = i_pts;
2037 video_timer_start( id->p_encoder );
2038 p_block = id->p_encoder->pf_encode_video(id->p_encoder, p_pic);
2039 video_timer_stop( id->p_encoder );
2040 block_ChainAppend( out, p_block );
2044 if( p_sys->i_threads == 0 )
2046 p_pic->pf_release( p_pic );
2050 vlc_mutex_lock( &p_sys->lock_out );
2051 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic;
2052 p_sys->i_last_pic %= PICTURE_RING_SIZE;
2053 *out = p_sys->p_buffers;
2054 p_sys->p_buffers = NULL;
2055 if( p_pic2 != NULL )
2057 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic2;
2058 p_sys->i_last_pic %= PICTURE_RING_SIZE;
2060 vlc_cond_signal( &p_sys->cond );
2061 vlc_mutex_unlock( &p_sys->lock_out );
2068 static void* EncoderThread( vlc_object_t* p_this )
2070 sout_stream_sys_t *p_sys = (sout_stream_sys_t*)p_this;
2071 sout_stream_id_t *id = p_sys->id_video;
2073 int canc = vlc_savecancel ();
2075 while( vlc_object_alive (p_sys) && !p_sys->b_error )
2079 vlc_mutex_lock( &p_sys->lock_out );
2080 while( p_sys->i_last_pic == p_sys->i_first_pic )
2082 vlc_cond_wait( &p_sys->cond, &p_sys->lock_out );
2083 if( !vlc_object_alive (p_sys) || p_sys->b_error ) break;
2085 if( !vlc_object_alive (p_sys) || p_sys->b_error )
2087 vlc_mutex_unlock( &p_sys->lock_out );
2091 p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2092 p_sys->i_first_pic %= PICTURE_RING_SIZE;
2093 vlc_mutex_unlock( &p_sys->lock_out );
2095 video_timer_start( id->p_encoder );
2096 p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
2097 video_timer_stop( id->p_encoder );
2099 vlc_mutex_lock( &p_sys->lock_out );
2100 block_ChainAppend( &p_sys->p_buffers, p_block );
2102 vlc_mutex_unlock( &p_sys->lock_out );
2103 p_pic->pf_release( p_pic );
2106 while( p_sys->i_last_pic != p_sys->i_first_pic )
2108 p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2109 p_sys->i_first_pic %= PICTURE_RING_SIZE;
2110 p_pic->pf_release( p_pic );
2112 block_ChainRelease( p_sys->p_buffers );
2114 vlc_restorecancel (canc);
2118 struct picture_sys_t
2120 vlc_object_t *p_owner;
2123 static void video_release_buffer( picture_t *p_pic )
2125 if( p_pic && !p_pic->i_refcount && p_pic->pf_release && p_pic->p_sys )
2127 video_del_buffer_decoder( (decoder_t *)p_pic->p_sys->p_owner, p_pic );
2129 else if( p_pic && p_pic->i_refcount > 0 ) p_pic->i_refcount--;
2132 static picture_t *video_new_buffer( vlc_object_t *p_this, picture_t **pp_ring,
2133 sout_stream_sys_t *p_sys )
2135 decoder_t *p_dec = (decoder_t *)p_this;
2139 /* Find an empty space in the picture ring buffer */
2140 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2142 if( pp_ring[i] != NULL && pp_ring[i]->i_status == DESTROYED_PICTURE )
2144 pp_ring[i]->i_status = RESERVED_PICTURE;
2148 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2150 if( pp_ring[i] == NULL ) break;
2153 if( i == PICTURE_RING_SIZE && p_sys->i_threads >= 1 )
2155 int i_first_pic = p_sys->i_first_pic;
2157 if( p_sys->i_first_pic != p_sys->i_last_pic )
2159 /* Encoder still has stuff to encode, wait to clear-up the list */
2160 while( p_sys->i_first_pic == i_first_pic )
2164 /* Find an empty space in the picture ring buffer */
2165 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2167 if( pp_ring[i] != NULL && pp_ring[i]->i_status == DESTROYED_PICTURE )
2169 pp_ring[i]->i_status = RESERVED_PICTURE;
2173 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2175 if( pp_ring[i] == NULL ) break;
2179 if( i == PICTURE_RING_SIZE )
2181 msg_Err( p_this, "decoder/filter is leaking pictures, "
2182 "resetting its ring buffer" );
2184 for( i = 0; i < PICTURE_RING_SIZE; i++ )
2186 pp_ring[i]->pf_release( pp_ring[i] );
2192 p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
2193 p_pic = picture_New( p_dec->fmt_out.video.i_chroma,
2194 p_dec->fmt_out.video.i_width,
2195 p_dec->fmt_out.video.i_height,
2196 p_dec->fmt_out.video.i_aspect );
2197 if( !p_pic ) return NULL;
2198 p_pic->p_sys = calloc( 1, sizeof(picture_sys_t) );
2201 picture_Release( p_pic );
2204 p_pic->pf_release = video_release_buffer;
2205 p_pic->i_refcount = 0;
2211 static picture_t *video_new_buffer_decoder( decoder_t *p_dec )
2213 return video_new_buffer( VLC_OBJECT(p_dec),
2214 p_dec->p_owner->pp_pics, p_dec->p_owner->p_sys );
2217 static picture_t *video_new_buffer_filter( filter_t *p_filter )
2219 return video_new_buffer( VLC_OBJECT(p_filter),
2220 p_filter->p_owner->pp_pics,
2221 p_filter->p_owner->p_sys );
2224 static void video_del_buffer( vlc_object_t *p_this, picture_t *p_pic )
2230 free( p_pic->p_data_orig );
2231 free( p_pic->p_sys );
2236 static void video_del_buffer_decoder( decoder_t *p_decoder, picture_t *p_pic )
2238 VLC_UNUSED(p_decoder);
2239 p_pic->i_refcount = 0;
2240 p_pic->i_status = DESTROYED_PICTURE;
2241 picture_CleanupQuant( p_pic );
2244 static void video_del_buffer_filter( filter_t *p_filter, picture_t *p_pic )
2246 VLC_UNUSED(p_filter);
2247 p_pic->i_refcount = 0;
2248 p_pic->i_status = DESTROYED_PICTURE;
2249 picture_CleanupQuant( p_pic );
2252 static void video_link_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2255 p_pic->i_refcount++;
2258 static void video_unlink_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2261 video_release_buffer( p_pic );
2267 static subpicture_t *spu_new_buffer( decoder_t * );
2268 static void spu_del_buffer( decoder_t *, subpicture_t * );
2270 static int transcode_spu_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2272 sout_stream_sys_t *p_sys = p_stream->p_sys;
2278 /* Initialization of decoder structures */
2279 id->p_decoder->pf_decode_sub = NULL;
2280 id->p_decoder->pf_spu_buffer_new = spu_new_buffer;
2281 id->p_decoder->pf_spu_buffer_del = spu_del_buffer;
2282 id->p_decoder->p_owner = (decoder_owner_sys_t *)p_stream;
2283 /* id->p_decoder->p_cfg = p_sys->p_spu_cfg; */
2285 id->p_decoder->p_module =
2286 module_need( id->p_decoder, "decoder", "$codec", false );
2288 if( !id->p_decoder->p_module )
2290 msg_Err( p_stream, "cannot find spu decoder" );
2291 return VLC_EGENERIC;
2294 if( !p_sys->b_soverlay )
2297 /* Initialization of encoder format structures */
2298 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
2299 id->p_decoder->fmt_in.i_codec );
2301 id->p_encoder->p_cfg = p_sys->p_spu_cfg;
2303 id->p_encoder->p_module =
2304 module_need( id->p_encoder, "encoder", p_sys->psz_senc, true );
2306 if( !id->p_encoder->p_module )
2308 module_unneed( id->p_decoder, id->p_decoder->p_module );
2309 msg_Err( p_stream, "cannot find spu encoder (%s)", p_sys->psz_senc );
2310 return VLC_EGENERIC;
2316 p_sys->p_spu = spu_Create( p_stream );
2317 spu_Init( p_sys->p_spu );
2323 static void transcode_spu_close( sout_stream_id_t *id)
2326 if( id->p_decoder->p_module )
2327 module_unneed( id->p_decoder, id->p_decoder->p_module );
2328 if( id->p_decoder->p_description )
2329 vlc_meta_Delete( id->p_decoder->p_description );
2332 if( id->p_encoder->p_module )
2333 module_unneed( id->p_encoder, id->p_encoder->p_module );
2336 static int transcode_spu_process( sout_stream_t *p_stream,
2337 sout_stream_id_t *id,
2338 block_t *in, block_t **out )
2340 sout_stream_sys_t *p_sys = p_stream->p_sys;
2341 subpicture_t *p_subpic;
2344 p_subpic = id->p_decoder->pf_decode_sub( id->p_decoder, &in );
2346 return VLC_EGENERIC;
2348 sout_UpdateStatistic( p_stream->p_sout, SOUT_STATISTIC_DECODED_SUBTITLE, 1 );
2350 if( p_sys->b_master_sync && p_sys->i_master_drift )
2352 p_subpic->i_start -= p_sys->i_master_drift;
2353 if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2356 if( p_sys->b_soverlay )
2358 spu_DisplaySubpicture( p_sys->p_spu, p_subpic );
2364 p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
2365 spu_del_buffer( id->p_decoder, p_subpic );
2368 block_ChainAppend( out, p_block );
2373 return VLC_EGENERIC;
2376 static subpicture_t *spu_new_buffer( decoder_t *p_dec )
2378 VLC_UNUSED( p_dec );
2379 return subpicture_New();
2382 static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_subpic )
2384 VLC_UNUSED( p_dec );
2385 subpicture_Delete( p_subpic );
2391 static int transcode_osd_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2393 sout_stream_sys_t *p_sys = p_stream->p_sys;
2395 id->p_decoder->fmt_in.i_cat = SPU_ES;
2396 id->p_encoder->fmt_out.psz_language = strdup( "osd" );
2398 if( p_sys->i_osdcodec != 0 || p_sys->psz_osdenc )
2400 msg_Dbg( p_stream, "creating osdmenu transcoding from fcc=`%4.4s' "
2401 "to fcc=`%4.4s'", (char*)&id->p_encoder->fmt_out.i_codec,
2402 (char*)&p_sys->i_osdcodec );
2404 /* Complete destination format */
2405 id->p_encoder->fmt_out.i_codec = p_sys->i_osdcodec;
2408 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
2409 VLC_FOURCC('Y','U','V','A') );
2410 id->p_encoder->fmt_in.psz_language = strdup( "osd" );
2412 id->p_encoder->p_cfg = p_sys->p_osd_cfg;
2414 id->p_encoder->p_module =
2415 module_need( id->p_encoder, "encoder", p_sys->psz_osdenc, true );
2417 if( !id->p_encoder->p_module )
2419 msg_Err( p_stream, "cannot find spu encoder (%s)", p_sys->psz_osdenc );
2423 /* open output stream */
2424 id->id = sout_StreamIdAdd( p_sys->p_out, &id->p_encoder->fmt_out );
2425 id->b_transcode = true;
2427 if( !id->id ) goto error;
2431 msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
2432 (char*)&id->p_decoder->fmt_out.i_codec );
2433 id->id = sout_StreamIdAdd( p_sys->p_out, &id->p_decoder->fmt_out );
2434 id->b_transcode = false;
2436 if( !id->id ) goto error;
2441 p_sys->p_spu = spu_Create( p_stream );
2442 spu_Init( p_sys->p_spu );
2448 msg_Err( p_stream, "starting osd encoding thread failed" );
2449 if( id->p_encoder->p_module )
2450 module_unneed( id->p_encoder, id->p_encoder->p_module );
2451 p_sys->b_osd = false;
2452 return VLC_EGENERIC;
2455 static void transcode_osd_close( sout_stream_t *p_stream, sout_stream_id_t *id)
2457 sout_stream_sys_t *p_sys = p_stream->p_sys;
2462 if( id->p_encoder->p_module )
2463 module_unneed( id->p_encoder, id->p_encoder->p_module );
2465 p_sys->b_osd = false;
2468 static int transcode_osd_process( sout_stream_t *p_stream,
2469 sout_stream_id_t *id,
2470 block_t *in, block_t **out )
2472 sout_stream_sys_t *p_sys = p_stream->p_sys;
2473 subpicture_t *p_subpic = NULL;
2475 /* Check if we have a subpicture to send */
2476 if( p_sys->p_spu && in->i_dts > 0)
2478 p_subpic = spu_SortSubpictures( p_sys->p_spu, in->i_dts, false, false );
2482 msg_Warn( p_stream, "spu channel not initialized, doing it now" );
2485 p_sys->p_spu = spu_Create( p_stream );
2486 spu_Init( p_sys->p_spu );
2492 block_t *p_block = NULL;
2494 if( p_sys->b_master_sync && p_sys->i_master_drift )
2496 p_subpic->i_start -= p_sys->i_master_drift;
2497 if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2500 p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
2501 subpicture_Delete( p_subpic );
2504 p_block->i_dts = p_block->i_pts = in->i_dts;
2505 block_ChainAppend( out, p_block );
2509 return VLC_EGENERIC;