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", 0, 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 picture_t *video_new_buffer_decoder( decoder_t * );
272 static void video_del_buffer_decoder( decoder_t *, picture_t * );
273 static void video_link_picture_decoder( decoder_t *, picture_t * );
274 static void video_unlink_picture_decoder( decoder_t *, picture_t * );
276 static int transcode_spu_new ( sout_stream_t *, sout_stream_id_t * );
277 static void transcode_spu_close ( sout_stream_id_t * );
278 static int transcode_spu_process( sout_stream_t *, sout_stream_id_t *,
279 block_t *, block_t ** );
281 static int transcode_osd_new ( sout_stream_t *, sout_stream_id_t * );
282 static void transcode_osd_close ( sout_stream_t *, sout_stream_id_t * );
283 static int transcode_osd_process( sout_stream_t *, sout_stream_id_t *,
284 block_t *, block_t ** );
286 static void* EncoderThread( vlc_object_t * p_this );
288 static const int pi_channels_maps[6] =
291 AOUT_CHAN_CENTER, AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
292 AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
293 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
294 | AOUT_CHAN_REARRIGHT,
295 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
296 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
299 #define PICTURE_RING_SIZE 64
300 #define SUBPICTURE_RING_SIZE 20
302 #define ENC_FRAMERATE (25 * 1000 + .5)
303 #define ENC_FRAMERATE_BASE 1000
305 struct sout_stream_sys_t
309 sout_stream_t *p_out;
310 sout_stream_id_t *id_video;
312 vlc_mutex_t lock_out;
314 picture_t * pp_pics[PICTURE_RING_SIZE];
315 int i_first_pic, i_last_pic;
318 vlc_fourcc_t i_acodec; /* codec audio (0 if not transcode) */
320 config_chain_t *p_audio_cfg;
321 uint32_t i_sample_rate;
328 vlc_fourcc_t i_vcodec; /* codec video (0 if not transcode) */
330 config_chain_t *p_video_cfg;
334 unsigned int i_width, i_maxwidth;
335 unsigned int i_height, i_maxheight;
337 char *psz_deinterlace;
338 config_chain_t *p_deinterlace_cfg;
340 bool b_high_priority;
346 vlc_fourcc_t i_scodec; /* codec spu (0 if not transcode) */
349 config_chain_t *p_spu_cfg;
353 vlc_fourcc_t i_osdcodec; /* codec osd menu (0 if not transcode) */
355 config_chain_t *p_osd_cfg;
356 bool b_osd; /* true when osd es is registered */
360 mtime_t i_master_drift;
363 struct decoder_owner_sys_t
365 sout_stream_sys_t *p_sys;
368 /*****************************************************************************
370 *****************************************************************************/
371 static int Open( vlc_object_t *p_this )
373 sout_stream_t *p_stream = (sout_stream_t*)p_this;
374 sout_stream_sys_t *p_sys;
377 p_sys = vlc_object_create( p_this, sizeof( sout_stream_sys_t ) );
379 p_sys->p_out = sout_StreamNew( p_stream->p_sout, p_stream->psz_next );
382 msg_Err( p_stream, "cannot create chain" );
383 vlc_object_release( p_sys );
387 p_sys->i_master_drift = 0;
389 config_ChainParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
392 /* Audio transcoding parameters */
393 var_Get( p_stream, SOUT_CFG_PREFIX "aenc", &val );
394 p_sys->psz_aenc = NULL;
395 p_sys->p_audio_cfg = NULL;
396 if( val.psz_string && *val.psz_string )
399 psz_next = config_ChainCreate( &p_sys->psz_aenc, &p_sys->p_audio_cfg,
403 free( val.psz_string );
405 var_Get( p_stream, SOUT_CFG_PREFIX "acodec", &val );
407 if( val.psz_string && *val.psz_string )
410 memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
411 p_sys->i_acodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
413 free( val.psz_string );
415 var_Get( p_stream, SOUT_CFG_PREFIX "ab", &val );
416 p_sys->i_abitrate = val.i_int;
417 if( p_sys->i_abitrate < 4000 ) p_sys->i_abitrate *= 1000;
419 var_Get( p_stream, SOUT_CFG_PREFIX "samplerate", &val );
420 p_sys->i_sample_rate = val.i_int;
422 var_Get( p_stream, SOUT_CFG_PREFIX "channels", &val );
423 p_sys->i_channels = val.i_int;
425 if( p_sys->i_acodec )
427 if( ( p_sys->i_acodec == VLC_CODEC_MP3 ||
428 p_sys->i_acodec == VLC_CODEC_MPGA ) && p_sys->i_channels > 2 )
430 msg_Warn( p_stream, "%d channels invalid for mp3, forcing to 2",
432 p_sys->i_channels = 2;
434 msg_Dbg( p_stream, "codec audio=%4.4s %dHz %d channels %dKb/s",
435 (char *)&p_sys->i_acodec, p_sys->i_sample_rate,
436 p_sys->i_channels, p_sys->i_abitrate / 1000 );
439 var_Get( p_stream, SOUT_CFG_PREFIX "afilter", &val );
440 if( val.psz_string && *val.psz_string )
441 p_sys->psz_af2 = val.psz_string;
444 free( val.psz_string );
445 p_sys->psz_af2 = NULL;
448 /* Video transcoding parameters */
449 var_Get( p_stream, SOUT_CFG_PREFIX "venc", &val );
450 p_sys->psz_venc = NULL;
451 p_sys->p_video_cfg = NULL;
452 if( val.psz_string && *val.psz_string )
455 psz_next = config_ChainCreate( &p_sys->psz_venc, &p_sys->p_video_cfg,
459 free( val.psz_string );
461 var_Get( p_stream, SOUT_CFG_PREFIX "vcodec", &val );
463 if( val.psz_string && *val.psz_string )
466 memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
467 p_sys->i_vcodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
469 free( val.psz_string );
471 var_Get( p_stream, SOUT_CFG_PREFIX "vb", &val );
472 p_sys->i_vbitrate = val.i_int;
473 if( p_sys->i_vbitrate < 16000 ) p_sys->i_vbitrate *= 1000;
475 var_Get( p_stream, SOUT_CFG_PREFIX "scale", &val );
476 p_sys->f_scale = val.f_float;
478 var_Get( p_stream, SOUT_CFG_PREFIX "fps", &val );
479 p_sys->f_fps = val.f_float;
481 var_Get( p_stream, SOUT_CFG_PREFIX "hurry-up", &val );
482 p_sys->b_hurry_up = val.b_bool;
484 var_Get( p_stream, SOUT_CFG_PREFIX "width", &val );
485 p_sys->i_width = val.i_int;
487 var_Get( p_stream, SOUT_CFG_PREFIX "height", &val );
488 p_sys->i_height = val.i_int;
490 var_Get( p_stream, SOUT_CFG_PREFIX "maxwidth", &val );
491 p_sys->i_maxwidth = val.i_int;
493 var_Get( p_stream, SOUT_CFG_PREFIX "maxheight", &val );
494 p_sys->i_maxheight = val.i_int;
496 var_Get( p_stream, SOUT_CFG_PREFIX "vfilter", &val );
497 if( val.psz_string && *val.psz_string )
498 p_sys->psz_vf2 = val.psz_string;
501 free( val.psz_string );
502 p_sys->psz_vf2 = NULL;
505 var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace", &val );
506 p_sys->b_deinterlace = val.b_bool;
508 var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace-module", &val );
509 p_sys->psz_deinterlace = NULL;
510 p_sys->p_deinterlace_cfg = NULL;
511 if( val.psz_string && *val.psz_string )
514 psz_next = config_ChainCreate( &p_sys->psz_deinterlace,
515 &p_sys->p_deinterlace_cfg,
519 free( val.psz_string );
521 var_Get( p_stream, SOUT_CFG_PREFIX "threads", &val );
522 p_sys->i_threads = val.i_int;
523 var_Get( p_stream, SOUT_CFG_PREFIX "high-priority", &val );
524 p_sys->b_high_priority = val.b_bool;
526 if( p_sys->i_vcodec )
528 msg_Dbg( p_stream, "codec video=%4.4s %dx%d scaling: %f %dkb/s",
529 (char *)&p_sys->i_vcodec, p_sys->i_width, p_sys->i_height,
530 p_sys->f_scale, p_sys->i_vbitrate / 1000 );
533 /* Subpictures transcoding parameters */
535 p_sys->psz_senc = NULL;
536 p_sys->p_spu_cfg = NULL;
539 var_Get( p_stream, SOUT_CFG_PREFIX "senc", &val );
540 if( val.psz_string && *val.psz_string )
543 psz_next = config_ChainCreate( &p_sys->psz_senc, &p_sys->p_spu_cfg,
547 free( val.psz_string );
549 var_Get( p_stream, SOUT_CFG_PREFIX "scodec", &val );
550 if( val.psz_string && *val.psz_string )
553 memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
554 p_sys->i_scodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
556 free( val.psz_string );
558 if( p_sys->i_scodec )
560 msg_Dbg( p_stream, "codec spu=%4.4s", (char *)&p_sys->i_scodec );
563 var_Get( p_stream, SOUT_CFG_PREFIX "soverlay", &val );
564 p_sys->b_soverlay = val.b_bool;
566 var_Get( p_stream, SOUT_CFG_PREFIX "sfilter", &val );
567 if( val.psz_string && *val.psz_string )
569 p_sys->p_spu = spu_Create( p_stream );
570 var_Create( p_sys->p_spu, "sub-filter", VLC_VAR_STRING );
571 var_Set( p_sys->p_spu, "sub-filter", val );
572 spu_Init( p_sys->p_spu );
574 free( val.psz_string );
576 /* OSD menu transcoding parameters */
577 p_sys->psz_osdenc = NULL;
578 p_sys->p_osd_cfg = NULL;
579 p_sys->i_osdcodec = 0;
580 p_sys->b_osd = false;
582 var_Get( p_stream, SOUT_CFG_PREFIX "osd", &val );
588 psz_next = config_ChainCreate( &p_sys->psz_osdenc,
589 &p_sys->p_osd_cfg, strdup( "dvbsub") );
592 p_sys->i_osdcodec = VLC_CODEC_YUVP;
594 msg_Dbg( p_stream, "codec osd=%4.4s", (char *)&p_sys->i_osdcodec );
598 osd_val.psz_string = strdup("osdmenu");
599 p_sys->p_spu = spu_Create( p_stream );
600 var_Create( p_sys->p_spu, "sub-filter", VLC_VAR_STRING );
601 var_Set( p_sys->p_spu, "sub-filter", osd_val );
602 spu_Init( p_sys->p_spu );
603 free( osd_val.psz_string );
607 osd_val.psz_string = strdup("osdmenu");
608 var_Set( p_sys->p_spu, "sub-filter", osd_val );
609 free( osd_val.psz_string );
614 var_Get( p_stream, SOUT_CFG_PREFIX "audio-sync", &val );
615 p_sys->b_master_sync = val.b_bool;
616 if( p_sys->f_fps > 0 ) p_sys->b_master_sync = true;
618 p_stream->pf_add = Add;
619 p_stream->pf_del = Del;
620 p_stream->pf_send = Send;
621 p_stream->p_sys = p_sys;
626 /*****************************************************************************
628 *****************************************************************************/
629 static void Close( vlc_object_t * p_this )
631 sout_stream_t *p_stream = (sout_stream_t*)p_this;
632 sout_stream_sys_t *p_sys = p_stream->p_sys;
634 sout_StreamDelete( p_sys->p_out );
636 free( p_sys->psz_af2 );
638 config_ChainDestroy( p_sys->p_audio_cfg );
639 free( p_sys->psz_aenc );
641 free( p_sys->psz_vf2 );
643 config_ChainDestroy( p_sys->p_video_cfg );
644 free( p_sys->psz_venc );
646 config_ChainDestroy( p_sys->p_deinterlace_cfg );
647 free( p_sys->psz_deinterlace );
649 config_ChainDestroy( p_sys->p_spu_cfg );
650 free( p_sys->psz_senc );
652 if( p_sys->p_spu ) spu_Destroy( p_sys->p_spu );
654 config_ChainDestroy( p_sys->p_osd_cfg );
655 free( p_sys->psz_osdenc );
657 vlc_object_release( p_sys );
660 struct sout_stream_id_t
664 /* id of the out stream */
668 decoder_t *p_decoder;
671 filter_chain_t *p_f_chain;
672 /* User specified filters */
673 filter_chain_t *p_uf_chain;
676 encoder_t *p_encoder;
679 date_t interpolated_pts;
682 static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
684 sout_stream_sys_t *p_sys = p_stream->p_sys;
685 sout_stream_id_t *id;
687 id = calloc( 1, sizeof( sout_stream_id_t ) );
692 id->p_decoder = NULL;
693 id->p_encoder = NULL;
695 /* Create decoder object */
696 id->p_decoder = vlc_object_create( p_stream, VLC_OBJECT_DECODER );
699 vlc_object_attach( id->p_decoder, p_stream );
700 id->p_decoder->p_module = NULL;
701 id->p_decoder->fmt_in = *p_fmt;
702 id->p_decoder->b_pace_control = true;
704 /* Create encoder object */
705 id->p_encoder = sout_EncoderCreate( p_stream );
708 vlc_object_attach( id->p_encoder, p_stream );
709 id->p_encoder->p_module = NULL;
711 /* Create destination format */
712 es_format_Init( &id->p_encoder->fmt_out, p_fmt->i_cat, 0 );
713 id->p_encoder->fmt_out.i_id = p_fmt->i_id;
714 id->p_encoder->fmt_out.i_group = p_fmt->i_group;
715 if( p_fmt->psz_language )
716 id->p_encoder->fmt_out.psz_language = strdup( p_fmt->psz_language );
718 if( p_fmt->i_cat == AUDIO_ES && (p_sys->i_acodec || p_sys->psz_aenc) )
721 "creating audio transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
722 (char*)&p_fmt->i_codec, (char*)&p_sys->i_acodec );
724 /* Complete destination format */
725 id->p_encoder->fmt_out.i_codec = p_sys->i_acodec;
726 id->p_encoder->fmt_out.audio.i_rate = p_sys->i_sample_rate > 0 ?
727 p_sys->i_sample_rate : p_fmt->audio.i_rate;
728 id->p_encoder->fmt_out.i_bitrate = p_sys->i_abitrate;
729 id->p_encoder->fmt_out.audio.i_bitspersample =
730 p_fmt->audio.i_bitspersample;
731 id->p_encoder->fmt_out.audio.i_channels = p_sys->i_channels > 0 ?
732 p_sys->i_channels : p_fmt->audio.i_channels;
733 /* Sanity check for audio channels */
734 id->p_encoder->fmt_out.audio.i_channels =
735 __MIN( id->p_encoder->fmt_out.audio.i_channels,
736 id->p_decoder->fmt_in.audio.i_channels );
737 id->p_encoder->fmt_out.audio.i_original_channels =
738 id->p_decoder->fmt_in.audio.i_physical_channels;
739 if( id->p_decoder->fmt_in.audio.i_channels ==
740 id->p_encoder->fmt_out.audio.i_channels )
742 id->p_encoder->fmt_out.audio.i_physical_channels =
743 id->p_decoder->fmt_in.audio.i_physical_channels;
747 id->p_encoder->fmt_out.audio.i_physical_channels =
748 pi_channels_maps[id->p_encoder->fmt_out.audio.i_channels];
751 /* Build decoder -> filter -> encoder chain */
752 if( transcode_audio_new( p_stream, id ) )
754 msg_Err( p_stream, "cannot create audio chain" );
758 /* Open output stream */
759 id->id = sout_StreamIdAdd( p_sys->p_out, &id->p_encoder->fmt_out );
760 id->b_transcode = true;
764 transcode_audio_close( id );
768 date_Init( &id->interpolated_pts, p_fmt->audio.i_rate, 1 );
770 else if( p_fmt->i_cat == VIDEO_ES &&
771 (p_sys->i_vcodec != 0 || p_sys->psz_venc) )
774 "creating video transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
775 (char*)&p_fmt->i_codec, (char*)&p_sys->i_vcodec );
777 /* Complete destination format */
778 id->p_encoder->fmt_out.i_codec = p_sys->i_vcodec;
779 id->p_encoder->fmt_out.video.i_width = p_sys->i_width & ~1;
780 id->p_encoder->fmt_out.video.i_height = p_sys->i_height & ~1;
781 id->p_encoder->fmt_out.i_bitrate = p_sys->i_vbitrate;
783 /* Build decoder -> filter -> encoder chain */
784 if( transcode_video_new( p_stream, id ) )
786 msg_Err( p_stream, "cannot create video chain" );
790 /* Stream will be added later on because we don't know
791 * all the characteristics of the decoded stream yet */
792 id->b_transcode = true;
794 if( p_sys->f_fps > 0 )
796 id->p_encoder->fmt_out.video.i_frame_rate =
797 (p_sys->f_fps * 1000) + 0.5;
798 id->p_encoder->fmt_out.video.i_frame_rate_base =
802 else if( ( p_fmt->i_cat == SPU_ES ) &&
803 ( p_sys->i_scodec || p_sys->psz_senc ) )
805 msg_Dbg( p_stream, "creating subtitles transcoding from fcc=`%4.4s' "
806 "to fcc=`%4.4s'", (char*)&p_fmt->i_codec,
807 (char*)&p_sys->i_scodec );
809 /* Complete destination format */
810 id->p_encoder->fmt_out.i_codec = p_sys->i_scodec;
812 /* build decoder -> filter -> encoder */
813 if( transcode_spu_new( p_stream, id ) )
815 msg_Err( p_stream, "cannot create subtitles chain" );
819 /* open output stream */
820 id->id = sout_StreamIdAdd( p_sys->p_out, &id->p_encoder->fmt_out );
821 id->b_transcode = true;
825 transcode_spu_close( id );
829 else if( p_fmt->i_cat == SPU_ES && p_sys->b_soverlay )
831 msg_Dbg( p_stream, "subtitles (fcc=`%4.4s') overlaying",
832 (char*)&p_fmt->i_codec );
834 id->b_transcode = true;
836 /* Build decoder -> filter -> overlaying chain */
837 if( transcode_spu_new( p_stream, id ) )
839 msg_Err( p_stream, "cannot create subtitles chain" );
843 else if( !p_sys->b_osd && (p_sys->i_osdcodec != 0 || p_sys->psz_osdenc) )
845 msg_Dbg( p_stream, "creating osd transcoding from fcc=`%4.4s' "
846 "to fcc=`%4.4s'", (char*)&p_fmt->i_codec,
847 (char*)&p_sys->i_scodec );
849 id->b_transcode = true;
851 /* Create a fake OSD menu elementary stream */
852 if( transcode_osd_new( p_stream, id ) )
854 msg_Err( p_stream, "cannot create osd chain" );
861 msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
862 (char*)&p_fmt->i_codec );
863 id->id = sout_StreamIdAdd( p_sys->p_out, p_fmt );
864 id->b_transcode = false;
866 if( !id->id ) goto error;
876 vlc_object_detach( id->p_decoder );
877 vlc_object_release( id->p_decoder );
878 id->p_decoder = NULL;
883 vlc_object_detach( id->p_encoder );
884 es_format_Clean( &id->p_encoder->fmt_out );
885 vlc_object_release( id->p_encoder );
886 id->p_encoder = NULL;
894 static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
896 sout_stream_sys_t *p_sys = p_stream->p_sys;
898 if( id->b_transcode )
900 switch( id->p_decoder->fmt_in.i_cat )
903 transcode_audio_close( id );
906 transcode_video_close( p_stream, id );
910 transcode_osd_close( p_stream, id );
912 transcode_spu_close( id );
917 if( id->id ) sout_StreamIdDel( p_sys->p_out, id->id );
921 vlc_object_detach( id->p_decoder );
922 vlc_object_release( id->p_decoder );
923 id->p_decoder = NULL;
928 vlc_object_detach( id->p_encoder );
929 es_format_Clean( &id->p_encoder->fmt_out );
930 vlc_object_release( id->p_encoder );
931 id->p_encoder = NULL;
938 static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
941 sout_stream_sys_t *p_sys = p_stream->p_sys;
942 block_t *p_out = NULL;
944 if( !id->b_transcode )
947 return sout_StreamIdSend( p_sys->p_out, id->id, p_buffer );
949 block_Release( p_buffer );
953 switch( id->p_decoder->fmt_in.i_cat )
956 transcode_audio_process( p_stream, id, p_buffer, &p_out );
960 if( transcode_video_process( p_stream, id, p_buffer, &p_out )
968 /* Transcode OSD menu pictures. */
971 if( transcode_osd_process( p_stream, id, p_buffer, &p_out ) !=
977 else if ( transcode_spu_process( p_stream, id, p_buffer, &p_out ) !=
986 block_Release( p_buffer );
991 return sout_StreamIdSend( p_sys->p_out, id->id, p_out );
995 /****************************************************************************
997 ****************************************************************************/
998 static inline void video_timer_start( encoder_t * p_encoder )
1000 stats_TimerStart( p_encoder, "encoding video frame",
1001 STATS_TIMER_VIDEO_FRAME_ENCODING );
1004 static inline void video_timer_stop( encoder_t * p_encoder )
1006 stats_TimerStop( p_encoder, STATS_TIMER_VIDEO_FRAME_ENCODING );
1009 static inline void video_timer_close( encoder_t * p_encoder )
1011 stats_TimerDump( p_encoder, STATS_TIMER_VIDEO_FRAME_ENCODING );
1012 stats_TimerClean( p_encoder, STATS_TIMER_VIDEO_FRAME_ENCODING );
1015 static inline void audio_timer_start( encoder_t * p_encoder )
1017 stats_TimerStart( p_encoder, "encoding audio frame",
1018 STATS_TIMER_AUDIO_FRAME_ENCODING );
1021 static inline void audio_timer_stop( encoder_t * p_encoder )
1023 stats_TimerStop( p_encoder, STATS_TIMER_AUDIO_FRAME_ENCODING );
1026 static inline void audio_timer_close( encoder_t * p_encoder )
1028 stats_TimerDump( p_encoder, STATS_TIMER_AUDIO_FRAME_ENCODING );
1029 stats_TimerClean( p_encoder, STATS_TIMER_AUDIO_FRAME_ENCODING );
1032 /****************************************************************************
1033 * decoder reencoder part
1034 ****************************************************************************/
1036 static block_t *transcode_audio_alloc( filter_t *p_filter, int size )
1038 VLC_UNUSED( p_filter );
1039 return block_Alloc( size );
1042 static int transcode_audio_filter_allocation_init( filter_t *p_filter,
1046 p_filter->pf_audio_buffer_new = transcode_audio_alloc;
1050 static bool transcode_audio_filter_needed( const es_format_t *p_fmt1, const es_format_t *p_fmt2 )
1052 if( p_fmt1->i_codec != p_fmt2->i_codec ||
1053 p_fmt1->audio.i_channels != p_fmt2->audio.i_channels ||
1054 p_fmt1->audio.i_rate != p_fmt2->audio.i_rate )
1058 static int transcode_audio_filter_chain_build( sout_stream_t *p_stream, filter_chain_t *p_chain,
1059 const es_format_t *p_dst, const es_format_t *p_src )
1061 if( !transcode_audio_filter_needed( p_dst, p_src ) )
1064 es_format_t current = *p_src;
1066 msg_Dbg( p_stream, "Looking for filter "
1067 "(%4.4s->%4.4s, channels %d->%d, rate %d->%d)",
1068 (const char *)&p_src->i_codec,
1069 (const char *)&p_dst->i_codec,
1070 p_src->audio.i_channels,
1071 p_dst->audio.i_channels,
1072 p_src->audio.i_rate,
1073 p_dst->audio.i_rate );
1075 /* If any filter is needed, convert to fl32 */
1076 if( current.i_codec != VLC_CODEC_FL32 )
1078 /* First step, convert to fl32 */
1080 current.audio.i_format = VLC_CODEC_FL32;
1082 if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, ¤t ) )
1084 msg_Err( p_stream, "Failed to find conversion filter to fl32" );
1085 return VLC_EGENERIC;
1087 current = *filter_chain_GetFmtOut( p_chain );
1090 /* Fix sample rate */
1091 if( current.audio.i_rate != p_dst->audio.i_rate )
1093 current.audio.i_rate = p_dst->audio.i_rate;
1094 if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, ¤t ) )
1096 msg_Err( p_stream, "Failed to find conversion filter for resampling" );
1097 return VLC_EGENERIC;
1099 current = *filter_chain_GetFmtOut( p_chain );
1103 if( current.audio.i_channels != p_dst->audio.i_channels )
1105 current.audio.i_channels = p_dst->audio.i_channels;
1106 current.audio.i_physical_channels = p_dst->audio.i_physical_channels;
1107 current.audio.i_original_channels = p_dst->audio.i_original_channels;
1109 if( ( !current.audio.i_physical_channels || !current.audio.i_original_channels ) &&
1110 current.audio.i_channels < 6 )
1111 current.audio.i_physical_channels =
1112 current.audio.i_original_channels = pi_channels_maps[current.audio.i_channels];
1114 if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, ¤t ) )
1116 msg_Err( p_stream, "Failed to find conversion filter for channel mixing" );
1117 return VLC_EGENERIC;
1119 current = *filter_chain_GetFmtOut( p_chain );
1122 /* And last step, convert to the requested codec */
1123 if( current.i_codec != p_dst->i_codec )
1125 current.i_codec = p_dst->i_codec;
1126 if( !filter_chain_AppendFilter( p_chain, NULL, NULL, NULL, ¤t ) )
1128 msg_Err( p_stream, "Failed to find conversion filter to %4.4s",
1129 (const char*)&p_dst->i_codec);
1130 return VLC_EGENERIC;
1132 current = *filter_chain_GetFmtOut( p_chain );
1135 if( transcode_audio_filter_needed( p_dst, ¤t ) )
1137 /* Weird case, a filter has side effects, doomed */
1138 msg_Err( p_stream, "Failed to create a valid audio filter chain" );
1139 return VLC_EGENERIC;
1142 msg_Dbg( p_stream, "Got complete audio filter chain" );
1146 static int transcode_audio_new( sout_stream_t *p_stream,
1147 sout_stream_id_t *id )
1149 sout_stream_sys_t *p_sys = p_stream->p_sys;
1150 es_format_t fmt_last;
1156 /* Initialization of decoder structures */
1157 id->p_decoder->fmt_out = id->p_decoder->fmt_in;
1158 id->p_decoder->fmt_out.i_extra = 0;
1159 id->p_decoder->fmt_out.p_extra = 0;
1160 id->p_decoder->pf_decode_audio = NULL;
1161 id->p_decoder->pf_aout_buffer_new = audio_new_buffer;
1162 id->p_decoder->pf_aout_buffer_del = audio_del_buffer;
1163 /* id->p_decoder->p_cfg = p_sys->p_audio_cfg; */
1165 id->p_decoder->p_module =
1166 module_need( id->p_decoder, "decoder", "$codec", false );
1167 if( !id->p_decoder->p_module )
1169 msg_Err( p_stream, "cannot find audio decoder" );
1170 return VLC_EGENERIC;
1172 id->p_decoder->fmt_out.audio.i_bitspersample =
1173 aout_BitsPerSample( id->p_decoder->fmt_out.i_codec );
1174 fmt_last = id->p_decoder->fmt_out;
1175 /* Fix AAC SBR changing number of channels and sampling rate */
1176 if( !(id->p_decoder->fmt_in.i_codec == VLC_CODEC_MP4A &&
1177 fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate &&
1178 fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels) )
1179 fmt_last.audio.i_rate = id->p_decoder->fmt_in.audio.i_rate;
1185 /* Initialization of encoder format structures */
1186 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1187 id->p_decoder->fmt_out.i_codec );
1188 id->p_encoder->fmt_in.audio.i_format = id->p_decoder->fmt_out.i_codec;
1190 id->p_encoder->fmt_in.audio.i_rate = id->p_encoder->fmt_out.audio.i_rate;
1191 id->p_encoder->fmt_in.audio.i_physical_channels =
1192 id->p_encoder->fmt_out.audio.i_physical_channels;
1193 id->p_encoder->fmt_in.audio.i_original_channels =
1194 id->p_encoder->fmt_out.audio.i_original_channels;
1195 id->p_encoder->fmt_in.audio.i_channels =
1196 id->p_encoder->fmt_out.audio.i_channels;
1197 id->p_encoder->fmt_in.audio.i_bitspersample =
1198 aout_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1200 id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
1201 id->p_encoder->p_module =
1202 module_need( id->p_encoder, "encoder", p_sys->psz_aenc, true );
1203 if( !id->p_encoder->p_module )
1205 msg_Err( p_stream, "cannot find audio encoder (module:%s fourcc:%4.4s)",
1206 p_sys->psz_aenc ? p_sys->psz_aenc : "any",
1207 (char *)&p_sys->i_acodec );
1208 module_unneed( id->p_decoder, id->p_decoder->p_module );
1209 id->p_decoder->p_module = NULL;
1210 return VLC_EGENERIC;
1212 id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
1213 id->p_encoder->fmt_in.audio.i_bitspersample =
1214 aout_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1216 /* Load user specified audio filters */
1217 if( p_sys->psz_af2 )
1219 es_format_t fmt_fl32 = fmt_last;
1221 fmt_fl32.audio.i_format = VLC_CODEC_FL32;
1222 if( transcode_audio_filter_chain_build( p_stream, id->p_uf_chain,
1223 &fmt_fl32, &fmt_last ) )
1225 transcode_audio_close( id );
1226 return VLC_EGENERIC;
1228 fmt_last = fmt_fl32;
1230 id->p_uf_chain = filter_chain_New( p_stream, "audio filter2", false,
1231 transcode_audio_filter_allocation_init, NULL, NULL );
1232 filter_chain_Reset( id->p_uf_chain, &fmt_last, &fmt_fl32 );
1233 if( filter_chain_AppendFromString( id->p_uf_chain, p_sys->psz_af2 ) > 0 )
1234 fmt_last = *filter_chain_GetFmtOut( id->p_uf_chain );
1237 /* Load conversion filters */
1238 id->p_f_chain = filter_chain_New( p_stream, "audio filter2", true,
1239 transcode_audio_filter_allocation_init, NULL, NULL );
1240 filter_chain_Reset( id->p_f_chain, &fmt_last, &id->p_encoder->fmt_in );
1242 if( transcode_audio_filter_chain_build( p_stream, id->p_f_chain,
1243 &id->p_encoder->fmt_in, &fmt_last ) )
1245 transcode_audio_close( id );
1246 return VLC_EGENERIC;
1248 fmt_last = id->p_encoder->fmt_in;
1251 id->p_encoder->fmt_out.i_codec =
1252 vlc_fourcc_GetCodec( AUDIO_ES, id->p_encoder->fmt_out.i_codec );
1257 static void transcode_audio_close( sout_stream_id_t *id )
1259 audio_timer_close( id->p_encoder );
1262 if( id->p_decoder->p_module )
1263 module_unneed( id->p_decoder, id->p_decoder->p_module );
1264 id->p_decoder->p_module = NULL;
1266 if( id->p_decoder->p_description )
1267 vlc_meta_Delete( id->p_decoder->p_description );
1268 id->p_decoder->p_description = NULL;
1271 if( id->p_encoder->p_module )
1272 module_unneed( id->p_encoder, id->p_encoder->p_module );
1273 id->p_encoder->p_module = NULL;
1276 if( id->p_uf_chain )
1277 filter_chain_Delete( id->p_uf_chain );
1279 filter_chain_Delete( id->p_f_chain );
1282 static int transcode_audio_process( sout_stream_t *p_stream,
1283 sout_stream_id_t *id,
1284 block_t *in, block_t **out )
1286 sout_stream_sys_t *p_sys = p_stream->p_sys;
1287 aout_buffer_t *p_audio_buf;
1288 block_t *p_block, *p_audio_block;
1291 while( (p_audio_buf = id->p_decoder->pf_decode_audio( id->p_decoder,
1294 sout_UpdateStatistic( p_stream->p_sout, SOUT_STATISTIC_DECODED_AUDIO, 1 );
1295 if( p_sys->b_master_sync )
1297 mtime_t i_dts = date_Get( &id->interpolated_pts ) + 1;
1298 if ( p_audio_buf->start_date - i_dts > MASTER_SYNC_MAX_DRIFT
1299 || p_audio_buf->start_date - i_dts < -MASTER_SYNC_MAX_DRIFT )
1301 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
1302 date_Set( &id->interpolated_pts, p_audio_buf->start_date );
1303 i_dts = p_audio_buf->start_date + 1;
1305 p_sys->i_master_drift = p_audio_buf->start_date - i_dts;
1306 date_Increment( &id->interpolated_pts, p_audio_buf->i_nb_samples );
1307 p_audio_buf->start_date -= p_sys->i_master_drift;
1308 p_audio_buf->end_date -= p_sys->i_master_drift;
1311 p_audio_block = p_audio_buf->p_sys;
1312 p_audio_block->i_buffer = p_audio_buf->i_nb_bytes;
1313 p_audio_block->i_dts = p_audio_block->i_pts =
1314 p_audio_buf->start_date;
1315 p_audio_block->i_length = p_audio_buf->end_date -
1316 p_audio_buf->start_date;
1317 p_audio_block->i_samples = p_audio_buf->i_nb_samples;
1319 /* Run filter chain */
1320 if( id->p_uf_chain )
1322 p_audio_block = filter_chain_AudioFilter( id->p_uf_chain, p_audio_block );
1323 assert( p_audio_block );
1326 p_audio_block = filter_chain_AudioFilter( id->p_f_chain, p_audio_block );
1327 assert( p_audio_block );
1329 p_audio_buf->p_buffer = p_audio_block->p_buffer;
1330 p_audio_buf->i_nb_bytes = p_audio_block->i_buffer;
1331 p_audio_buf->i_nb_samples = p_audio_block->i_samples;
1332 p_audio_buf->start_date = p_audio_block->i_dts;
1333 p_audio_buf->end_date = p_audio_block->i_dts + p_audio_block->i_length;
1335 audio_timer_start( id->p_encoder );
1336 p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf );
1337 audio_timer_stop( id->p_encoder );
1339 block_ChainAppend( out, p_block );
1340 block_Release( p_audio_block );
1341 free( p_audio_buf );
1347 static void audio_release_buffer( aout_buffer_t *p_buffer )
1349 if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
1353 static aout_buffer_t *audio_new_buffer( decoder_t *p_dec, int i_samples )
1355 aout_buffer_t *p_buffer;
1359 if( p_dec->fmt_out.audio.i_bitspersample )
1361 i_size = i_samples * p_dec->fmt_out.audio.i_bitspersample / 8 *
1362 p_dec->fmt_out.audio.i_channels;
1364 else if( p_dec->fmt_out.audio.i_bytes_per_frame &&
1365 p_dec->fmt_out.audio.i_frame_length )
1367 i_size = i_samples * p_dec->fmt_out.audio.i_bytes_per_frame /
1368 p_dec->fmt_out.audio.i_frame_length;
1372 i_size = i_samples * 4 * p_dec->fmt_out.audio.i_channels;
1375 p_buffer = malloc( sizeof(aout_buffer_t) );
1376 if( !p_buffer ) return NULL;
1377 p_buffer->b_discontinuity = false;
1378 p_buffer->pf_release = audio_release_buffer;
1379 p_buffer->p_sys = p_block = block_New( p_dec, i_size );
1381 p_buffer->p_buffer = p_block->p_buffer;
1382 p_buffer->i_size = p_buffer->i_nb_bytes = p_block->i_buffer;
1383 p_buffer->i_nb_samples = i_samples;
1384 p_block->i_samples = i_samples;
1389 static void audio_del_buffer( decoder_t *p_dec, aout_buffer_t *p_buffer )
1392 if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
1400 static picture_t *transcode_video_filter_buffer_new( filter_t *p_filter )
1402 p_filter->fmt_out.video.i_chroma = p_filter->fmt_out.i_codec;
1403 return picture_New( p_filter->fmt_out.video.i_chroma,
1404 p_filter->fmt_out.video.i_width,
1405 p_filter->fmt_out.video.i_height,
1406 p_filter->fmt_out.video.i_aspect );
1408 static void transcode_video_filter_buffer_del( filter_t *p_filter, picture_t *p_pic )
1410 VLC_UNUSED(p_filter);
1411 picture_Release( p_pic );
1414 static int transcode_video_filter_allocation_init( filter_t *p_filter,
1417 p_filter->pf_vout_buffer_new = transcode_video_filter_buffer_new;
1418 p_filter->pf_vout_buffer_del = transcode_video_filter_buffer_del;
1422 static void transcode_video_filter_allocation_clear( filter_t *p_filter )
1426 static int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_t *id )
1428 sout_stream_sys_t *p_sys = p_stream->p_sys;
1431 * Initialization of decoder structures
1433 id->p_decoder->fmt_out = id->p_decoder->fmt_in;
1434 id->p_decoder->fmt_out.i_extra = 0;
1435 id->p_decoder->fmt_out.p_extra = 0;
1436 id->p_decoder->pf_decode_video = NULL;
1437 id->p_decoder->pf_get_cc = NULL;
1438 id->p_decoder->pf_get_cc = 0;
1439 id->p_decoder->pf_vout_buffer_new = video_new_buffer_decoder;
1440 id->p_decoder->pf_vout_buffer_del = video_del_buffer_decoder;
1441 id->p_decoder->pf_picture_link = video_link_picture_decoder;
1442 id->p_decoder->pf_picture_unlink = video_unlink_picture_decoder;
1443 id->p_decoder->p_owner = malloc( sizeof(decoder_owner_sys_t) );
1444 if( !id->p_decoder->p_owner )
1445 return VLC_EGENERIC;
1447 id->p_decoder->p_owner->p_sys = p_sys;
1448 /* id->p_decoder->p_cfg = p_sys->p_video_cfg; */
1450 id->p_decoder->p_module =
1451 module_need( id->p_decoder, "decoder", "$codec", false );
1453 if( !id->p_decoder->p_module )
1455 msg_Err( p_stream, "cannot find video decoder" );
1456 free( id->p_decoder->p_owner );
1457 return VLC_EGENERIC;
1462 * Because some info about the decoded input will only be available
1463 * once the first frame is decoded, we actually only test the availability
1464 * of the encoder here.
1467 /* Initialization of encoder format structures */
1468 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1469 id->p_decoder->fmt_out.i_codec );
1470 id->p_encoder->fmt_in.video.i_chroma = id->p_decoder->fmt_out.i_codec;
1472 /* The dimensions will be set properly later on.
1473 * Just put sensible values so we can test an encoder is available. */
1474 id->p_encoder->fmt_in.video.i_width =
1475 id->p_encoder->fmt_out.video.i_width
1476 ? id->p_encoder->fmt_out.video.i_width
1477 : id->p_decoder->fmt_in.video.i_width
1478 ? id->p_decoder->fmt_in.video.i_width : 16;
1479 id->p_encoder->fmt_in.video.i_height =
1480 id->p_encoder->fmt_out.video.i_height
1481 ? id->p_encoder->fmt_out.video.i_height
1482 : id->p_decoder->fmt_in.video.i_height
1483 ? id->p_decoder->fmt_in.video.i_height : 16;
1484 id->p_encoder->fmt_in.video.i_frame_rate = ENC_FRAMERATE;
1485 id->p_encoder->fmt_in.video.i_frame_rate_base = ENC_FRAMERATE_BASE;
1487 id->p_encoder->i_threads = p_sys->i_threads;
1488 id->p_encoder->p_cfg = p_sys->p_video_cfg;
1490 id->p_encoder->p_module =
1491 module_need( id->p_encoder, "encoder", p_sys->psz_venc, true );
1492 if( !id->p_encoder->p_module )
1494 msg_Err( p_stream, "cannot find video encoder (module:%s fourcc:%4.4s)",
1495 p_sys->psz_venc ? p_sys->psz_venc : "any",
1496 (char *)&p_sys->i_vcodec );
1497 module_unneed( id->p_decoder, id->p_decoder->p_module );
1498 id->p_decoder->p_module = 0;
1499 free( id->p_decoder->p_owner );
1500 return VLC_EGENERIC;
1503 /* Close the encoder.
1504 * We'll open it only when we have the first frame. */
1505 module_unneed( id->p_encoder, id->p_encoder->p_module );
1506 if( id->p_encoder->fmt_out.p_extra )
1508 free( id->p_encoder->fmt_out.p_extra );
1509 id->p_encoder->fmt_out.p_extra = NULL;
1510 id->p_encoder->fmt_out.i_extra = 0;
1512 id->p_encoder->p_module = NULL;
1514 if( p_sys->i_threads >= 1 )
1516 int i_priority = p_sys->b_high_priority ? VLC_THREAD_PRIORITY_OUTPUT :
1517 VLC_THREAD_PRIORITY_VIDEO;
1518 p_sys->id_video = id;
1519 vlc_mutex_init( &p_sys->lock_out );
1520 vlc_cond_init( &p_sys->cond );
1521 memset( p_sys->pp_pics, 0, sizeof(p_sys->pp_pics) );
1522 p_sys->i_first_pic = 0;
1523 p_sys->i_last_pic = 0;
1524 p_sys->p_buffers = NULL;
1525 p_sys->b_die = p_sys->b_error = 0;
1526 if( vlc_thread_create( p_sys, "encoder", EncoderThread, i_priority ) )
1528 msg_Err( p_stream, "cannot spawn encoder thread" );
1529 module_unneed( id->p_decoder, id->p_decoder->p_module );
1530 id->p_decoder->p_module = 0;
1531 free( id->p_decoder->p_owner );
1532 return VLC_EGENERIC;
1539 static void transcode_video_encoder_init( sout_stream_t *p_stream,
1540 sout_stream_id_t *id )
1542 sout_stream_sys_t *p_sys = p_stream->p_sys;
1544 /* Calculate scaling
1545 * width/height of source */
1546 int i_src_width = id->p_decoder->fmt_out.video.i_width;
1547 int i_src_height = id->p_decoder->fmt_out.video.i_height;
1549 /* with/height scaling */
1550 float f_scale_width = 1;
1551 float f_scale_height = 1;
1553 /* width/height of output stream */
1558 float f_aspect = (float)id->p_decoder->fmt_out.video.i_aspect /
1561 msg_Dbg( p_stream, "decoder aspect is %i:%i",
1562 id->p_decoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
1564 /* Change f_aspect from source frame to source pixel */
1565 f_aspect = f_aspect * i_src_height / i_src_width;
1566 msg_Dbg( p_stream, "source pixel aspect is %f:1", f_aspect );
1568 /* Calculate scaling factor for specified parameters */
1569 if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1570 id->p_encoder->fmt_out.video.i_height <= 0 && p_sys->f_scale )
1572 /* Global scaling. Make sure width will remain a factor of 16 */
1575 int i_new_width = i_src_width * p_sys->f_scale;
1577 if( i_new_width % 16 <= 7 && i_new_width >= 16 )
1578 i_new_width -= i_new_width % 16;
1580 i_new_width += 16 - i_new_width % 16;
1582 f_real_scale = (float)( i_new_width ) / (float) i_src_width;
1584 i_new_height = __MAX( 16, i_src_height * (float)f_real_scale );
1586 f_scale_width = f_real_scale;
1587 f_scale_height = (float) i_new_height / (float) i_src_height;
1589 else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1590 id->p_encoder->fmt_out.video.i_height <= 0 )
1592 /* Only width specified */
1593 f_scale_width = (float)id->p_encoder->fmt_out.video.i_width/i_src_width;
1594 f_scale_height = f_scale_width;
1596 else if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1597 id->p_encoder->fmt_out.video.i_height > 0 )
1599 /* Only height specified */
1600 f_scale_height = (float)id->p_encoder->fmt_out.video.i_height/i_src_height;
1601 f_scale_width = f_scale_height;
1603 else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1604 id->p_encoder->fmt_out.video.i_height > 0 )
1606 /* Width and height specified */
1607 f_scale_width = (float)id->p_encoder->fmt_out.video.i_width/i_src_width;
1608 f_scale_height = (float)id->p_encoder->fmt_out.video.i_height/i_src_height;
1611 /* check maxwidth and maxheight
1613 if( p_sys->i_maxwidth && f_scale_width > (float)p_sys->i_maxwidth /
1616 f_scale_width = (float)p_sys->i_maxwidth / i_src_width;
1619 if( p_sys->i_maxheight && f_scale_height > (float)p_sys->i_maxheight /
1622 f_scale_height = (float)p_sys->i_maxheight / i_src_height;
1626 /* Change aspect ratio from source pixel to scaled pixel */
1627 f_aspect = f_aspect * f_scale_height / f_scale_width;
1628 msg_Dbg( p_stream, "scaled pixel aspect is %f:1", f_aspect );
1630 /* f_scale_width and f_scale_height are now final */
1631 /* Calculate width, height from scaling
1632 * Make sure its multiple of 2
1634 i_dst_width = 2 * (int)(f_scale_width*i_src_width/2+0.5);
1635 i_dst_height = 2 * (int)(f_scale_height*i_src_height/2+0.5);
1637 /* Change aspect ratio from scaled pixel to output frame */
1638 f_aspect = f_aspect * i_dst_width / i_dst_height;
1640 /* Store calculated values */
1641 id->p_encoder->fmt_out.video.i_width =
1642 id->p_encoder->fmt_out.video.i_visible_width = i_dst_width;
1643 id->p_encoder->fmt_out.video.i_height =
1644 id->p_encoder->fmt_out.video.i_visible_height = i_dst_height;
1646 id->p_encoder->fmt_in.video.i_width =
1647 id->p_encoder->fmt_in.video.i_visible_width = i_dst_width;
1648 id->p_encoder->fmt_in.video.i_height =
1649 id->p_encoder->fmt_in.video.i_visible_height = i_dst_height;
1651 msg_Dbg( p_stream, "source %ix%i, destination %ix%i",
1652 i_src_width, i_src_height,
1653 i_dst_width, i_dst_height
1656 /* Handle frame rate conversion */
1657 if( !id->p_encoder->fmt_out.video.i_frame_rate ||
1658 !id->p_encoder->fmt_out.video.i_frame_rate_base )
1660 if( id->p_decoder->fmt_out.video.i_frame_rate &&
1661 id->p_decoder->fmt_out.video.i_frame_rate_base )
1663 id->p_encoder->fmt_out.video.i_frame_rate =
1664 id->p_decoder->fmt_out.video.i_frame_rate;
1665 id->p_encoder->fmt_out.video.i_frame_rate_base =
1666 id->p_decoder->fmt_out.video.i_frame_rate_base;
1670 /* Pick a sensible default value */
1671 id->p_encoder->fmt_out.video.i_frame_rate = ENC_FRAMERATE;
1672 id->p_encoder->fmt_out.video.i_frame_rate_base = ENC_FRAMERATE_BASE;
1676 id->p_encoder->fmt_in.video.i_frame_rate =
1677 id->p_encoder->fmt_out.video.i_frame_rate;
1678 id->p_encoder->fmt_in.video.i_frame_rate_base =
1679 id->p_encoder->fmt_out.video.i_frame_rate_base;
1681 date_Init( &id->interpolated_pts,
1682 id->p_encoder->fmt_out.video.i_frame_rate,
1683 id->p_encoder->fmt_out.video.i_frame_rate_base );
1685 /* Check whether a particular aspect ratio was requested */
1686 if( !id->p_encoder->fmt_out.video.i_aspect )
1688 id->p_encoder->fmt_out.video.i_aspect =
1689 (int)( f_aspect * VOUT_ASPECT_FACTOR + 0.5 );
1691 id->p_encoder->fmt_in.video.i_aspect =
1692 id->p_encoder->fmt_out.video.i_aspect;
1694 msg_Dbg( p_stream, "encoder aspect is %i:%i",
1695 id->p_encoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
1697 id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
1700 static int transcode_video_encoder_open( sout_stream_t *p_stream,
1701 sout_stream_id_t *id )
1703 sout_stream_sys_t *p_sys = p_stream->p_sys;
1706 msg_Dbg( p_stream, "destination (after video filters) %ix%i",
1707 id->p_encoder->fmt_in.video.i_width,
1708 id->p_encoder->fmt_in.video.i_height );
1710 id->p_encoder->p_module =
1711 module_need( id->p_encoder, "encoder", p_sys->psz_venc, true );
1712 if( !id->p_encoder->p_module )
1714 msg_Err( p_stream, "cannot find video encoder (module:%s fourcc:%4.4s)",
1715 p_sys->psz_venc ? p_sys->psz_venc : "any",
1716 (char *)&p_sys->i_vcodec );
1717 return VLC_EGENERIC;
1720 id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
1723 id->p_encoder->fmt_out.i_codec =
1724 vlc_fourcc_GetCodec( VIDEO_ES, id->p_encoder->fmt_out.i_codec );
1726 id->id = sout_StreamIdAdd( p_stream->p_sys->p_out,
1727 &id->p_encoder->fmt_out );
1730 msg_Err( p_stream, "cannot add this stream" );
1731 return VLC_EGENERIC;
1737 static void transcode_video_close( sout_stream_t *p_stream,
1738 sout_stream_id_t *id )
1740 if( p_stream->p_sys->i_threads >= 1 )
1742 vlc_mutex_lock( &p_stream->p_sys->lock_out );
1743 vlc_object_kill( p_stream->p_sys );
1744 vlc_cond_signal( &p_stream->p_sys->cond );
1745 vlc_mutex_unlock( &p_stream->p_sys->lock_out );
1746 vlc_thread_join( p_stream->p_sys );
1747 vlc_mutex_destroy( &p_stream->p_sys->lock_out );
1748 vlc_cond_destroy( &p_stream->p_sys->cond );
1751 video_timer_close( id->p_encoder );
1754 if( id->p_decoder->p_module )
1755 module_unneed( id->p_decoder, id->p_decoder->p_module );
1756 if( id->p_decoder->p_description )
1757 vlc_meta_Delete( id->p_decoder->p_description );
1759 free( id->p_decoder->p_owner );
1762 if( id->p_encoder->p_module )
1763 module_unneed( id->p_encoder, id->p_encoder->p_module );
1767 filter_chain_Delete( id->p_f_chain );
1768 if( id->p_uf_chain )
1769 filter_chain_Delete( id->p_uf_chain );
1772 static int transcode_video_process( sout_stream_t *p_stream,
1773 sout_stream_id_t *id,
1774 block_t *in, block_t **out )
1776 sout_stream_sys_t *p_sys = p_stream->p_sys;
1777 int i_duplicate = 1;
1778 picture_t *p_pic, *p_pic2 = NULL;
1781 while( (p_pic = id->p_decoder->pf_decode_video( id->p_decoder, &in )) )
1783 subpicture_t *p_subpic = NULL;
1785 sout_UpdateStatistic( p_stream->p_sout, SOUT_STATISTIC_DECODED_VIDEO, 1 );
1787 if( p_stream->p_sout->i_out_pace_nocontrol && p_sys->b_hurry_up )
1789 mtime_t current_date = mdate();
1790 if( current_date + 50000 > p_pic->date )
1792 msg_Dbg( p_stream, "late picture skipped (%"PRId64")",
1793 current_date + 50000 - p_pic->date );
1794 picture_Release( p_pic );
1799 if( p_sys->b_master_sync )
1801 mtime_t i_video_drift;
1802 mtime_t i_master_drift = p_sys->i_master_drift;
1805 i_pts = date_Get( &id->interpolated_pts ) + 1;
1806 if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
1807 || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
1809 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
1810 date_Set( &id->interpolated_pts, p_pic->date );
1811 i_pts = p_pic->date + 1;
1813 i_video_drift = p_pic->date - i_pts;
1816 /* Set the pts of the frame being encoded */
1817 p_pic->date = i_pts;
1819 if( i_video_drift < (i_master_drift - 50000) )
1822 msg_Dbg( p_stream, "dropping frame (%i)",
1823 (int)(i_video_drift - i_master_drift) );
1825 picture_Release( p_pic );
1828 else if( i_video_drift > (i_master_drift + 50000) )
1831 msg_Dbg( p_stream, "adding frame (%i)",
1832 (int)(i_video_drift - i_master_drift) );
1838 if( !id->p_encoder->p_module )
1840 transcode_video_encoder_init( p_stream, id );
1842 id->p_f_chain = filter_chain_New( p_stream, "video filter2",
1844 transcode_video_filter_allocation_init,
1845 transcode_video_filter_allocation_clear,
1849 if( p_stream->p_sys->b_deinterlace )
1851 filter_chain_AppendFilter( id->p_f_chain,
1852 p_sys->psz_deinterlace,
1853 p_sys->p_deinterlace_cfg,
1854 &id->p_decoder->fmt_out,
1855 &id->p_decoder->fmt_out );
1858 /* Take care of the scaling and chroma conversions */
1859 if( ( id->p_decoder->fmt_out.video.i_chroma !=
1860 id->p_encoder->fmt_in.video.i_chroma ) ||
1861 ( id->p_decoder->fmt_out.video.i_width !=
1862 id->p_encoder->fmt_in.video.i_width ) ||
1863 ( id->p_decoder->fmt_out.video.i_height !=
1864 id->p_encoder->fmt_in.video.i_height ) )
1866 filter_chain_AppendFilter( id->p_f_chain,
1868 &id->p_decoder->fmt_out,
1869 &id->p_encoder->fmt_in );
1872 if( p_sys->psz_vf2 )
1874 const es_format_t *p_fmt_out;
1875 id->p_uf_chain = filter_chain_New( p_stream, "video filter2",
1877 transcode_video_filter_allocation_init,
1878 transcode_video_filter_allocation_clear,
1880 filter_chain_Reset( id->p_uf_chain, &id->p_encoder->fmt_in,
1881 &id->p_encoder->fmt_in );
1882 filter_chain_AppendFromString( id->p_uf_chain, p_sys->psz_vf2 );
1883 p_fmt_out = filter_chain_GetFmtOut( id->p_uf_chain );
1884 es_format_Copy( &id->p_encoder->fmt_in, p_fmt_out );
1885 id->p_encoder->fmt_out.video.i_width =
1886 id->p_encoder->fmt_in.video.i_width;
1887 id->p_encoder->fmt_out.video.i_height =
1888 id->p_encoder->fmt_in.video.i_height;
1889 id->p_encoder->fmt_out.video.i_aspect =
1890 id->p_encoder->fmt_in.video.i_aspect;
1893 if( transcode_video_encoder_open( p_stream, id ) != VLC_SUCCESS )
1895 picture_Release( p_pic );
1896 transcode_video_close( p_stream, id );
1897 id->b_transcode = false;
1898 return VLC_EGENERIC;
1902 /* Run filter chain */
1904 p_pic = filter_chain_VideoFilter( id->p_f_chain, p_pic );
1910 /* Check if we have a subpicture to overlay */
1913 p_subpic = spu_SortSubpictures( p_sys->p_spu, p_pic->date, false );
1914 /* TODO: get another pic */
1917 /* Overlay subpicture */
1922 if( picture_IsReferenced( p_pic ) && !filter_chain_GetLength( id->p_f_chain ) )
1924 /* We can't modify the picture, we need to duplicate it */
1925 picture_t *p_tmp = video_new_buffer_decoder( id->p_decoder );
1928 picture_Copy( p_tmp, p_pic );
1929 picture_Release( p_pic );
1934 if( filter_chain_GetLength( id->p_f_chain ) > 0 )
1935 fmt = filter_chain_GetFmtOut( id->p_f_chain )->video;
1937 fmt = id->p_decoder->fmt_out.video;
1939 /* FIXME (shouldn't have to be done here) */
1940 fmt.i_sar_num = fmt.i_aspect * fmt.i_height / fmt.i_width;
1941 fmt.i_sar_den = VOUT_ASPECT_FACTOR;
1943 /* FIXME the mdate() seems highly suspicious */
1944 spu_RenderSubpictures( p_sys->p_spu, p_pic, &fmt,
1945 p_subpic, &id->p_decoder->fmt_out.video, mdate() );
1948 /* Run user specified filter chain */
1949 if( id->p_uf_chain )
1950 p_pic = filter_chain_VideoFilter( id->p_uf_chain, p_pic );
1952 if( p_sys->i_threads == 0 )
1956 video_timer_start( id->p_encoder );
1957 p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
1958 video_timer_stop( id->p_encoder );
1960 block_ChainAppend( out, p_block );
1963 if( p_sys->b_master_sync )
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 );
1976 if( p_sys->b_master_sync && i_duplicate > 1 )
1978 mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
1979 if( (p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT)
1980 || ((p_pic->date - i_pts) < -MASTER_SYNC_MAX_DRIFT) )
1982 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
1983 date_Set( &id->interpolated_pts, p_pic->date );
1984 i_pts = p_pic->date + 1;
1986 date_Increment( &id->interpolated_pts, 1 );
1988 if( p_sys->i_threads >= 1 )
1990 /* We can't modify the picture, we need to duplicate it */
1991 p_pic2 = video_new_buffer_decoder( id->p_decoder );
1992 if( p_pic2 != NULL )
1994 picture_Copy( p_pic2, p_pic );
1995 p_pic2->date = i_pts;
2001 p_pic->date = i_pts;
2002 video_timer_start( id->p_encoder );
2003 p_block = id->p_encoder->pf_encode_video(id->p_encoder, p_pic);
2004 video_timer_stop( id->p_encoder );
2005 block_ChainAppend( out, p_block );
2009 if( p_sys->i_threads == 0 )
2011 picture_Release( p_pic );
2015 vlc_mutex_lock( &p_sys->lock_out );
2016 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic;
2017 p_sys->i_last_pic %= PICTURE_RING_SIZE;
2018 *out = p_sys->p_buffers;
2019 p_sys->p_buffers = NULL;
2020 if( p_pic2 != NULL )
2022 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic2;
2023 p_sys->i_last_pic %= PICTURE_RING_SIZE;
2025 vlc_cond_signal( &p_sys->cond );
2026 vlc_mutex_unlock( &p_sys->lock_out );
2033 static void* EncoderThread( vlc_object_t* p_this )
2035 sout_stream_sys_t *p_sys = (sout_stream_sys_t*)p_this;
2036 sout_stream_id_t *id = p_sys->id_video;
2038 int canc = vlc_savecancel ();
2040 while( vlc_object_alive (p_sys) && !p_sys->b_error )
2044 vlc_mutex_lock( &p_sys->lock_out );
2045 while( p_sys->i_last_pic == p_sys->i_first_pic )
2047 vlc_cond_wait( &p_sys->cond, &p_sys->lock_out );
2048 if( !vlc_object_alive (p_sys) || p_sys->b_error ) break;
2050 if( !vlc_object_alive (p_sys) || p_sys->b_error )
2052 vlc_mutex_unlock( &p_sys->lock_out );
2056 p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2057 p_sys->i_first_pic %= PICTURE_RING_SIZE;
2058 vlc_mutex_unlock( &p_sys->lock_out );
2060 video_timer_start( id->p_encoder );
2061 p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
2062 video_timer_stop( id->p_encoder );
2064 vlc_mutex_lock( &p_sys->lock_out );
2065 block_ChainAppend( &p_sys->p_buffers, p_block );
2067 vlc_mutex_unlock( &p_sys->lock_out );
2068 picture_Release( p_pic );
2071 while( p_sys->i_last_pic != p_sys->i_first_pic )
2073 p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2074 p_sys->i_first_pic %= PICTURE_RING_SIZE;
2075 picture_Release( p_pic );
2077 block_ChainRelease( p_sys->p_buffers );
2079 vlc_restorecancel (canc);
2083 static picture_t *video_new_buffer_decoder( decoder_t *p_dec )
2085 sout_stream_sys_t *p_ssys = p_dec->p_owner->p_sys;
2086 if( p_ssys->i_threads >= 1 )
2088 int i_first_pic = p_ssys->i_first_pic;
2090 if( p_ssys->i_first_pic != p_ssys->i_last_pic )
2092 /* Encoder still has stuff to encode, wait to clear-up the list */
2093 while( p_ssys->i_first_pic == i_first_pic )
2098 p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
2099 return picture_New( p_dec->fmt_out.video.i_chroma,
2100 p_dec->fmt_out.video.i_width,
2101 p_dec->fmt_out.video.i_height,
2102 p_dec->fmt_out.video.i_aspect );
2105 static void video_del_buffer_decoder( decoder_t *p_decoder, picture_t *p_pic )
2107 VLC_UNUSED(p_decoder);
2108 picture_Release( p_pic );
2111 static void video_link_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2114 picture_Hold( p_pic );
2117 static void video_unlink_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2120 picture_Release( p_pic );
2126 static subpicture_t *spu_new_buffer( decoder_t * );
2127 static void spu_del_buffer( decoder_t *, subpicture_t * );
2129 static int transcode_spu_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2131 sout_stream_sys_t *p_sys = p_stream->p_sys;
2137 /* Initialization of decoder structures */
2138 id->p_decoder->pf_decode_sub = NULL;
2139 id->p_decoder->pf_spu_buffer_new = spu_new_buffer;
2140 id->p_decoder->pf_spu_buffer_del = spu_del_buffer;
2141 id->p_decoder->p_owner = (decoder_owner_sys_t *)p_stream;
2142 /* id->p_decoder->p_cfg = p_sys->p_spu_cfg; */
2144 id->p_decoder->p_module =
2145 module_need( id->p_decoder, "decoder", "$codec", false );
2147 if( !id->p_decoder->p_module )
2149 msg_Err( p_stream, "cannot find spu decoder" );
2150 return VLC_EGENERIC;
2153 if( !p_sys->b_soverlay )
2156 /* Initialization of encoder format structures */
2157 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
2158 id->p_decoder->fmt_in.i_codec );
2160 id->p_encoder->p_cfg = p_sys->p_spu_cfg;
2162 id->p_encoder->p_module =
2163 module_need( id->p_encoder, "encoder", p_sys->psz_senc, true );
2165 if( !id->p_encoder->p_module )
2167 module_unneed( id->p_decoder, id->p_decoder->p_module );
2168 msg_Err( p_stream, "cannot find spu encoder (%s)", p_sys->psz_senc );
2169 return VLC_EGENERIC;
2175 p_sys->p_spu = spu_Create( p_stream );
2176 spu_Init( p_sys->p_spu );
2182 static void transcode_spu_close( sout_stream_id_t *id)
2185 if( id->p_decoder->p_module )
2186 module_unneed( id->p_decoder, id->p_decoder->p_module );
2187 if( id->p_decoder->p_description )
2188 vlc_meta_Delete( id->p_decoder->p_description );
2191 if( id->p_encoder->p_module )
2192 module_unneed( id->p_encoder, id->p_encoder->p_module );
2195 static int transcode_spu_process( sout_stream_t *p_stream,
2196 sout_stream_id_t *id,
2197 block_t *in, block_t **out )
2199 sout_stream_sys_t *p_sys = p_stream->p_sys;
2200 subpicture_t *p_subpic;
2203 p_subpic = id->p_decoder->pf_decode_sub( id->p_decoder, &in );
2205 return VLC_EGENERIC;
2207 sout_UpdateStatistic( p_stream->p_sout, SOUT_STATISTIC_DECODED_SUBTITLE, 1 );
2209 if( p_sys->b_master_sync && p_sys->i_master_drift )
2211 p_subpic->i_start -= p_sys->i_master_drift;
2212 if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2215 if( p_sys->b_soverlay )
2217 spu_DisplaySubpicture( p_sys->p_spu, p_subpic );
2223 p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
2224 spu_del_buffer( id->p_decoder, p_subpic );
2227 block_ChainAppend( out, p_block );
2232 return VLC_EGENERIC;
2235 static subpicture_t *spu_new_buffer( decoder_t *p_dec )
2237 VLC_UNUSED( p_dec );
2238 return subpicture_New();
2241 static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_subpic )
2243 VLC_UNUSED( p_dec );
2244 subpicture_Delete( p_subpic );
2250 static int transcode_osd_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2252 sout_stream_sys_t *p_sys = p_stream->p_sys;
2254 id->p_decoder->fmt_in.i_cat = SPU_ES;
2255 id->p_encoder->fmt_out.psz_language = strdup( "osd" );
2257 if( p_sys->i_osdcodec != 0 || p_sys->psz_osdenc )
2259 msg_Dbg( p_stream, "creating osdmenu transcoding from fcc=`%4.4s' "
2260 "to fcc=`%4.4s'", (char*)&id->p_encoder->fmt_out.i_codec,
2261 (char*)&p_sys->i_osdcodec );
2263 /* Complete destination format */
2264 id->p_encoder->fmt_out.i_codec = p_sys->i_osdcodec;
2267 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
2269 id->p_encoder->fmt_in.psz_language = strdup( "osd" );
2271 id->p_encoder->p_cfg = p_sys->p_osd_cfg;
2273 id->p_encoder->p_module =
2274 module_need( id->p_encoder, "encoder", p_sys->psz_osdenc, true );
2276 if( !id->p_encoder->p_module )
2278 msg_Err( p_stream, "cannot find spu encoder (%s)", p_sys->psz_osdenc );
2282 /* open output stream */
2283 id->id = sout_StreamIdAdd( p_sys->p_out, &id->p_encoder->fmt_out );
2284 id->b_transcode = true;
2286 if( !id->id ) goto error;
2290 msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
2291 (char*)&id->p_decoder->fmt_out.i_codec );
2292 id->id = sout_StreamIdAdd( p_sys->p_out, &id->p_decoder->fmt_out );
2293 id->b_transcode = false;
2295 if( !id->id ) goto error;
2300 p_sys->p_spu = spu_Create( p_stream );
2301 spu_Init( p_sys->p_spu );
2307 msg_Err( p_stream, "starting osd encoding thread failed" );
2308 if( id->p_encoder->p_module )
2309 module_unneed( id->p_encoder, id->p_encoder->p_module );
2310 p_sys->b_osd = false;
2311 return VLC_EGENERIC;
2314 static void transcode_osd_close( sout_stream_t *p_stream, sout_stream_id_t *id)
2316 sout_stream_sys_t *p_sys = p_stream->p_sys;
2321 if( id->p_encoder->p_module )
2322 module_unneed( id->p_encoder, id->p_encoder->p_module );
2324 p_sys->b_osd = false;
2327 static int transcode_osd_process( sout_stream_t *p_stream,
2328 sout_stream_id_t *id,
2329 block_t *in, block_t **out )
2331 sout_stream_sys_t *p_sys = p_stream->p_sys;
2332 subpicture_t *p_subpic = NULL;
2334 /* Check if we have a subpicture to send */
2335 if( p_sys->p_spu && in->i_dts > 0)
2337 p_subpic = spu_SortSubpictures( p_sys->p_spu, in->i_dts, false );
2341 msg_Warn( p_stream, "spu channel not initialized, doing it now" );
2344 p_sys->p_spu = spu_Create( p_stream );
2345 spu_Init( p_sys->p_spu );
2351 block_t *p_block = NULL;
2353 if( p_sys->b_master_sync && p_sys->i_master_drift )
2355 p_subpic->i_start -= p_sys->i_master_drift;
2356 if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2359 p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
2360 subpicture_Delete( p_subpic );
2363 p_block->i_dts = p_block->i_pts = in->i_dts;
2364 block_ChainAppend( out, p_block );
2368 return VLC_EGENERIC;