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 ALANG_TEXT N_("Audio Language")
108 #define ALANG_LONGTEXT N_( \
109 "This is the language of the audio stream.")
110 #define ACHANS_TEXT N_("Audio channels")
111 #define ACHANS_LONGTEXT N_( \
112 "Number of audio channels in the transcoded streams." )
113 #define AFILTER_TEXT N_("Audio filter")
114 #define AFILTER_LONGTEXT N_( \
115 "Audio filters will be applied to the audio streams (after conversion " \
116 "filters are applied). You must enter a comma-separated list of filters." )
118 #define SENC_TEXT N_("Subtitles encoder")
119 #define SENC_LONGTEXT N_( \
120 "This is the subtitles encoder module that will be used (and its " \
121 "associated options)." )
122 #define SCODEC_TEXT N_("Destination subtitles codec")
123 #define SCODEC_LONGTEXT N_( \
124 "This is the subtitles codec that will be used." )
126 #define SFILTER_TEXT N_("Overlays")
127 #define SFILTER_LONGTEXT N_( \
128 "This allows you to add overlays (also known as \"subpictures\" on the "\
129 "transcoded video stream. The subpictures produced by the filters will "\
130 "be overlayed directly onto the video. You must specify a comma-separated "\
131 "list of subpicture modules" )
133 #define OSD_TEXT N_("OSD menu")
134 #define OSD_LONGTEXT N_(\
135 "Stream the On Screen Display menu (using the osdmenu subpicture module)." )
137 #define THREADS_TEXT N_("Number of threads")
138 #define THREADS_LONGTEXT N_( \
139 "Number of threads used for the transcoding." )
140 #define HP_TEXT N_("High priority")
141 #define HP_LONGTEXT N_( \
142 "Runs the optional encoder thread at the OUTPUT priority instead of " \
145 #define ASYNC_TEXT N_("Synchronise on audio track")
146 #define ASYNC_LONGTEXT N_( \
147 "This option will drop/duplicate video frames to synchronise the video " \
148 "track on the audio track." )
150 #define HURRYUP_TEXT N_( "Hurry up" )
151 #define HURRYUP_LONGTEXT N_( "The transcoder will drop frames if your CPU " \
152 "can't keep up with the encoding rate." )
154 static const char *const ppsz_deinterlace_type[] =
156 "deinterlace", "ffmpeg-deinterlace"
159 static int Open ( vlc_object_t * );
160 static void Close( vlc_object_t * );
162 #define SOUT_CFG_PREFIX "sout-transcode-"
165 set_shortname( N_("Transcode"))
166 set_description( N_("Transcode stream output") )
167 set_capability( "sout stream", 50 )
168 add_shortcut( "transcode" )
169 set_callbacks( Open, Close )
170 set_category( CAT_SOUT )
171 set_subcategory( SUBCAT_SOUT_STREAM )
172 set_section( N_("Video"), NULL )
173 add_module( SOUT_CFG_PREFIX "venc", "encoder", NULL, NULL, VENC_TEXT,
174 VENC_LONGTEXT, false )
175 add_string( SOUT_CFG_PREFIX "vcodec", NULL, NULL, VCODEC_TEXT,
176 VCODEC_LONGTEXT, false )
177 add_integer( SOUT_CFG_PREFIX "vb", 0, NULL, VB_TEXT,
179 add_float( SOUT_CFG_PREFIX "scale", 1, NULL, SCALE_TEXT,
180 SCALE_LONGTEXT, false )
181 add_float( SOUT_CFG_PREFIX "fps", 0, NULL, FPS_TEXT,
182 FPS_LONGTEXT, false )
183 add_bool( SOUT_CFG_PREFIX "hurry-up", true, NULL, HURRYUP_TEXT,
184 HURRYUP_LONGTEXT, false )
185 add_bool( SOUT_CFG_PREFIX "deinterlace", false, NULL, DEINTERLACE_TEXT,
186 DEINTERLACE_LONGTEXT, false )
187 add_string( SOUT_CFG_PREFIX "deinterlace-module", "deinterlace", NULL,
188 DEINTERLACE_MODULE_TEXT, DEINTERLACE_MODULE_LONGTEXT,
190 change_string_list( ppsz_deinterlace_type, 0, 0 )
191 add_integer( SOUT_CFG_PREFIX "width", 0, NULL, WIDTH_TEXT,
192 WIDTH_LONGTEXT, true )
193 add_integer( SOUT_CFG_PREFIX "height", 0, NULL, HEIGHT_TEXT,
194 HEIGHT_LONGTEXT, true )
195 add_integer( SOUT_CFG_PREFIX "maxwidth", 0, NULL, MAXWIDTH_TEXT,
196 MAXWIDTH_LONGTEXT, true )
197 add_integer( SOUT_CFG_PREFIX "maxheight", 0, NULL, MAXHEIGHT_TEXT,
198 MAXHEIGHT_LONGTEXT, true )
199 add_module_list( SOUT_CFG_PREFIX "vfilter", "video filter2",
201 VFILTER_TEXT, VFILTER_LONGTEXT, false )
203 set_section( N_("Audio"), NULL )
204 add_module( SOUT_CFG_PREFIX "aenc", "encoder", NULL, NULL, AENC_TEXT,
205 AENC_LONGTEXT, false )
206 add_string( SOUT_CFG_PREFIX "acodec", NULL, NULL, ACODEC_TEXT,
207 ACODEC_LONGTEXT, false )
208 add_integer( SOUT_CFG_PREFIX "ab", 0, NULL, AB_TEXT,
210 add_string( SOUT_CFG_PREFIX "alang", NULL, NULL, ALANG_TEXT,
211 ALANG_LONGTEXT, true )
212 add_integer( SOUT_CFG_PREFIX "channels", 0, NULL, ACHANS_TEXT,
213 ACHANS_LONGTEXT, false )
214 add_integer( SOUT_CFG_PREFIX "samplerate", 0, NULL, ARATE_TEXT,
215 ARATE_LONGTEXT, true )
216 add_bool( SOUT_CFG_PREFIX "audio-sync", false, NULL, ASYNC_TEXT,
217 ASYNC_LONGTEXT, false )
218 add_module_list( SOUT_CFG_PREFIX "afilter", "audio filter",
220 AFILTER_TEXT, AFILTER_LONGTEXT, false )
222 set_section( N_("Overlays/Subtitles"), NULL )
223 add_module( SOUT_CFG_PREFIX "senc", "encoder", NULL, NULL, SENC_TEXT,
224 SENC_LONGTEXT, false )
225 add_string( SOUT_CFG_PREFIX "scodec", NULL, NULL, SCODEC_TEXT,
226 SCODEC_LONGTEXT, false )
227 add_bool( SOUT_CFG_PREFIX "soverlay", false, NULL, SCODEC_TEXT,
228 SCODEC_LONGTEXT, false )
229 add_module_list( SOUT_CFG_PREFIX "sfilter", "video filter",
231 SFILTER_TEXT, SFILTER_LONGTEXT, false )
233 set_section( N_("On Screen Display"), NULL )
234 add_bool( SOUT_CFG_PREFIX "osd", false, NULL, OSD_TEXT,
235 OSD_LONGTEXT, false )
237 set_section( N_("Miscellaneous"), NULL )
238 add_integer( SOUT_CFG_PREFIX "threads", 0, NULL, THREADS_TEXT,
239 THREADS_LONGTEXT, true )
240 add_bool( SOUT_CFG_PREFIX "high-priority", false, NULL, HP_TEXT, HP_LONGTEXT,
245 static const char *const ppsz_sout_options[] = {
246 "venc", "vcodec", "vb",
247 "scale", "fps", "width", "height", "vfilter", "deinterlace",
248 "deinterlace-module", "threads", "hurry-up", "aenc", "acodec", "ab", "alang",
249 "afilter", "samplerate", "channels", "senc", "scodec", "soverlay",
250 "sfilter", "osd", "audio-sync", "high-priority", "maxwidth", "maxheight",
254 /*****************************************************************************
255 * Exported prototypes
256 *****************************************************************************/
257 static sout_stream_id_t *Add ( sout_stream_t *, es_format_t * );
258 static int Del ( sout_stream_t *, sout_stream_id_t * );
259 static int Send( sout_stream_t *, sout_stream_id_t *, block_t* );
261 static int transcode_audio_new ( sout_stream_t *, sout_stream_id_t * );
262 static void transcode_audio_close ( sout_stream_id_t * );
263 static int transcode_audio_process( sout_stream_t *, sout_stream_id_t *,
264 block_t *, block_t ** );
266 static aout_buffer_t *audio_new_buffer( decoder_t *, int );
267 static void audio_del_buffer( decoder_t *, aout_buffer_t * );
269 static int transcode_video_new ( sout_stream_t *, sout_stream_id_t * );
270 static void transcode_video_close ( sout_stream_t *, sout_stream_id_t * );
271 static void transcode_video_encoder_init( sout_stream_t *, sout_stream_id_t *);
272 static int transcode_video_encoder_open( sout_stream_t *, sout_stream_id_t *);
273 static int transcode_video_process( sout_stream_t *, sout_stream_id_t *,
274 block_t *, block_t ** );
276 static picture_t *video_new_buffer_decoder( decoder_t * );
277 static void video_del_buffer_decoder( decoder_t *, picture_t * );
278 static void video_link_picture_decoder( decoder_t *, picture_t * );
279 static void video_unlink_picture_decoder( decoder_t *, picture_t * );
281 static int transcode_spu_new ( sout_stream_t *, sout_stream_id_t * );
282 static void transcode_spu_close ( sout_stream_id_t * );
283 static int transcode_spu_process( sout_stream_t *, sout_stream_id_t *,
284 block_t *, block_t ** );
286 static int transcode_osd_new ( sout_stream_t *, sout_stream_id_t * );
287 static void transcode_osd_close ( sout_stream_t *, sout_stream_id_t * );
288 static int transcode_osd_process( sout_stream_t *, sout_stream_id_t *,
289 block_t *, block_t ** );
291 static void* EncoderThread( vlc_object_t * p_this );
293 static const int pi_channels_maps[6] =
296 AOUT_CHAN_CENTER, AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
297 AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
298 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
299 | AOUT_CHAN_REARRIGHT,
300 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
301 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
304 #define PICTURE_RING_SIZE 64
305 #define SUBPICTURE_RING_SIZE 20
307 #define ENC_FRAMERATE (25 * 1000 + .5)
308 #define ENC_FRAMERATE_BASE 1000
310 struct sout_stream_sys_t
314 sout_stream_t *p_out;
315 sout_stream_id_t *id_video;
317 vlc_mutex_t lock_out;
319 picture_t * pp_pics[PICTURE_RING_SIZE];
320 int i_first_pic, i_last_pic;
323 vlc_fourcc_t i_acodec; /* codec audio (0 if not transcode) */
326 config_chain_t *p_audio_cfg;
327 uint32_t i_sample_rate;
334 vlc_fourcc_t i_vcodec; /* codec video (0 if not transcode) */
336 config_chain_t *p_video_cfg;
340 unsigned int i_width, i_maxwidth;
341 unsigned int i_height, i_maxheight;
343 char *psz_deinterlace;
344 config_chain_t *p_deinterlace_cfg;
346 bool b_high_priority;
352 vlc_fourcc_t i_scodec; /* codec spu (0 if not transcode) */
355 config_chain_t *p_spu_cfg;
359 vlc_fourcc_t i_osdcodec; /* codec osd menu (0 if not transcode) */
361 config_chain_t *p_osd_cfg;
362 bool b_osd; /* true when osd es is registered */
366 mtime_t i_master_drift;
369 struct decoder_owner_sys_t
371 sout_stream_sys_t *p_sys;
374 /*****************************************************************************
376 *****************************************************************************/
377 static int Open( vlc_object_t *p_this )
379 sout_stream_t *p_stream = (sout_stream_t*)p_this;
380 sout_stream_sys_t *p_sys;
383 p_sys = vlc_object_create( p_this, sizeof( sout_stream_sys_t ) );
385 p_sys->p_out = sout_StreamNew( p_stream->p_sout, p_stream->psz_next );
388 msg_Err( p_stream, "cannot create chain" );
389 vlc_object_release( p_sys );
393 p_sys->i_master_drift = 0;
395 config_ChainParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
398 /* Audio transcoding parameters */
399 var_Get( p_stream, SOUT_CFG_PREFIX "aenc", &val );
400 p_sys->psz_aenc = NULL;
401 p_sys->p_audio_cfg = NULL;
402 if( val.psz_string && *val.psz_string )
405 psz_next = config_ChainCreate( &p_sys->psz_aenc, &p_sys->p_audio_cfg,
409 free( val.psz_string );
411 var_Get( p_stream, SOUT_CFG_PREFIX "acodec", &val );
413 if( val.psz_string && *val.psz_string )
416 memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
417 p_sys->i_acodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
419 free( val.psz_string );
421 p_sys->psz_alang = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "alang" );
423 var_Get( p_stream, SOUT_CFG_PREFIX "ab", &val );
424 p_sys->i_abitrate = val.i_int;
425 if( p_sys->i_abitrate < 4000 ) p_sys->i_abitrate *= 1000;
427 var_Get( p_stream, SOUT_CFG_PREFIX "samplerate", &val );
428 p_sys->i_sample_rate = val.i_int;
430 var_Get( p_stream, SOUT_CFG_PREFIX "channels", &val );
431 p_sys->i_channels = val.i_int;
433 if( p_sys->i_acodec )
435 if( ( p_sys->i_acodec == VLC_CODEC_MP3 ||
436 p_sys->i_acodec == VLC_CODEC_MPGA ) && p_sys->i_channels > 2 )
438 msg_Warn( p_stream, "%d channels invalid for mp3, forcing to 2",
440 p_sys->i_channels = 2;
442 msg_Dbg( p_stream, "codec audio=%4.4s %dHz %d channels %dKb/s",
443 (char *)&p_sys->i_acodec, p_sys->i_sample_rate,
444 p_sys->i_channels, p_sys->i_abitrate / 1000 );
447 var_Get( p_stream, SOUT_CFG_PREFIX "afilter", &val );
448 if( val.psz_string && *val.psz_string )
449 p_sys->psz_af2 = val.psz_string;
452 free( val.psz_string );
453 p_sys->psz_af2 = NULL;
456 /* Video transcoding parameters */
457 var_Get( p_stream, SOUT_CFG_PREFIX "venc", &val );
458 p_sys->psz_venc = NULL;
459 p_sys->p_video_cfg = NULL;
460 if( val.psz_string && *val.psz_string )
463 psz_next = config_ChainCreate( &p_sys->psz_venc, &p_sys->p_video_cfg,
467 free( val.psz_string );
469 var_Get( p_stream, SOUT_CFG_PREFIX "vcodec", &val );
471 if( val.psz_string && *val.psz_string )
474 memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
475 p_sys->i_vcodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
477 free( val.psz_string );
479 var_Get( p_stream, SOUT_CFG_PREFIX "vb", &val );
480 p_sys->i_vbitrate = val.i_int;
481 if( p_sys->i_vbitrate < 16000 ) p_sys->i_vbitrate *= 1000;
483 var_Get( p_stream, SOUT_CFG_PREFIX "scale", &val );
484 p_sys->f_scale = val.f_float;
486 var_Get( p_stream, SOUT_CFG_PREFIX "fps", &val );
487 p_sys->f_fps = val.f_float;
489 var_Get( p_stream, SOUT_CFG_PREFIX "hurry-up", &val );
490 p_sys->b_hurry_up = val.b_bool;
492 var_Get( p_stream, SOUT_CFG_PREFIX "width", &val );
493 p_sys->i_width = val.i_int;
495 var_Get( p_stream, SOUT_CFG_PREFIX "height", &val );
496 p_sys->i_height = val.i_int;
498 var_Get( p_stream, SOUT_CFG_PREFIX "maxwidth", &val );
499 p_sys->i_maxwidth = val.i_int;
501 var_Get( p_stream, SOUT_CFG_PREFIX "maxheight", &val );
502 p_sys->i_maxheight = val.i_int;
504 var_Get( p_stream, SOUT_CFG_PREFIX "vfilter", &val );
505 if( val.psz_string && *val.psz_string )
506 p_sys->psz_vf2 = val.psz_string;
509 free( val.psz_string );
510 p_sys->psz_vf2 = NULL;
513 var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace", &val );
514 p_sys->b_deinterlace = val.b_bool;
516 var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace-module", &val );
517 p_sys->psz_deinterlace = NULL;
518 p_sys->p_deinterlace_cfg = NULL;
519 if( val.psz_string && *val.psz_string )
522 psz_next = config_ChainCreate( &p_sys->psz_deinterlace,
523 &p_sys->p_deinterlace_cfg,
527 free( val.psz_string );
529 var_Get( p_stream, SOUT_CFG_PREFIX "threads", &val );
530 p_sys->i_threads = val.i_int;
531 var_Get( p_stream, SOUT_CFG_PREFIX "high-priority", &val );
532 p_sys->b_high_priority = val.b_bool;
534 if( p_sys->i_vcodec )
536 msg_Dbg( p_stream, "codec video=%4.4s %dx%d scaling: %f %dkb/s",
537 (char *)&p_sys->i_vcodec, p_sys->i_width, p_sys->i_height,
538 p_sys->f_scale, p_sys->i_vbitrate / 1000 );
541 /* Subpictures transcoding parameters */
543 p_sys->psz_senc = NULL;
544 p_sys->p_spu_cfg = NULL;
547 var_Get( p_stream, SOUT_CFG_PREFIX "senc", &val );
548 if( val.psz_string && *val.psz_string )
551 psz_next = config_ChainCreate( &p_sys->psz_senc, &p_sys->p_spu_cfg,
555 free( val.psz_string );
557 var_Get( p_stream, SOUT_CFG_PREFIX "scodec", &val );
558 if( val.psz_string && *val.psz_string )
561 memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
562 p_sys->i_scodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
564 free( val.psz_string );
566 if( p_sys->i_scodec )
568 msg_Dbg( p_stream, "codec spu=%4.4s", (char *)&p_sys->i_scodec );
571 var_Get( p_stream, SOUT_CFG_PREFIX "soverlay", &val );
572 p_sys->b_soverlay = val.b_bool;
574 var_Get( p_stream, SOUT_CFG_PREFIX "sfilter", &val );
575 if( val.psz_string && *val.psz_string )
577 p_sys->p_spu = spu_Create( p_stream );
578 var_Create( p_sys->p_spu, "sub-filter", VLC_VAR_STRING );
579 var_Set( p_sys->p_spu, "sub-filter", val );
580 spu_Init( p_sys->p_spu );
582 free( val.psz_string );
584 /* OSD menu transcoding parameters */
585 p_sys->psz_osdenc = NULL;
586 p_sys->p_osd_cfg = NULL;
587 p_sys->i_osdcodec = 0;
588 p_sys->b_osd = false;
590 var_Get( p_stream, SOUT_CFG_PREFIX "osd", &val );
596 psz_next = config_ChainCreate( &p_sys->psz_osdenc,
597 &p_sys->p_osd_cfg, strdup( "dvbsub") );
600 p_sys->i_osdcodec = VLC_CODEC_YUVP;
602 msg_Dbg( p_stream, "codec osd=%4.4s", (char *)&p_sys->i_osdcodec );
606 osd_val.psz_string = strdup("osdmenu");
607 p_sys->p_spu = spu_Create( p_stream );
608 var_Create( p_sys->p_spu, "sub-filter", VLC_VAR_STRING );
609 var_Set( p_sys->p_spu, "sub-filter", osd_val );
610 spu_Init( p_sys->p_spu );
611 free( osd_val.psz_string );
615 osd_val.psz_string = strdup("osdmenu");
616 var_Set( p_sys->p_spu, "sub-filter", osd_val );
617 free( osd_val.psz_string );
622 var_Get( p_stream, SOUT_CFG_PREFIX "audio-sync", &val );
623 p_sys->b_master_sync = val.b_bool;
624 if( p_sys->f_fps > 0 ) p_sys->b_master_sync = true;
626 p_stream->pf_add = Add;
627 p_stream->pf_del = Del;
628 p_stream->pf_send = Send;
629 p_stream->p_sys = p_sys;
634 /*****************************************************************************
636 *****************************************************************************/
637 static void Close( vlc_object_t * p_this )
639 sout_stream_t *p_stream = (sout_stream_t*)p_this;
640 sout_stream_sys_t *p_sys = p_stream->p_sys;
642 sout_StreamDelete( p_sys->p_out );
644 free( p_sys->psz_af2 );
646 config_ChainDestroy( p_sys->p_audio_cfg );
647 free( p_sys->psz_aenc );
648 free( p_sys->psz_alang );
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;
725 if( p_sys->psz_alang )
726 id->p_encoder->fmt_out.psz_language = strdup( p_sys->psz_alang );
727 else if( p_fmt->psz_language )
728 id->p_encoder->fmt_out.psz_language = strdup( p_fmt->psz_language );
730 if( p_fmt->i_cat == AUDIO_ES && (p_sys->i_acodec || p_sys->psz_aenc) )
733 "creating audio transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
734 (char*)&p_fmt->i_codec, (char*)&p_sys->i_acodec );
736 /* Complete destination format */
737 id->p_encoder->fmt_out.i_codec = p_sys->i_acodec;
738 id->p_encoder->fmt_out.audio.i_rate = p_sys->i_sample_rate > 0 ?
739 p_sys->i_sample_rate : p_fmt->audio.i_rate;
740 id->p_encoder->fmt_out.i_bitrate = p_sys->i_abitrate;
741 id->p_encoder->fmt_out.audio.i_bitspersample =
742 p_fmt->audio.i_bitspersample;
743 id->p_encoder->fmt_out.audio.i_channels = p_sys->i_channels > 0 ?
744 p_sys->i_channels : p_fmt->audio.i_channels;
745 /* Sanity check for audio channels */
746 id->p_encoder->fmt_out.audio.i_channels =
747 __MIN( id->p_encoder->fmt_out.audio.i_channels,
748 id->p_decoder->fmt_in.audio.i_channels );
749 id->p_encoder->fmt_out.audio.i_original_channels =
750 id->p_decoder->fmt_in.audio.i_physical_channels;
751 if( id->p_decoder->fmt_in.audio.i_channels ==
752 id->p_encoder->fmt_out.audio.i_channels )
754 id->p_encoder->fmt_out.audio.i_physical_channels =
755 id->p_decoder->fmt_in.audio.i_physical_channels;
759 id->p_encoder->fmt_out.audio.i_physical_channels =
760 pi_channels_maps[id->p_encoder->fmt_out.audio.i_channels];
763 /* Build decoder -> filter -> encoder chain */
764 if( transcode_audio_new( p_stream, id ) )
766 msg_Err( p_stream, "cannot create audio chain" );
770 /* Open output stream */
771 id->id = sout_StreamIdAdd( p_sys->p_out, &id->p_encoder->fmt_out );
772 id->b_transcode = true;
776 transcode_audio_close( id );
780 date_Init( &id->interpolated_pts, p_fmt->audio.i_rate, 1 );
782 else if( p_fmt->i_cat == VIDEO_ES &&
783 (p_sys->i_vcodec != 0 || p_sys->psz_venc) )
786 "creating video transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
787 (char*)&p_fmt->i_codec, (char*)&p_sys->i_vcodec );
789 /* Complete destination format */
790 id->p_encoder->fmt_out.i_codec = p_sys->i_vcodec;
791 id->p_encoder->fmt_out.video.i_width = p_sys->i_width & ~1;
792 id->p_encoder->fmt_out.video.i_height = p_sys->i_height & ~1;
793 id->p_encoder->fmt_out.i_bitrate = p_sys->i_vbitrate;
795 /* Build decoder -> filter -> encoder chain */
796 if( transcode_video_new( p_stream, id ) )
798 msg_Err( p_stream, "cannot create video chain" );
802 /* Stream will be added later on because we don't know
803 * all the characteristics of the decoded stream yet */
804 id->b_transcode = true;
806 if( p_sys->f_fps > 0 )
808 id->p_encoder->fmt_out.video.i_frame_rate =
809 (p_sys->f_fps * 1000) + 0.5;
810 id->p_encoder->fmt_out.video.i_frame_rate_base =
814 else if( ( p_fmt->i_cat == SPU_ES ) &&
815 ( p_sys->i_scodec || p_sys->psz_senc ) )
817 msg_Dbg( p_stream, "creating subtitles transcoding from fcc=`%4.4s' "
818 "to fcc=`%4.4s'", (char*)&p_fmt->i_codec,
819 (char*)&p_sys->i_scodec );
821 /* Complete destination format */
822 id->p_encoder->fmt_out.i_codec = p_sys->i_scodec;
824 /* build decoder -> filter -> encoder */
825 if( transcode_spu_new( p_stream, id ) )
827 msg_Err( p_stream, "cannot create subtitles chain" );
831 /* open output stream */
832 id->id = sout_StreamIdAdd( p_sys->p_out, &id->p_encoder->fmt_out );
833 id->b_transcode = true;
837 transcode_spu_close( id );
841 else if( p_fmt->i_cat == SPU_ES && p_sys->b_soverlay )
843 msg_Dbg( p_stream, "subtitles (fcc=`%4.4s') overlaying",
844 (char*)&p_fmt->i_codec );
846 id->b_transcode = true;
848 /* Build decoder -> filter -> overlaying chain */
849 if( transcode_spu_new( p_stream, id ) )
851 msg_Err( p_stream, "cannot create subtitles chain" );
855 else if( !p_sys->b_osd && (p_sys->i_osdcodec != 0 || p_sys->psz_osdenc) )
857 msg_Dbg( p_stream, "creating osd transcoding from fcc=`%4.4s' "
858 "to fcc=`%4.4s'", (char*)&p_fmt->i_codec,
859 (char*)&p_sys->i_scodec );
861 id->b_transcode = true;
863 /* Create a fake OSD menu elementary stream */
864 if( transcode_osd_new( p_stream, id ) )
866 msg_Err( p_stream, "cannot create osd chain" );
873 msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
874 (char*)&p_fmt->i_codec );
875 id->id = sout_StreamIdAdd( p_sys->p_out, p_fmt );
876 id->b_transcode = false;
878 if( !id->id ) goto error;
888 vlc_object_detach( id->p_decoder );
889 vlc_object_release( id->p_decoder );
890 id->p_decoder = NULL;
895 vlc_object_detach( id->p_encoder );
896 es_format_Clean( &id->p_encoder->fmt_out );
897 vlc_object_release( id->p_encoder );
898 id->p_encoder = NULL;
906 static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
908 sout_stream_sys_t *p_sys = p_stream->p_sys;
910 if( id->b_transcode )
912 switch( id->p_decoder->fmt_in.i_cat )
915 transcode_audio_close( id );
918 transcode_video_close( p_stream, id );
922 transcode_osd_close( p_stream, id );
924 transcode_spu_close( id );
929 if( id->id ) sout_StreamIdDel( p_sys->p_out, id->id );
933 vlc_object_detach( id->p_decoder );
934 vlc_object_release( id->p_decoder );
935 id->p_decoder = NULL;
940 vlc_object_detach( id->p_encoder );
941 es_format_Clean( &id->p_encoder->fmt_out );
942 vlc_object_release( id->p_encoder );
943 id->p_encoder = NULL;
950 static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
953 sout_stream_sys_t *p_sys = p_stream->p_sys;
954 block_t *p_out = NULL;
956 if( !id->b_transcode )
959 return sout_StreamIdSend( p_sys->p_out, id->id, p_buffer );
961 block_Release( p_buffer );
965 switch( id->p_decoder->fmt_in.i_cat )
968 transcode_audio_process( p_stream, id, p_buffer, &p_out );
972 if( transcode_video_process( p_stream, id, p_buffer, &p_out )
980 /* Transcode OSD menu pictures. */
983 if( transcode_osd_process( p_stream, id, p_buffer, &p_out ) !=
989 else if ( transcode_spu_process( p_stream, id, p_buffer, &p_out ) !=
998 block_Release( p_buffer );
1003 return sout_StreamIdSend( p_sys->p_out, id->id, p_out );
1007 /****************************************************************************
1009 ****************************************************************************/
1010 static inline void video_timer_start( encoder_t * p_encoder )
1012 stats_TimerStart( p_encoder, "encoding video frame",
1013 STATS_TIMER_VIDEO_FRAME_ENCODING );
1016 static inline void video_timer_stop( encoder_t * p_encoder )
1018 stats_TimerStop( p_encoder, STATS_TIMER_VIDEO_FRAME_ENCODING );
1021 static inline void video_timer_close( encoder_t * p_encoder )
1023 stats_TimerDump( p_encoder, STATS_TIMER_VIDEO_FRAME_ENCODING );
1024 stats_TimerClean( p_encoder, STATS_TIMER_VIDEO_FRAME_ENCODING );
1027 static inline void audio_timer_start( encoder_t * p_encoder )
1029 stats_TimerStart( p_encoder, "encoding audio frame",
1030 STATS_TIMER_AUDIO_FRAME_ENCODING );
1033 static inline void audio_timer_stop( encoder_t * p_encoder )
1035 stats_TimerStop( p_encoder, STATS_TIMER_AUDIO_FRAME_ENCODING );
1038 static inline void audio_timer_close( encoder_t * p_encoder )
1040 stats_TimerDump( p_encoder, STATS_TIMER_AUDIO_FRAME_ENCODING );
1041 stats_TimerClean( p_encoder, STATS_TIMER_AUDIO_FRAME_ENCODING );
1044 /****************************************************************************
1045 * decoder reencoder part
1046 ****************************************************************************/
1048 static block_t *transcode_audio_alloc( filter_t *p_filter, int size )
1050 VLC_UNUSED( p_filter );
1051 return block_Alloc( size );
1054 static int transcode_audio_filter_allocation_init( filter_t *p_filter,
1058 p_filter->pf_audio_buffer_new = transcode_audio_alloc;
1062 static bool transcode_audio_filter_needed( const es_format_t *p_fmt1, const es_format_t *p_fmt2 )
1064 if( p_fmt1->i_codec != p_fmt2->i_codec ||
1065 p_fmt1->audio.i_channels != p_fmt2->audio.i_channels ||
1066 p_fmt1->audio.i_rate != p_fmt2->audio.i_rate )
1070 static int transcode_audio_filter_chain_build( sout_stream_t *p_stream, filter_chain_t *p_chain,
1071 const es_format_t *p_dst, const es_format_t *p_src )
1073 if( !transcode_audio_filter_needed( p_dst, p_src ) )
1076 es_format_t current = *p_src;
1078 msg_Dbg( p_stream, "Looking for filter "
1079 "(%4.4s->%4.4s, channels %d->%d, rate %d->%d)",
1080 (const char *)&p_src->i_codec,
1081 (const char *)&p_dst->i_codec,
1082 p_src->audio.i_channels,
1083 p_dst->audio.i_channels,
1084 p_src->audio.i_rate,
1085 p_dst->audio.i_rate );
1087 /* If any filter is needed, convert to fl32 */
1088 if( current.i_codec != VLC_CODEC_FL32 )
1090 /* First step, convert to fl32 */
1092 current.audio.i_format = VLC_CODEC_FL32;
1094 if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, ¤t ) )
1096 msg_Err( p_stream, "Failed to find conversion filter to fl32" );
1097 return VLC_EGENERIC;
1099 current = *filter_chain_GetFmtOut( p_chain );
1102 /* Fix sample rate */
1103 if( current.audio.i_rate != p_dst->audio.i_rate )
1105 current.audio.i_rate = p_dst->audio.i_rate;
1106 if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, ¤t ) )
1108 msg_Err( p_stream, "Failed to find conversion filter for resampling" );
1109 return VLC_EGENERIC;
1111 current = *filter_chain_GetFmtOut( p_chain );
1115 if( current.audio.i_channels != p_dst->audio.i_channels )
1117 current.audio.i_channels = p_dst->audio.i_channels;
1118 current.audio.i_physical_channels = p_dst->audio.i_physical_channels;
1119 current.audio.i_original_channels = p_dst->audio.i_original_channels;
1121 if( ( !current.audio.i_physical_channels || !current.audio.i_original_channels ) &&
1122 current.audio.i_channels < 6 )
1123 current.audio.i_physical_channels =
1124 current.audio.i_original_channels = pi_channels_maps[current.audio.i_channels];
1126 if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, ¤t ) )
1128 msg_Err( p_stream, "Failed to find conversion filter for channel mixing" );
1129 return VLC_EGENERIC;
1131 current = *filter_chain_GetFmtOut( p_chain );
1134 /* And last step, convert to the requested codec */
1135 if( current.i_codec != p_dst->i_codec )
1137 current.i_codec = p_dst->i_codec;
1138 if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, ¤t ) )
1140 msg_Err( p_stream, "Failed to find conversion filter to %4.4s",
1141 (const char*)&p_dst->i_codec);
1142 return VLC_EGENERIC;
1144 current = *filter_chain_GetFmtOut( p_chain );
1147 if( transcode_audio_filter_needed( p_dst, ¤t ) )
1149 /* Weird case, a filter has side effects, doomed */
1150 msg_Err( p_stream, "Failed to create a valid audio filter chain" );
1151 return VLC_EGENERIC;
1154 msg_Dbg( p_stream, "Got complete audio filter chain" );
1158 static int transcode_audio_new( sout_stream_t *p_stream,
1159 sout_stream_id_t *id )
1161 sout_stream_sys_t *p_sys = p_stream->p_sys;
1162 es_format_t fmt_last;
1168 /* Initialization of decoder structures */
1169 id->p_decoder->fmt_out = id->p_decoder->fmt_in;
1170 id->p_decoder->fmt_out.i_extra = 0;
1171 id->p_decoder->fmt_out.p_extra = 0;
1172 id->p_decoder->pf_decode_audio = NULL;
1173 id->p_decoder->pf_aout_buffer_new = audio_new_buffer;
1174 id->p_decoder->pf_aout_buffer_del = audio_del_buffer;
1175 /* id->p_decoder->p_cfg = p_sys->p_audio_cfg; */
1177 id->p_decoder->p_module =
1178 module_need( id->p_decoder, "decoder", "$codec", false );
1179 if( !id->p_decoder->p_module )
1181 msg_Err( p_stream, "cannot find audio decoder" );
1182 return VLC_EGENERIC;
1184 id->p_decoder->fmt_out.audio.i_bitspersample =
1185 aout_BitsPerSample( id->p_decoder->fmt_out.i_codec );
1186 fmt_last = id->p_decoder->fmt_out;
1187 /* Fix AAC SBR changing number of channels and sampling rate */
1188 if( !(id->p_decoder->fmt_in.i_codec == VLC_CODEC_MP4A &&
1189 fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate &&
1190 fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels) )
1191 fmt_last.audio.i_rate = id->p_decoder->fmt_in.audio.i_rate;
1197 /* Initialization of encoder format structures */
1198 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1199 id->p_decoder->fmt_out.i_codec );
1200 id->p_encoder->fmt_in.audio.i_format = id->p_decoder->fmt_out.i_codec;
1202 id->p_encoder->fmt_in.audio.i_rate = id->p_encoder->fmt_out.audio.i_rate;
1203 id->p_encoder->fmt_in.audio.i_physical_channels =
1204 id->p_encoder->fmt_out.audio.i_physical_channels;
1205 id->p_encoder->fmt_in.audio.i_original_channels =
1206 id->p_encoder->fmt_out.audio.i_original_channels;
1207 id->p_encoder->fmt_in.audio.i_channels =
1208 id->p_encoder->fmt_out.audio.i_channels;
1209 id->p_encoder->fmt_in.audio.i_bitspersample =
1210 aout_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1212 id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
1213 id->p_encoder->p_module =
1214 module_need( id->p_encoder, "encoder", p_sys->psz_aenc, true );
1215 if( !id->p_encoder->p_module )
1217 msg_Err( p_stream, "cannot find audio encoder (module:%s fourcc:%4.4s)",
1218 p_sys->psz_aenc ? p_sys->psz_aenc : "any",
1219 (char *)&p_sys->i_acodec );
1220 module_unneed( id->p_decoder, id->p_decoder->p_module );
1221 id->p_decoder->p_module = NULL;
1222 return VLC_EGENERIC;
1224 id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
1225 id->p_encoder->fmt_in.audio.i_bitspersample =
1226 aout_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1228 /* Load user specified audio filters */
1229 if( p_sys->psz_af2 )
1231 es_format_t fmt_fl32 = fmt_last;
1233 fmt_fl32.audio.i_format = VLC_CODEC_FL32;
1234 if( transcode_audio_filter_chain_build( p_stream, id->p_uf_chain,
1235 &fmt_fl32, &fmt_last ) )
1237 transcode_audio_close( id );
1238 return VLC_EGENERIC;
1240 fmt_last = fmt_fl32;
1242 id->p_uf_chain = filter_chain_New( p_stream, "audio filter", false,
1243 transcode_audio_filter_allocation_init, NULL, NULL );
1244 filter_chain_Reset( id->p_uf_chain, &fmt_last, &fmt_fl32 );
1245 if( filter_chain_AppendFromString( id->p_uf_chain, p_sys->psz_af2 ) > 0 )
1246 fmt_last = *filter_chain_GetFmtOut( id->p_uf_chain );
1249 /* Load conversion filters */
1250 id->p_f_chain = filter_chain_New( p_stream, "audio filter", true,
1251 transcode_audio_filter_allocation_init, NULL, NULL );
1252 filter_chain_Reset( id->p_f_chain, &fmt_last, &id->p_encoder->fmt_in );
1254 if( transcode_audio_filter_chain_build( p_stream, id->p_f_chain,
1255 &id->p_encoder->fmt_in, &fmt_last ) )
1257 transcode_audio_close( id );
1258 return VLC_EGENERIC;
1260 fmt_last = id->p_encoder->fmt_in;
1263 id->p_encoder->fmt_out.i_codec =
1264 vlc_fourcc_GetCodec( AUDIO_ES, id->p_encoder->fmt_out.i_codec );
1269 static void transcode_audio_close( sout_stream_id_t *id )
1271 audio_timer_close( id->p_encoder );
1274 if( id->p_decoder->p_module )
1275 module_unneed( id->p_decoder, id->p_decoder->p_module );
1276 id->p_decoder->p_module = NULL;
1278 if( id->p_decoder->p_description )
1279 vlc_meta_Delete( id->p_decoder->p_description );
1280 id->p_decoder->p_description = NULL;
1283 if( id->p_encoder->p_module )
1284 module_unneed( id->p_encoder, id->p_encoder->p_module );
1285 id->p_encoder->p_module = NULL;
1288 if( id->p_uf_chain )
1289 filter_chain_Delete( id->p_uf_chain );
1291 filter_chain_Delete( id->p_f_chain );
1294 static int transcode_audio_process( sout_stream_t *p_stream,
1295 sout_stream_id_t *id,
1296 block_t *in, block_t **out )
1298 sout_stream_sys_t *p_sys = p_stream->p_sys;
1299 block_t *p_block, *p_audio_buf;
1302 while( (p_audio_buf = id->p_decoder->pf_decode_audio( id->p_decoder,
1305 sout_UpdateStatistic( p_stream->p_sout, SOUT_STATISTIC_DECODED_AUDIO, 1 );
1306 if( p_sys->b_master_sync )
1308 mtime_t i_dts = date_Get( &id->interpolated_pts ) + 1;
1309 if ( p_audio_buf->i_pts - i_dts > MASTER_SYNC_MAX_DRIFT
1310 || p_audio_buf->i_pts - i_dts < -MASTER_SYNC_MAX_DRIFT )
1312 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
1313 date_Set( &id->interpolated_pts, p_audio_buf->i_pts );
1314 i_dts = p_audio_buf->i_pts + 1;
1316 p_sys->i_master_drift = p_audio_buf->i_pts - i_dts;
1317 date_Increment( &id->interpolated_pts, p_audio_buf->i_nb_samples );
1318 p_audio_buf->i_pts -= p_sys->i_master_drift;
1321 p_audio_buf->i_dts = p_audio_buf->i_pts;
1323 /* Run filter chain */
1324 if( id->p_uf_chain )
1326 p_audio_buf = filter_chain_AudioFilter( id->p_uf_chain,
1332 p_audio_buf = filter_chain_AudioFilter( id->p_f_chain, p_audio_buf );
1336 p_audio_buf->i_pts = p_audio_buf->i_dts;
1338 audio_timer_start( id->p_encoder );
1339 p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf );
1340 audio_timer_stop( id->p_encoder );
1342 block_ChainAppend( out, p_block );
1343 block_Release( p_audio_buf );
1349 static aout_buffer_t *audio_new_buffer( decoder_t *p_dec, int i_samples )
1354 if( p_dec->fmt_out.audio.i_bitspersample )
1356 i_size = i_samples * p_dec->fmt_out.audio.i_bitspersample / 8 *
1357 p_dec->fmt_out.audio.i_channels;
1359 else if( p_dec->fmt_out.audio.i_bytes_per_frame &&
1360 p_dec->fmt_out.audio.i_frame_length )
1362 i_size = i_samples * p_dec->fmt_out.audio.i_bytes_per_frame /
1363 p_dec->fmt_out.audio.i_frame_length;
1367 i_size = i_samples * 4 * p_dec->fmt_out.audio.i_channels;
1370 p_block = block_New( p_dec, i_size );
1371 p_block->i_nb_samples = i_samples;
1375 static void audio_del_buffer( decoder_t *p_dec, aout_buffer_t *p_buffer )
1378 block_Release( p_buffer );
1385 static picture_t *transcode_video_filter_buffer_new( filter_t *p_filter )
1387 p_filter->fmt_out.video.i_chroma = p_filter->fmt_out.i_codec;
1388 return picture_New( p_filter->fmt_out.video.i_chroma,
1389 p_filter->fmt_out.video.i_width,
1390 p_filter->fmt_out.video.i_height,
1391 p_filter->fmt_out.video.i_aspect );
1393 static void transcode_video_filter_buffer_del( filter_t *p_filter, picture_t *p_pic )
1395 VLC_UNUSED(p_filter);
1396 picture_Release( p_pic );
1399 static int transcode_video_filter_allocation_init( filter_t *p_filter,
1403 p_filter->pf_vout_buffer_new = transcode_video_filter_buffer_new;
1404 p_filter->pf_vout_buffer_del = transcode_video_filter_buffer_del;
1408 static void transcode_video_filter_allocation_clear( filter_t *p_filter )
1410 VLC_UNUSED(p_filter);
1413 static int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_t *id )
1415 sout_stream_sys_t *p_sys = p_stream->p_sys;
1418 * Initialization of decoder structures
1420 id->p_decoder->fmt_out = id->p_decoder->fmt_in;
1421 id->p_decoder->fmt_out.i_extra = 0;
1422 id->p_decoder->fmt_out.p_extra = 0;
1423 id->p_decoder->pf_decode_video = NULL;
1424 id->p_decoder->pf_get_cc = NULL;
1425 id->p_decoder->pf_get_cc = 0;
1426 id->p_decoder->pf_vout_buffer_new = video_new_buffer_decoder;
1427 id->p_decoder->pf_vout_buffer_del = video_del_buffer_decoder;
1428 id->p_decoder->pf_picture_link = video_link_picture_decoder;
1429 id->p_decoder->pf_picture_unlink = video_unlink_picture_decoder;
1430 id->p_decoder->p_owner = malloc( sizeof(decoder_owner_sys_t) );
1431 if( !id->p_decoder->p_owner )
1432 return VLC_EGENERIC;
1434 id->p_decoder->p_owner->p_sys = p_sys;
1435 /* id->p_decoder->p_cfg = p_sys->p_video_cfg; */
1437 id->p_decoder->p_module =
1438 module_need( id->p_decoder, "decoder", "$codec", false );
1440 if( !id->p_decoder->p_module )
1442 msg_Err( p_stream, "cannot find video decoder" );
1443 free( id->p_decoder->p_owner );
1444 return VLC_EGENERIC;
1449 * Because some info about the decoded input will only be available
1450 * once the first frame is decoded, we actually only test the availability
1451 * of the encoder here.
1454 /* Initialization of encoder format structures */
1455 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1456 id->p_decoder->fmt_out.i_codec );
1457 id->p_encoder->fmt_in.video.i_chroma = id->p_decoder->fmt_out.i_codec;
1459 /* The dimensions will be set properly later on.
1460 * Just put sensible values so we can test an encoder is available. */
1461 id->p_encoder->fmt_in.video.i_width =
1462 id->p_encoder->fmt_out.video.i_width
1463 ? id->p_encoder->fmt_out.video.i_width
1464 : id->p_decoder->fmt_in.video.i_width
1465 ? id->p_decoder->fmt_in.video.i_width : 16;
1466 id->p_encoder->fmt_in.video.i_height =
1467 id->p_encoder->fmt_out.video.i_height
1468 ? id->p_encoder->fmt_out.video.i_height
1469 : id->p_decoder->fmt_in.video.i_height
1470 ? id->p_decoder->fmt_in.video.i_height : 16;
1471 id->p_encoder->fmt_in.video.i_frame_rate = ENC_FRAMERATE;
1472 id->p_encoder->fmt_in.video.i_frame_rate_base = ENC_FRAMERATE_BASE;
1474 id->p_encoder->i_threads = p_sys->i_threads;
1475 id->p_encoder->p_cfg = p_sys->p_video_cfg;
1477 id->p_encoder->p_module =
1478 module_need( id->p_encoder, "encoder", p_sys->psz_venc, true );
1479 if( !id->p_encoder->p_module )
1481 msg_Err( p_stream, "cannot find video encoder (module:%s fourcc:%4.4s)",
1482 p_sys->psz_venc ? p_sys->psz_venc : "any",
1483 (char *)&p_sys->i_vcodec );
1484 module_unneed( id->p_decoder, id->p_decoder->p_module );
1485 id->p_decoder->p_module = 0;
1486 free( id->p_decoder->p_owner );
1487 return VLC_EGENERIC;
1490 /* Close the encoder.
1491 * We'll open it only when we have the first frame. */
1492 module_unneed( id->p_encoder, id->p_encoder->p_module );
1493 if( id->p_encoder->fmt_out.p_extra )
1495 free( id->p_encoder->fmt_out.p_extra );
1496 id->p_encoder->fmt_out.p_extra = NULL;
1497 id->p_encoder->fmt_out.i_extra = 0;
1499 id->p_encoder->p_module = NULL;
1501 if( p_sys->i_threads >= 1 )
1503 int i_priority = p_sys->b_high_priority ? VLC_THREAD_PRIORITY_OUTPUT :
1504 VLC_THREAD_PRIORITY_VIDEO;
1505 p_sys->id_video = id;
1506 vlc_mutex_init( &p_sys->lock_out );
1507 vlc_cond_init( &p_sys->cond );
1508 memset( p_sys->pp_pics, 0, sizeof(p_sys->pp_pics) );
1509 p_sys->i_first_pic = 0;
1510 p_sys->i_last_pic = 0;
1511 p_sys->p_buffers = NULL;
1512 p_sys->b_die = p_sys->b_error = 0;
1513 if( vlc_thread_create( p_sys, "encoder", EncoderThread, i_priority ) )
1515 msg_Err( p_stream, "cannot spawn encoder thread" );
1516 module_unneed( id->p_decoder, id->p_decoder->p_module );
1517 id->p_decoder->p_module = 0;
1518 free( id->p_decoder->p_owner );
1519 return VLC_EGENERIC;
1526 static void transcode_video_encoder_init( sout_stream_t *p_stream,
1527 sout_stream_id_t *id )
1529 sout_stream_sys_t *p_sys = p_stream->p_sys;
1531 /* Calculate scaling
1532 * width/height of source */
1533 int i_src_width = id->p_decoder->fmt_out.video.i_width;
1534 int i_src_height = id->p_decoder->fmt_out.video.i_height;
1536 /* with/height scaling */
1537 float f_scale_width = 1;
1538 float f_scale_height = 1;
1540 /* width/height of output stream */
1545 float f_aspect = (float)id->p_decoder->fmt_out.video.i_aspect /
1548 msg_Dbg( p_stream, "decoder aspect is %i:%i",
1549 id->p_decoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
1551 /* Change f_aspect from source frame to source pixel */
1552 f_aspect = f_aspect * i_src_height / i_src_width;
1553 msg_Dbg( p_stream, "source pixel aspect is %f:1", f_aspect );
1555 /* Calculate scaling factor for specified parameters */
1556 if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1557 id->p_encoder->fmt_out.video.i_height <= 0 && p_sys->f_scale )
1559 /* Global scaling. Make sure width will remain a factor of 16 */
1562 int i_new_width = i_src_width * p_sys->f_scale;
1564 if( i_new_width % 16 <= 7 && i_new_width >= 16 )
1565 i_new_width -= i_new_width % 16;
1567 i_new_width += 16 - i_new_width % 16;
1569 f_real_scale = (float)( i_new_width ) / (float) i_src_width;
1571 i_new_height = __MAX( 16, i_src_height * (float)f_real_scale );
1573 f_scale_width = f_real_scale;
1574 f_scale_height = (float) i_new_height / (float) i_src_height;
1576 else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1577 id->p_encoder->fmt_out.video.i_height <= 0 )
1579 /* Only width specified */
1580 f_scale_width = (float)id->p_encoder->fmt_out.video.i_width/i_src_width;
1581 f_scale_height = f_scale_width;
1583 else if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1584 id->p_encoder->fmt_out.video.i_height > 0 )
1586 /* Only height specified */
1587 f_scale_height = (float)id->p_encoder->fmt_out.video.i_height/i_src_height;
1588 f_scale_width = f_scale_height;
1590 else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1591 id->p_encoder->fmt_out.video.i_height > 0 )
1593 /* Width and height specified */
1594 f_scale_width = (float)id->p_encoder->fmt_out.video.i_width/i_src_width;
1595 f_scale_height = (float)id->p_encoder->fmt_out.video.i_height/i_src_height;
1598 /* check maxwidth and maxheight
1600 if( p_sys->i_maxwidth && f_scale_width > (float)p_sys->i_maxwidth /
1603 f_scale_width = (float)p_sys->i_maxwidth / i_src_width;
1606 if( p_sys->i_maxheight && f_scale_height > (float)p_sys->i_maxheight /
1609 f_scale_height = (float)p_sys->i_maxheight / i_src_height;
1613 /* Change aspect ratio from source pixel to scaled pixel */
1614 f_aspect = f_aspect * f_scale_height / f_scale_width;
1615 msg_Dbg( p_stream, "scaled pixel aspect is %f:1", f_aspect );
1617 /* f_scale_width and f_scale_height are now final */
1618 /* Calculate width, height from scaling
1619 * Make sure its multiple of 2
1621 i_dst_width = 2 * (int)(f_scale_width*i_src_width/2+0.5);
1622 i_dst_height = 2 * (int)(f_scale_height*i_src_height/2+0.5);
1624 /* Change aspect ratio from scaled pixel to output frame */
1625 f_aspect = f_aspect * i_dst_width / i_dst_height;
1627 /* Store calculated values */
1628 id->p_encoder->fmt_out.video.i_width =
1629 id->p_encoder->fmt_out.video.i_visible_width = i_dst_width;
1630 id->p_encoder->fmt_out.video.i_height =
1631 id->p_encoder->fmt_out.video.i_visible_height = i_dst_height;
1633 id->p_encoder->fmt_in.video.i_width =
1634 id->p_encoder->fmt_in.video.i_visible_width = i_dst_width;
1635 id->p_encoder->fmt_in.video.i_height =
1636 id->p_encoder->fmt_in.video.i_visible_height = i_dst_height;
1638 msg_Dbg( p_stream, "source %ix%i, destination %ix%i",
1639 i_src_width, i_src_height,
1640 i_dst_width, i_dst_height
1643 /* Handle frame rate conversion */
1644 if( !id->p_encoder->fmt_out.video.i_frame_rate ||
1645 !id->p_encoder->fmt_out.video.i_frame_rate_base )
1647 if( id->p_decoder->fmt_out.video.i_frame_rate &&
1648 id->p_decoder->fmt_out.video.i_frame_rate_base )
1650 id->p_encoder->fmt_out.video.i_frame_rate =
1651 id->p_decoder->fmt_out.video.i_frame_rate;
1652 id->p_encoder->fmt_out.video.i_frame_rate_base =
1653 id->p_decoder->fmt_out.video.i_frame_rate_base;
1657 /* Pick a sensible default value */
1658 id->p_encoder->fmt_out.video.i_frame_rate = ENC_FRAMERATE;
1659 id->p_encoder->fmt_out.video.i_frame_rate_base = ENC_FRAMERATE_BASE;
1663 id->p_encoder->fmt_in.video.i_frame_rate =
1664 id->p_encoder->fmt_out.video.i_frame_rate;
1665 id->p_encoder->fmt_in.video.i_frame_rate_base =
1666 id->p_encoder->fmt_out.video.i_frame_rate_base;
1668 date_Init( &id->interpolated_pts,
1669 id->p_encoder->fmt_out.video.i_frame_rate,
1670 id->p_encoder->fmt_out.video.i_frame_rate_base );
1672 /* Check whether a particular aspect ratio was requested */
1673 if( !id->p_encoder->fmt_out.video.i_aspect )
1675 id->p_encoder->fmt_out.video.i_aspect =
1676 (int)( f_aspect * VOUT_ASPECT_FACTOR + 0.5 );
1678 id->p_encoder->fmt_in.video.i_aspect =
1679 id->p_encoder->fmt_out.video.i_aspect;
1681 msg_Dbg( p_stream, "encoder aspect is %i:%i",
1682 id->p_encoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
1684 id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
1687 static int transcode_video_encoder_open( sout_stream_t *p_stream,
1688 sout_stream_id_t *id )
1690 sout_stream_sys_t *p_sys = p_stream->p_sys;
1693 msg_Dbg( p_stream, "destination (after video filters) %ix%i",
1694 id->p_encoder->fmt_in.video.i_width,
1695 id->p_encoder->fmt_in.video.i_height );
1697 id->p_encoder->p_module =
1698 module_need( id->p_encoder, "encoder", p_sys->psz_venc, true );
1699 if( !id->p_encoder->p_module )
1701 msg_Err( p_stream, "cannot find video encoder (module:%s fourcc:%4.4s)",
1702 p_sys->psz_venc ? p_sys->psz_venc : "any",
1703 (char *)&p_sys->i_vcodec );
1704 return VLC_EGENERIC;
1707 id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
1710 id->p_encoder->fmt_out.i_codec =
1711 vlc_fourcc_GetCodec( VIDEO_ES, id->p_encoder->fmt_out.i_codec );
1713 id->id = sout_StreamIdAdd( p_stream->p_sys->p_out,
1714 &id->p_encoder->fmt_out );
1717 msg_Err( p_stream, "cannot add this stream" );
1718 return VLC_EGENERIC;
1724 static void transcode_video_close( sout_stream_t *p_stream,
1725 sout_stream_id_t *id )
1727 if( p_stream->p_sys->i_threads >= 1 )
1729 vlc_mutex_lock( &p_stream->p_sys->lock_out );
1730 vlc_object_kill( p_stream->p_sys );
1731 vlc_cond_signal( &p_stream->p_sys->cond );
1732 vlc_mutex_unlock( &p_stream->p_sys->lock_out );
1733 vlc_thread_join( p_stream->p_sys );
1734 vlc_mutex_destroy( &p_stream->p_sys->lock_out );
1735 vlc_cond_destroy( &p_stream->p_sys->cond );
1738 video_timer_close( id->p_encoder );
1741 if( id->p_decoder->p_module )
1742 module_unneed( id->p_decoder, id->p_decoder->p_module );
1743 if( id->p_decoder->p_description )
1744 vlc_meta_Delete( id->p_decoder->p_description );
1746 free( id->p_decoder->p_owner );
1749 if( id->p_encoder->p_module )
1750 module_unneed( id->p_encoder, id->p_encoder->p_module );
1754 filter_chain_Delete( id->p_f_chain );
1755 if( id->p_uf_chain )
1756 filter_chain_Delete( id->p_uf_chain );
1759 static int transcode_video_process( sout_stream_t *p_stream,
1760 sout_stream_id_t *id,
1761 block_t *in, block_t **out )
1763 sout_stream_sys_t *p_sys = p_stream->p_sys;
1764 int i_duplicate = 1;
1765 picture_t *p_pic, *p_pic2 = NULL;
1768 while( (p_pic = id->p_decoder->pf_decode_video( id->p_decoder, &in )) )
1770 subpicture_t *p_subpic = NULL;
1772 sout_UpdateStatistic( p_stream->p_sout, SOUT_STATISTIC_DECODED_VIDEO, 1 );
1774 if( p_stream->p_sout->i_out_pace_nocontrol && p_sys->b_hurry_up )
1776 mtime_t current_date = mdate();
1777 if( current_date + 50000 > p_pic->date )
1779 msg_Dbg( p_stream, "late picture skipped (%"PRId64")",
1780 current_date + 50000 - p_pic->date );
1781 picture_Release( p_pic );
1786 if( p_sys->b_master_sync )
1788 mtime_t i_video_drift;
1789 mtime_t i_master_drift = p_sys->i_master_drift;
1792 i_pts = date_Get( &id->interpolated_pts ) + 1;
1793 if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
1794 || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
1796 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
1797 date_Set( &id->interpolated_pts, p_pic->date );
1798 i_pts = p_pic->date + 1;
1800 i_video_drift = p_pic->date - i_pts;
1803 /* Set the pts of the frame being encoded */
1804 p_pic->date = i_pts;
1806 if( i_video_drift < (i_master_drift - 50000) )
1809 msg_Dbg( p_stream, "dropping frame (%i)",
1810 (int)(i_video_drift - i_master_drift) );
1812 picture_Release( p_pic );
1815 else if( i_video_drift > (i_master_drift + 50000) )
1818 msg_Dbg( p_stream, "adding frame (%i)",
1819 (int)(i_video_drift - i_master_drift) );
1825 if( !id->p_encoder->p_module )
1827 transcode_video_encoder_init( p_stream, id );
1829 id->p_f_chain = filter_chain_New( p_stream, "video filter2",
1831 transcode_video_filter_allocation_init,
1832 transcode_video_filter_allocation_clear,
1836 if( p_stream->p_sys->b_deinterlace )
1838 filter_chain_AppendFilter( id->p_f_chain,
1839 p_sys->psz_deinterlace,
1840 p_sys->p_deinterlace_cfg,
1841 &id->p_decoder->fmt_out,
1842 &id->p_decoder->fmt_out );
1845 /* Take care of the scaling and chroma conversions */
1846 if( ( id->p_decoder->fmt_out.video.i_chroma !=
1847 id->p_encoder->fmt_in.video.i_chroma ) ||
1848 ( id->p_decoder->fmt_out.video.i_width !=
1849 id->p_encoder->fmt_in.video.i_width ) ||
1850 ( id->p_decoder->fmt_out.video.i_height !=
1851 id->p_encoder->fmt_in.video.i_height ) )
1853 filter_chain_AppendFilter( id->p_f_chain,
1855 &id->p_decoder->fmt_out,
1856 &id->p_encoder->fmt_in );
1859 if( p_sys->psz_vf2 )
1861 const es_format_t *p_fmt_out;
1862 id->p_uf_chain = filter_chain_New( p_stream, "video filter2",
1864 transcode_video_filter_allocation_init,
1865 transcode_video_filter_allocation_clear,
1867 filter_chain_Reset( id->p_uf_chain, &id->p_encoder->fmt_in,
1868 &id->p_encoder->fmt_in );
1869 filter_chain_AppendFromString( id->p_uf_chain, p_sys->psz_vf2 );
1870 p_fmt_out = filter_chain_GetFmtOut( id->p_uf_chain );
1871 es_format_Copy( &id->p_encoder->fmt_in, p_fmt_out );
1872 id->p_encoder->fmt_out.video.i_width =
1873 id->p_encoder->fmt_in.video.i_width;
1874 id->p_encoder->fmt_out.video.i_height =
1875 id->p_encoder->fmt_in.video.i_height;
1876 id->p_encoder->fmt_out.video.i_aspect =
1877 id->p_encoder->fmt_in.video.i_aspect;
1880 if( transcode_video_encoder_open( p_stream, id ) != VLC_SUCCESS )
1882 picture_Release( p_pic );
1883 transcode_video_close( p_stream, id );
1884 id->b_transcode = false;
1885 return VLC_EGENERIC;
1889 /* Run filter chain */
1891 p_pic = filter_chain_VideoFilter( id->p_f_chain, p_pic );
1897 /* Check if we have a subpicture to overlay */
1900 p_subpic = spu_SortSubpictures( p_sys->p_spu, p_pic->date, false );
1901 /* TODO: get another pic */
1904 /* Overlay subpicture */
1909 if( picture_IsReferenced( p_pic ) && !filter_chain_GetLength( id->p_f_chain ) )
1911 /* We can't modify the picture, we need to duplicate it */
1912 picture_t *p_tmp = video_new_buffer_decoder( id->p_decoder );
1915 picture_Copy( p_tmp, p_pic );
1916 picture_Release( p_pic );
1921 if( filter_chain_GetLength( id->p_f_chain ) > 0 )
1922 fmt = filter_chain_GetFmtOut( id->p_f_chain )->video;
1924 fmt = id->p_decoder->fmt_out.video;
1926 /* FIXME (shouldn't have to be done here) */
1927 fmt.i_sar_num = fmt.i_aspect * fmt.i_height / fmt.i_width;
1928 fmt.i_sar_den = VOUT_ASPECT_FACTOR;
1930 /* FIXME the mdate() seems highly suspicious */
1931 spu_RenderSubpictures( p_sys->p_spu, p_pic, &fmt,
1932 p_subpic, &id->p_decoder->fmt_out.video, mdate() );
1935 /* Run user specified filter chain */
1936 if( id->p_uf_chain )
1937 p_pic = filter_chain_VideoFilter( id->p_uf_chain, p_pic );
1939 if( p_sys->i_threads == 0 )
1943 video_timer_start( id->p_encoder );
1944 p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
1945 video_timer_stop( id->p_encoder );
1947 block_ChainAppend( out, p_block );
1950 if( p_sys->b_master_sync )
1952 mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
1953 if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
1954 || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
1956 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
1957 date_Set( &id->interpolated_pts, p_pic->date );
1958 i_pts = p_pic->date + 1;
1960 date_Increment( &id->interpolated_pts, 1 );
1963 if( p_sys->b_master_sync && i_duplicate > 1 )
1965 mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
1966 if( (p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT)
1967 || ((p_pic->date - i_pts) < -MASTER_SYNC_MAX_DRIFT) )
1969 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
1970 date_Set( &id->interpolated_pts, p_pic->date );
1971 i_pts = p_pic->date + 1;
1973 date_Increment( &id->interpolated_pts, 1 );
1975 if( p_sys->i_threads >= 1 )
1977 /* We can't modify the picture, we need to duplicate it */
1978 p_pic2 = video_new_buffer_decoder( id->p_decoder );
1979 if( p_pic2 != NULL )
1981 picture_Copy( p_pic2, p_pic );
1982 p_pic2->date = i_pts;
1988 p_pic->date = i_pts;
1989 video_timer_start( id->p_encoder );
1990 p_block = id->p_encoder->pf_encode_video(id->p_encoder, p_pic);
1991 video_timer_stop( id->p_encoder );
1992 block_ChainAppend( out, p_block );
1996 if( p_sys->i_threads == 0 )
1998 picture_Release( p_pic );
2002 vlc_mutex_lock( &p_sys->lock_out );
2003 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic;
2004 p_sys->i_last_pic %= PICTURE_RING_SIZE;
2005 *out = p_sys->p_buffers;
2006 p_sys->p_buffers = NULL;
2007 if( p_pic2 != NULL )
2009 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic2;
2010 p_sys->i_last_pic %= PICTURE_RING_SIZE;
2012 vlc_cond_signal( &p_sys->cond );
2013 vlc_mutex_unlock( &p_sys->lock_out );
2020 static void* EncoderThread( vlc_object_t* p_this )
2022 sout_stream_sys_t *p_sys = (sout_stream_sys_t*)p_this;
2023 sout_stream_id_t *id = p_sys->id_video;
2025 int canc = vlc_savecancel ();
2027 while( vlc_object_alive (p_sys) && !p_sys->b_error )
2031 vlc_mutex_lock( &p_sys->lock_out );
2032 while( p_sys->i_last_pic == p_sys->i_first_pic )
2034 vlc_cond_wait( &p_sys->cond, &p_sys->lock_out );
2035 if( !vlc_object_alive (p_sys) || p_sys->b_error ) break;
2037 if( !vlc_object_alive (p_sys) || p_sys->b_error )
2039 vlc_mutex_unlock( &p_sys->lock_out );
2043 p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2044 p_sys->i_first_pic %= PICTURE_RING_SIZE;
2045 vlc_mutex_unlock( &p_sys->lock_out );
2047 video_timer_start( id->p_encoder );
2048 p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
2049 video_timer_stop( id->p_encoder );
2051 vlc_mutex_lock( &p_sys->lock_out );
2052 block_ChainAppend( &p_sys->p_buffers, p_block );
2054 vlc_mutex_unlock( &p_sys->lock_out );
2055 picture_Release( p_pic );
2058 while( p_sys->i_last_pic != p_sys->i_first_pic )
2060 p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2061 p_sys->i_first_pic %= PICTURE_RING_SIZE;
2062 picture_Release( p_pic );
2064 block_ChainRelease( p_sys->p_buffers );
2066 vlc_restorecancel (canc);
2070 static picture_t *video_new_buffer_decoder( decoder_t *p_dec )
2072 sout_stream_sys_t *p_ssys = p_dec->p_owner->p_sys;
2073 if( p_ssys->i_threads >= 1 )
2075 int i_first_pic = p_ssys->i_first_pic;
2077 if( p_ssys->i_first_pic != p_ssys->i_last_pic )
2079 /* Encoder still has stuff to encode, wait to clear-up the list */
2080 while( p_ssys->i_first_pic == i_first_pic )
2082 #warning THERE IS DEFINITELY A BUG! LOCKING IS INSUFFICIENT!
2089 p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
2090 return picture_New( p_dec->fmt_out.video.i_chroma,
2091 p_dec->fmt_out.video.i_width,
2092 p_dec->fmt_out.video.i_height,
2093 p_dec->fmt_out.video.i_aspect );
2096 static void video_del_buffer_decoder( decoder_t *p_decoder, picture_t *p_pic )
2098 VLC_UNUSED(p_decoder);
2099 picture_Release( p_pic );
2102 static void video_link_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2105 picture_Hold( p_pic );
2108 static void video_unlink_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2111 picture_Release( p_pic );
2117 static subpicture_t *spu_new_buffer( decoder_t * );
2118 static void spu_del_buffer( decoder_t *, subpicture_t * );
2120 static int transcode_spu_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2122 sout_stream_sys_t *p_sys = p_stream->p_sys;
2128 /* Initialization of decoder structures */
2129 id->p_decoder->pf_decode_sub = NULL;
2130 id->p_decoder->pf_spu_buffer_new = spu_new_buffer;
2131 id->p_decoder->pf_spu_buffer_del = spu_del_buffer;
2132 id->p_decoder->p_owner = (decoder_owner_sys_t *)p_stream;
2133 /* id->p_decoder->p_cfg = p_sys->p_spu_cfg; */
2135 id->p_decoder->p_module =
2136 module_need( id->p_decoder, "decoder", "$codec", false );
2138 if( !id->p_decoder->p_module )
2140 msg_Err( p_stream, "cannot find spu decoder" );
2141 return VLC_EGENERIC;
2144 if( !p_sys->b_soverlay )
2147 /* Initialization of encoder format structures */
2148 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
2149 id->p_decoder->fmt_in.i_codec );
2151 id->p_encoder->p_cfg = p_sys->p_spu_cfg;
2153 id->p_encoder->p_module =
2154 module_need( id->p_encoder, "encoder", p_sys->psz_senc, true );
2156 if( !id->p_encoder->p_module )
2158 module_unneed( id->p_decoder, id->p_decoder->p_module );
2159 msg_Err( p_stream, "cannot find spu encoder (%s)", p_sys->psz_senc );
2160 return VLC_EGENERIC;
2166 p_sys->p_spu = spu_Create( p_stream );
2167 spu_Init( p_sys->p_spu );
2173 static void transcode_spu_close( sout_stream_id_t *id)
2176 if( id->p_decoder->p_module )
2177 module_unneed( id->p_decoder, id->p_decoder->p_module );
2178 if( id->p_decoder->p_description )
2179 vlc_meta_Delete( id->p_decoder->p_description );
2182 if( id->p_encoder->p_module )
2183 module_unneed( id->p_encoder, id->p_encoder->p_module );
2186 static int transcode_spu_process( sout_stream_t *p_stream,
2187 sout_stream_id_t *id,
2188 block_t *in, block_t **out )
2190 sout_stream_sys_t *p_sys = p_stream->p_sys;
2191 subpicture_t *p_subpic;
2194 p_subpic = id->p_decoder->pf_decode_sub( id->p_decoder, &in );
2196 return VLC_EGENERIC;
2198 sout_UpdateStatistic( p_stream->p_sout, SOUT_STATISTIC_DECODED_SUBTITLE, 1 );
2200 if( p_sys->b_master_sync && p_sys->i_master_drift )
2202 p_subpic->i_start -= p_sys->i_master_drift;
2203 if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2206 if( p_sys->b_soverlay )
2208 spu_DisplaySubpicture( p_sys->p_spu, p_subpic );
2214 p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
2215 spu_del_buffer( id->p_decoder, p_subpic );
2218 block_ChainAppend( out, p_block );
2223 return VLC_EGENERIC;
2226 static subpicture_t *spu_new_buffer( decoder_t *p_dec )
2228 VLC_UNUSED( p_dec );
2229 return subpicture_New();
2232 static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_subpic )
2234 VLC_UNUSED( p_dec );
2235 subpicture_Delete( p_subpic );
2241 static int transcode_osd_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2243 sout_stream_sys_t *p_sys = p_stream->p_sys;
2245 id->p_decoder->fmt_in.i_cat = SPU_ES;
2246 id->p_encoder->fmt_out.psz_language = strdup( "osd" );
2248 if( p_sys->i_osdcodec != 0 || p_sys->psz_osdenc )
2250 msg_Dbg( p_stream, "creating osdmenu transcoding from fcc=`%4.4s' "
2251 "to fcc=`%4.4s'", (char*)&id->p_encoder->fmt_out.i_codec,
2252 (char*)&p_sys->i_osdcodec );
2254 /* Complete destination format */
2255 id->p_encoder->fmt_out.i_codec = p_sys->i_osdcodec;
2258 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
2260 id->p_encoder->fmt_in.psz_language = strdup( "osd" );
2262 id->p_encoder->p_cfg = p_sys->p_osd_cfg;
2264 id->p_encoder->p_module =
2265 module_need( id->p_encoder, "encoder", p_sys->psz_osdenc, true );
2267 if( !id->p_encoder->p_module )
2269 msg_Err( p_stream, "cannot find spu encoder (%s)", p_sys->psz_osdenc );
2273 /* open output stream */
2274 id->id = sout_StreamIdAdd( p_sys->p_out, &id->p_encoder->fmt_out );
2275 id->b_transcode = true;
2277 if( !id->id ) goto error;
2281 msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
2282 (char*)&id->p_decoder->fmt_out.i_codec );
2283 id->id = sout_StreamIdAdd( p_sys->p_out, &id->p_decoder->fmt_out );
2284 id->b_transcode = false;
2286 if( !id->id ) goto error;
2291 p_sys->p_spu = spu_Create( p_stream );
2292 spu_Init( p_sys->p_spu );
2298 msg_Err( p_stream, "starting osd encoding thread failed" );
2299 if( id->p_encoder->p_module )
2300 module_unneed( id->p_encoder, id->p_encoder->p_module );
2301 p_sys->b_osd = false;
2302 return VLC_EGENERIC;
2305 static void transcode_osd_close( sout_stream_t *p_stream, sout_stream_id_t *id)
2307 sout_stream_sys_t *p_sys = p_stream->p_sys;
2312 if( id->p_encoder->p_module )
2313 module_unneed( id->p_encoder, id->p_encoder->p_module );
2315 p_sys->b_osd = false;
2318 static int transcode_osd_process( sout_stream_t *p_stream,
2319 sout_stream_id_t *id,
2320 block_t *in, block_t **out )
2322 sout_stream_sys_t *p_sys = p_stream->p_sys;
2323 subpicture_t *p_subpic = NULL;
2325 /* Check if we have a subpicture to send */
2326 if( p_sys->p_spu && in->i_dts > 0)
2328 p_subpic = spu_SortSubpictures( p_sys->p_spu, in->i_dts, false );
2332 msg_Warn( p_stream, "spu channel not initialized, doing it now" );
2335 p_sys->p_spu = spu_Create( p_stream );
2336 spu_Init( p_sys->p_spu );
2342 block_t *p_block = NULL;
2344 if( p_sys->b_master_sync && p_sys->i_master_drift )
2346 p_subpic->i_start -= p_sys->i_master_drift;
2347 if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2350 p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
2351 subpicture_Delete( p_subpic );
2354 p_block->i_dts = p_block->i_pts = in->i_dts;
2355 block_ChainAppend( out, p_block );
2359 return VLC_EGENERIC;