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", false, 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", false, 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", false, 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", false, 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", false, 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 block_t *p_block, *p_audio_buf;
1290 while( (p_audio_buf = id->p_decoder->pf_decode_audio( id->p_decoder,
1293 sout_UpdateStatistic( p_stream->p_sout, SOUT_STATISTIC_DECODED_AUDIO, 1 );
1294 if( p_sys->b_master_sync )
1296 mtime_t i_dts = date_Get( &id->interpolated_pts ) + 1;
1297 if ( p_audio_buf->i_pts - i_dts > MASTER_SYNC_MAX_DRIFT
1298 || p_audio_buf->i_pts - i_dts < -MASTER_SYNC_MAX_DRIFT )
1300 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
1301 date_Set( &id->interpolated_pts, p_audio_buf->i_pts );
1302 i_dts = p_audio_buf->i_pts + 1;
1304 p_sys->i_master_drift = p_audio_buf->i_pts - i_dts;
1305 date_Increment( &id->interpolated_pts, p_audio_buf->i_nb_samples );
1306 p_audio_buf->i_pts -= p_sys->i_master_drift;
1309 p_audio_buf->i_dts = p_audio_buf->i_pts;
1311 /* Run filter chain */
1312 if( id->p_uf_chain )
1314 p_audio_buf = filter_chain_AudioFilter( id->p_uf_chain,
1320 p_audio_buf = filter_chain_AudioFilter( id->p_f_chain, p_audio_buf );
1324 p_audio_buf->i_pts = p_audio_buf->i_dts;
1326 audio_timer_start( id->p_encoder );
1327 p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf );
1328 audio_timer_stop( id->p_encoder );
1330 block_ChainAppend( out, p_block );
1331 block_Release( p_audio_buf );
1337 static aout_buffer_t *audio_new_buffer( decoder_t *p_dec, int i_samples )
1342 if( p_dec->fmt_out.audio.i_bitspersample )
1344 i_size = i_samples * p_dec->fmt_out.audio.i_bitspersample / 8 *
1345 p_dec->fmt_out.audio.i_channels;
1347 else if( p_dec->fmt_out.audio.i_bytes_per_frame &&
1348 p_dec->fmt_out.audio.i_frame_length )
1350 i_size = i_samples * p_dec->fmt_out.audio.i_bytes_per_frame /
1351 p_dec->fmt_out.audio.i_frame_length;
1355 i_size = i_samples * 4 * p_dec->fmt_out.audio.i_channels;
1358 p_block = block_New( p_dec, i_size );
1359 p_block->i_nb_samples = i_samples;
1363 static void audio_del_buffer( decoder_t *p_dec, aout_buffer_t *p_buffer )
1366 block_Release( p_buffer );
1373 static picture_t *transcode_video_filter_buffer_new( filter_t *p_filter )
1375 p_filter->fmt_out.video.i_chroma = p_filter->fmt_out.i_codec;
1376 return picture_New( p_filter->fmt_out.video.i_chroma,
1377 p_filter->fmt_out.video.i_width,
1378 p_filter->fmt_out.video.i_height,
1379 p_filter->fmt_out.video.i_aspect );
1381 static void transcode_video_filter_buffer_del( filter_t *p_filter, picture_t *p_pic )
1383 VLC_UNUSED(p_filter);
1384 picture_Release( p_pic );
1387 static int transcode_video_filter_allocation_init( filter_t *p_filter,
1391 p_filter->pf_vout_buffer_new = transcode_video_filter_buffer_new;
1392 p_filter->pf_vout_buffer_del = transcode_video_filter_buffer_del;
1396 static void transcode_video_filter_allocation_clear( filter_t *p_filter )
1398 VLC_UNUSED(p_filter);
1401 static int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_t *id )
1403 sout_stream_sys_t *p_sys = p_stream->p_sys;
1406 * Initialization of decoder structures
1408 id->p_decoder->fmt_out = id->p_decoder->fmt_in;
1409 id->p_decoder->fmt_out.i_extra = 0;
1410 id->p_decoder->fmt_out.p_extra = 0;
1411 id->p_decoder->pf_decode_video = NULL;
1412 id->p_decoder->pf_get_cc = NULL;
1413 id->p_decoder->pf_get_cc = 0;
1414 id->p_decoder->pf_vout_buffer_new = video_new_buffer_decoder;
1415 id->p_decoder->pf_vout_buffer_del = video_del_buffer_decoder;
1416 id->p_decoder->pf_picture_link = video_link_picture_decoder;
1417 id->p_decoder->pf_picture_unlink = video_unlink_picture_decoder;
1418 id->p_decoder->p_owner = malloc( sizeof(decoder_owner_sys_t) );
1419 if( !id->p_decoder->p_owner )
1420 return VLC_EGENERIC;
1422 id->p_decoder->p_owner->p_sys = p_sys;
1423 /* id->p_decoder->p_cfg = p_sys->p_video_cfg; */
1425 id->p_decoder->p_module =
1426 module_need( id->p_decoder, "decoder", "$codec", false );
1428 if( !id->p_decoder->p_module )
1430 msg_Err( p_stream, "cannot find video decoder" );
1431 free( id->p_decoder->p_owner );
1432 return VLC_EGENERIC;
1437 * Because some info about the decoded input will only be available
1438 * once the first frame is decoded, we actually only test the availability
1439 * of the encoder here.
1442 /* Initialization of encoder format structures */
1443 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1444 id->p_decoder->fmt_out.i_codec );
1445 id->p_encoder->fmt_in.video.i_chroma = id->p_decoder->fmt_out.i_codec;
1447 /* The dimensions will be set properly later on.
1448 * Just put sensible values so we can test an encoder is available. */
1449 id->p_encoder->fmt_in.video.i_width =
1450 id->p_encoder->fmt_out.video.i_width
1451 ? id->p_encoder->fmt_out.video.i_width
1452 : id->p_decoder->fmt_in.video.i_width
1453 ? id->p_decoder->fmt_in.video.i_width : 16;
1454 id->p_encoder->fmt_in.video.i_height =
1455 id->p_encoder->fmt_out.video.i_height
1456 ? id->p_encoder->fmt_out.video.i_height
1457 : id->p_decoder->fmt_in.video.i_height
1458 ? id->p_decoder->fmt_in.video.i_height : 16;
1459 id->p_encoder->fmt_in.video.i_frame_rate = ENC_FRAMERATE;
1460 id->p_encoder->fmt_in.video.i_frame_rate_base = ENC_FRAMERATE_BASE;
1462 id->p_encoder->i_threads = p_sys->i_threads;
1463 id->p_encoder->p_cfg = p_sys->p_video_cfg;
1465 id->p_encoder->p_module =
1466 module_need( id->p_encoder, "encoder", p_sys->psz_venc, true );
1467 if( !id->p_encoder->p_module )
1469 msg_Err( p_stream, "cannot find video encoder (module:%s fourcc:%4.4s)",
1470 p_sys->psz_venc ? p_sys->psz_venc : "any",
1471 (char *)&p_sys->i_vcodec );
1472 module_unneed( id->p_decoder, id->p_decoder->p_module );
1473 id->p_decoder->p_module = 0;
1474 free( id->p_decoder->p_owner );
1475 return VLC_EGENERIC;
1478 /* Close the encoder.
1479 * We'll open it only when we have the first frame. */
1480 module_unneed( id->p_encoder, id->p_encoder->p_module );
1481 if( id->p_encoder->fmt_out.p_extra )
1483 free( id->p_encoder->fmt_out.p_extra );
1484 id->p_encoder->fmt_out.p_extra = NULL;
1485 id->p_encoder->fmt_out.i_extra = 0;
1487 id->p_encoder->p_module = NULL;
1489 if( p_sys->i_threads >= 1 )
1491 int i_priority = p_sys->b_high_priority ? VLC_THREAD_PRIORITY_OUTPUT :
1492 VLC_THREAD_PRIORITY_VIDEO;
1493 p_sys->id_video = id;
1494 vlc_mutex_init( &p_sys->lock_out );
1495 vlc_cond_init( &p_sys->cond );
1496 memset( p_sys->pp_pics, 0, sizeof(p_sys->pp_pics) );
1497 p_sys->i_first_pic = 0;
1498 p_sys->i_last_pic = 0;
1499 p_sys->p_buffers = NULL;
1500 p_sys->b_die = p_sys->b_error = 0;
1501 if( vlc_thread_create( p_sys, "encoder", EncoderThread, i_priority ) )
1503 msg_Err( p_stream, "cannot spawn encoder thread" );
1504 module_unneed( id->p_decoder, id->p_decoder->p_module );
1505 id->p_decoder->p_module = 0;
1506 free( id->p_decoder->p_owner );
1507 return VLC_EGENERIC;
1514 static void transcode_video_encoder_init( sout_stream_t *p_stream,
1515 sout_stream_id_t *id )
1517 sout_stream_sys_t *p_sys = p_stream->p_sys;
1519 /* Calculate scaling
1520 * width/height of source */
1521 int i_src_width = id->p_decoder->fmt_out.video.i_width;
1522 int i_src_height = id->p_decoder->fmt_out.video.i_height;
1524 /* with/height scaling */
1525 float f_scale_width = 1;
1526 float f_scale_height = 1;
1528 /* width/height of output stream */
1533 float f_aspect = (float)id->p_decoder->fmt_out.video.i_aspect /
1536 msg_Dbg( p_stream, "decoder aspect is %i:%i",
1537 id->p_decoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
1539 /* Change f_aspect from source frame to source pixel */
1540 f_aspect = f_aspect * i_src_height / i_src_width;
1541 msg_Dbg( p_stream, "source pixel aspect is %f:1", f_aspect );
1543 /* Calculate scaling factor for specified parameters */
1544 if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1545 id->p_encoder->fmt_out.video.i_height <= 0 && p_sys->f_scale )
1547 /* Global scaling. Make sure width will remain a factor of 16 */
1550 int i_new_width = i_src_width * p_sys->f_scale;
1552 if( i_new_width % 16 <= 7 && i_new_width >= 16 )
1553 i_new_width -= i_new_width % 16;
1555 i_new_width += 16 - i_new_width % 16;
1557 f_real_scale = (float)( i_new_width ) / (float) i_src_width;
1559 i_new_height = __MAX( 16, i_src_height * (float)f_real_scale );
1561 f_scale_width = f_real_scale;
1562 f_scale_height = (float) i_new_height / (float) i_src_height;
1564 else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1565 id->p_encoder->fmt_out.video.i_height <= 0 )
1567 /* Only width specified */
1568 f_scale_width = (float)id->p_encoder->fmt_out.video.i_width/i_src_width;
1569 f_scale_height = f_scale_width;
1571 else if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1572 id->p_encoder->fmt_out.video.i_height > 0 )
1574 /* Only height specified */
1575 f_scale_height = (float)id->p_encoder->fmt_out.video.i_height/i_src_height;
1576 f_scale_width = f_scale_height;
1578 else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1579 id->p_encoder->fmt_out.video.i_height > 0 )
1581 /* Width and height specified */
1582 f_scale_width = (float)id->p_encoder->fmt_out.video.i_width/i_src_width;
1583 f_scale_height = (float)id->p_encoder->fmt_out.video.i_height/i_src_height;
1586 /* check maxwidth and maxheight
1588 if( p_sys->i_maxwidth && f_scale_width > (float)p_sys->i_maxwidth /
1591 f_scale_width = (float)p_sys->i_maxwidth / i_src_width;
1594 if( p_sys->i_maxheight && f_scale_height > (float)p_sys->i_maxheight /
1597 f_scale_height = (float)p_sys->i_maxheight / i_src_height;
1601 /* Change aspect ratio from source pixel to scaled pixel */
1602 f_aspect = f_aspect * f_scale_height / f_scale_width;
1603 msg_Dbg( p_stream, "scaled pixel aspect is %f:1", f_aspect );
1605 /* f_scale_width and f_scale_height are now final */
1606 /* Calculate width, height from scaling
1607 * Make sure its multiple of 2
1609 i_dst_width = 2 * (int)(f_scale_width*i_src_width/2+0.5);
1610 i_dst_height = 2 * (int)(f_scale_height*i_src_height/2+0.5);
1612 /* Change aspect ratio from scaled pixel to output frame */
1613 f_aspect = f_aspect * i_dst_width / i_dst_height;
1615 /* Store calculated values */
1616 id->p_encoder->fmt_out.video.i_width =
1617 id->p_encoder->fmt_out.video.i_visible_width = i_dst_width;
1618 id->p_encoder->fmt_out.video.i_height =
1619 id->p_encoder->fmt_out.video.i_visible_height = i_dst_height;
1621 id->p_encoder->fmt_in.video.i_width =
1622 id->p_encoder->fmt_in.video.i_visible_width = i_dst_width;
1623 id->p_encoder->fmt_in.video.i_height =
1624 id->p_encoder->fmt_in.video.i_visible_height = i_dst_height;
1626 msg_Dbg( p_stream, "source %ix%i, destination %ix%i",
1627 i_src_width, i_src_height,
1628 i_dst_width, i_dst_height
1631 /* Handle frame rate conversion */
1632 if( !id->p_encoder->fmt_out.video.i_frame_rate ||
1633 !id->p_encoder->fmt_out.video.i_frame_rate_base )
1635 if( id->p_decoder->fmt_out.video.i_frame_rate &&
1636 id->p_decoder->fmt_out.video.i_frame_rate_base )
1638 id->p_encoder->fmt_out.video.i_frame_rate =
1639 id->p_decoder->fmt_out.video.i_frame_rate;
1640 id->p_encoder->fmt_out.video.i_frame_rate_base =
1641 id->p_decoder->fmt_out.video.i_frame_rate_base;
1645 /* Pick a sensible default value */
1646 id->p_encoder->fmt_out.video.i_frame_rate = ENC_FRAMERATE;
1647 id->p_encoder->fmt_out.video.i_frame_rate_base = ENC_FRAMERATE_BASE;
1651 id->p_encoder->fmt_in.video.i_frame_rate =
1652 id->p_encoder->fmt_out.video.i_frame_rate;
1653 id->p_encoder->fmt_in.video.i_frame_rate_base =
1654 id->p_encoder->fmt_out.video.i_frame_rate_base;
1656 date_Init( &id->interpolated_pts,
1657 id->p_encoder->fmt_out.video.i_frame_rate,
1658 id->p_encoder->fmt_out.video.i_frame_rate_base );
1660 /* Check whether a particular aspect ratio was requested */
1661 if( !id->p_encoder->fmt_out.video.i_aspect )
1663 id->p_encoder->fmt_out.video.i_aspect =
1664 (int)( f_aspect * VOUT_ASPECT_FACTOR + 0.5 );
1666 id->p_encoder->fmt_in.video.i_aspect =
1667 id->p_encoder->fmt_out.video.i_aspect;
1669 msg_Dbg( p_stream, "encoder aspect is %i:%i",
1670 id->p_encoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
1672 id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
1675 static int transcode_video_encoder_open( sout_stream_t *p_stream,
1676 sout_stream_id_t *id )
1678 sout_stream_sys_t *p_sys = p_stream->p_sys;
1681 msg_Dbg( p_stream, "destination (after video filters) %ix%i",
1682 id->p_encoder->fmt_in.video.i_width,
1683 id->p_encoder->fmt_in.video.i_height );
1685 id->p_encoder->p_module =
1686 module_need( id->p_encoder, "encoder", p_sys->psz_venc, true );
1687 if( !id->p_encoder->p_module )
1689 msg_Err( p_stream, "cannot find video encoder (module:%s fourcc:%4.4s)",
1690 p_sys->psz_venc ? p_sys->psz_venc : "any",
1691 (char *)&p_sys->i_vcodec );
1692 return VLC_EGENERIC;
1695 id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
1698 id->p_encoder->fmt_out.i_codec =
1699 vlc_fourcc_GetCodec( VIDEO_ES, id->p_encoder->fmt_out.i_codec );
1701 id->id = sout_StreamIdAdd( p_stream->p_sys->p_out,
1702 &id->p_encoder->fmt_out );
1705 msg_Err( p_stream, "cannot add this stream" );
1706 return VLC_EGENERIC;
1712 static void transcode_video_close( sout_stream_t *p_stream,
1713 sout_stream_id_t *id )
1715 if( p_stream->p_sys->i_threads >= 1 )
1717 vlc_mutex_lock( &p_stream->p_sys->lock_out );
1718 vlc_object_kill( p_stream->p_sys );
1719 vlc_cond_signal( &p_stream->p_sys->cond );
1720 vlc_mutex_unlock( &p_stream->p_sys->lock_out );
1721 vlc_thread_join( p_stream->p_sys );
1722 vlc_mutex_destroy( &p_stream->p_sys->lock_out );
1723 vlc_cond_destroy( &p_stream->p_sys->cond );
1726 video_timer_close( id->p_encoder );
1729 if( id->p_decoder->p_module )
1730 module_unneed( id->p_decoder, id->p_decoder->p_module );
1731 if( id->p_decoder->p_description )
1732 vlc_meta_Delete( id->p_decoder->p_description );
1734 free( id->p_decoder->p_owner );
1737 if( id->p_encoder->p_module )
1738 module_unneed( id->p_encoder, id->p_encoder->p_module );
1742 filter_chain_Delete( id->p_f_chain );
1743 if( id->p_uf_chain )
1744 filter_chain_Delete( id->p_uf_chain );
1747 static int transcode_video_process( sout_stream_t *p_stream,
1748 sout_stream_id_t *id,
1749 block_t *in, block_t **out )
1751 sout_stream_sys_t *p_sys = p_stream->p_sys;
1752 int i_duplicate = 1;
1753 picture_t *p_pic, *p_pic2 = NULL;
1756 while( (p_pic = id->p_decoder->pf_decode_video( id->p_decoder, &in )) )
1758 subpicture_t *p_subpic = NULL;
1760 sout_UpdateStatistic( p_stream->p_sout, SOUT_STATISTIC_DECODED_VIDEO, 1 );
1762 if( p_stream->p_sout->i_out_pace_nocontrol && p_sys->b_hurry_up )
1764 mtime_t current_date = mdate();
1765 if( current_date + 50000 > p_pic->date )
1767 msg_Dbg( p_stream, "late picture skipped (%"PRId64")",
1768 current_date + 50000 - p_pic->date );
1769 picture_Release( p_pic );
1774 if( p_sys->b_master_sync )
1776 mtime_t i_video_drift;
1777 mtime_t i_master_drift = p_sys->i_master_drift;
1780 i_pts = date_Get( &id->interpolated_pts ) + 1;
1781 if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
1782 || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
1784 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
1785 date_Set( &id->interpolated_pts, p_pic->date );
1786 i_pts = p_pic->date + 1;
1788 i_video_drift = p_pic->date - i_pts;
1791 /* Set the pts of the frame being encoded */
1792 p_pic->date = i_pts;
1794 if( i_video_drift < (i_master_drift - 50000) )
1797 msg_Dbg( p_stream, "dropping frame (%i)",
1798 (int)(i_video_drift - i_master_drift) );
1800 picture_Release( p_pic );
1803 else if( i_video_drift > (i_master_drift + 50000) )
1806 msg_Dbg( p_stream, "adding frame (%i)",
1807 (int)(i_video_drift - i_master_drift) );
1813 if( !id->p_encoder->p_module )
1815 transcode_video_encoder_init( p_stream, id );
1817 id->p_f_chain = filter_chain_New( p_stream, "video filter2",
1819 transcode_video_filter_allocation_init,
1820 transcode_video_filter_allocation_clear,
1824 if( p_stream->p_sys->b_deinterlace )
1826 filter_chain_AppendFilter( id->p_f_chain,
1827 p_sys->psz_deinterlace,
1828 p_sys->p_deinterlace_cfg,
1829 &id->p_decoder->fmt_out,
1830 &id->p_decoder->fmt_out );
1833 /* Take care of the scaling and chroma conversions */
1834 if( ( id->p_decoder->fmt_out.video.i_chroma !=
1835 id->p_encoder->fmt_in.video.i_chroma ) ||
1836 ( id->p_decoder->fmt_out.video.i_width !=
1837 id->p_encoder->fmt_in.video.i_width ) ||
1838 ( id->p_decoder->fmt_out.video.i_height !=
1839 id->p_encoder->fmt_in.video.i_height ) )
1841 filter_chain_AppendFilter( id->p_f_chain,
1843 &id->p_decoder->fmt_out,
1844 &id->p_encoder->fmt_in );
1847 if( p_sys->psz_vf2 )
1849 const es_format_t *p_fmt_out;
1850 id->p_uf_chain = filter_chain_New( p_stream, "video filter2",
1852 transcode_video_filter_allocation_init,
1853 transcode_video_filter_allocation_clear,
1855 filter_chain_Reset( id->p_uf_chain, &id->p_encoder->fmt_in,
1856 &id->p_encoder->fmt_in );
1857 filter_chain_AppendFromString( id->p_uf_chain, p_sys->psz_vf2 );
1858 p_fmt_out = filter_chain_GetFmtOut( id->p_uf_chain );
1859 es_format_Copy( &id->p_encoder->fmt_in, p_fmt_out );
1860 id->p_encoder->fmt_out.video.i_width =
1861 id->p_encoder->fmt_in.video.i_width;
1862 id->p_encoder->fmt_out.video.i_height =
1863 id->p_encoder->fmt_in.video.i_height;
1864 id->p_encoder->fmt_out.video.i_aspect =
1865 id->p_encoder->fmt_in.video.i_aspect;
1868 if( transcode_video_encoder_open( p_stream, id ) != VLC_SUCCESS )
1870 picture_Release( p_pic );
1871 transcode_video_close( p_stream, id );
1872 id->b_transcode = false;
1873 return VLC_EGENERIC;
1877 /* Run filter chain */
1879 p_pic = filter_chain_VideoFilter( id->p_f_chain, p_pic );
1885 /* Check if we have a subpicture to overlay */
1888 p_subpic = spu_SortSubpictures( p_sys->p_spu, p_pic->date, false );
1889 /* TODO: get another pic */
1892 /* Overlay subpicture */
1897 if( picture_IsReferenced( p_pic ) && !filter_chain_GetLength( id->p_f_chain ) )
1899 /* We can't modify the picture, we need to duplicate it */
1900 picture_t *p_tmp = video_new_buffer_decoder( id->p_decoder );
1903 picture_Copy( p_tmp, p_pic );
1904 picture_Release( p_pic );
1909 if( filter_chain_GetLength( id->p_f_chain ) > 0 )
1910 fmt = filter_chain_GetFmtOut( id->p_f_chain )->video;
1912 fmt = id->p_decoder->fmt_out.video;
1914 /* FIXME (shouldn't have to be done here) */
1915 fmt.i_sar_num = fmt.i_aspect * fmt.i_height / fmt.i_width;
1916 fmt.i_sar_den = VOUT_ASPECT_FACTOR;
1918 /* FIXME the mdate() seems highly suspicious */
1919 spu_RenderSubpictures( p_sys->p_spu, p_pic, &fmt,
1920 p_subpic, &id->p_decoder->fmt_out.video, mdate() );
1923 /* Run user specified filter chain */
1924 if( id->p_uf_chain )
1925 p_pic = filter_chain_VideoFilter( id->p_uf_chain, p_pic );
1927 if( p_sys->i_threads == 0 )
1931 video_timer_start( id->p_encoder );
1932 p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
1933 video_timer_stop( id->p_encoder );
1935 block_ChainAppend( out, p_block );
1938 if( p_sys->b_master_sync )
1940 mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
1941 if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
1942 || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
1944 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
1945 date_Set( &id->interpolated_pts, p_pic->date );
1946 i_pts = p_pic->date + 1;
1948 date_Increment( &id->interpolated_pts, 1 );
1951 if( p_sys->b_master_sync && i_duplicate > 1 )
1953 mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
1954 if( (p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT)
1955 || ((p_pic->date - i_pts) < -MASTER_SYNC_MAX_DRIFT) )
1957 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
1958 date_Set( &id->interpolated_pts, p_pic->date );
1959 i_pts = p_pic->date + 1;
1961 date_Increment( &id->interpolated_pts, 1 );
1963 if( p_sys->i_threads >= 1 )
1965 /* We can't modify the picture, we need to duplicate it */
1966 p_pic2 = video_new_buffer_decoder( id->p_decoder );
1967 if( p_pic2 != NULL )
1969 picture_Copy( p_pic2, p_pic );
1970 p_pic2->date = i_pts;
1976 p_pic->date = i_pts;
1977 video_timer_start( id->p_encoder );
1978 p_block = id->p_encoder->pf_encode_video(id->p_encoder, p_pic);
1979 video_timer_stop( id->p_encoder );
1980 block_ChainAppend( out, p_block );
1984 if( p_sys->i_threads == 0 )
1986 picture_Release( p_pic );
1990 vlc_mutex_lock( &p_sys->lock_out );
1991 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic;
1992 p_sys->i_last_pic %= PICTURE_RING_SIZE;
1993 *out = p_sys->p_buffers;
1994 p_sys->p_buffers = NULL;
1995 if( p_pic2 != NULL )
1997 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic2;
1998 p_sys->i_last_pic %= PICTURE_RING_SIZE;
2000 vlc_cond_signal( &p_sys->cond );
2001 vlc_mutex_unlock( &p_sys->lock_out );
2008 static void* EncoderThread( vlc_object_t* p_this )
2010 sout_stream_sys_t *p_sys = (sout_stream_sys_t*)p_this;
2011 sout_stream_id_t *id = p_sys->id_video;
2013 int canc = vlc_savecancel ();
2015 while( vlc_object_alive (p_sys) && !p_sys->b_error )
2019 vlc_mutex_lock( &p_sys->lock_out );
2020 while( p_sys->i_last_pic == p_sys->i_first_pic )
2022 vlc_cond_wait( &p_sys->cond, &p_sys->lock_out );
2023 if( !vlc_object_alive (p_sys) || p_sys->b_error ) break;
2025 if( !vlc_object_alive (p_sys) || p_sys->b_error )
2027 vlc_mutex_unlock( &p_sys->lock_out );
2031 p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2032 p_sys->i_first_pic %= PICTURE_RING_SIZE;
2033 vlc_mutex_unlock( &p_sys->lock_out );
2035 video_timer_start( id->p_encoder );
2036 p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
2037 video_timer_stop( id->p_encoder );
2039 vlc_mutex_lock( &p_sys->lock_out );
2040 block_ChainAppend( &p_sys->p_buffers, p_block );
2042 vlc_mutex_unlock( &p_sys->lock_out );
2043 picture_Release( p_pic );
2046 while( p_sys->i_last_pic != p_sys->i_first_pic )
2048 p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2049 p_sys->i_first_pic %= PICTURE_RING_SIZE;
2050 picture_Release( p_pic );
2052 block_ChainRelease( p_sys->p_buffers );
2054 vlc_restorecancel (canc);
2058 static picture_t *video_new_buffer_decoder( decoder_t *p_dec )
2060 sout_stream_sys_t *p_ssys = p_dec->p_owner->p_sys;
2061 if( p_ssys->i_threads >= 1 )
2063 int i_first_pic = p_ssys->i_first_pic;
2065 if( p_ssys->i_first_pic != p_ssys->i_last_pic )
2067 /* Encoder still has stuff to encode, wait to clear-up the list */
2068 while( p_ssys->i_first_pic == i_first_pic )
2070 #warning THERE IS A DEFINITELY BUG! LOCKING IS INSUFFICIENT!
2077 p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
2078 return picture_New( p_dec->fmt_out.video.i_chroma,
2079 p_dec->fmt_out.video.i_width,
2080 p_dec->fmt_out.video.i_height,
2081 p_dec->fmt_out.video.i_aspect );
2084 static void video_del_buffer_decoder( decoder_t *p_decoder, picture_t *p_pic )
2086 VLC_UNUSED(p_decoder);
2087 picture_Release( p_pic );
2090 static void video_link_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2093 picture_Hold( p_pic );
2096 static void video_unlink_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2099 picture_Release( p_pic );
2105 static subpicture_t *spu_new_buffer( decoder_t * );
2106 static void spu_del_buffer( decoder_t *, subpicture_t * );
2108 static int transcode_spu_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2110 sout_stream_sys_t *p_sys = p_stream->p_sys;
2116 /* Initialization of decoder structures */
2117 id->p_decoder->pf_decode_sub = NULL;
2118 id->p_decoder->pf_spu_buffer_new = spu_new_buffer;
2119 id->p_decoder->pf_spu_buffer_del = spu_del_buffer;
2120 id->p_decoder->p_owner = (decoder_owner_sys_t *)p_stream;
2121 /* id->p_decoder->p_cfg = p_sys->p_spu_cfg; */
2123 id->p_decoder->p_module =
2124 module_need( id->p_decoder, "decoder", "$codec", false );
2126 if( !id->p_decoder->p_module )
2128 msg_Err( p_stream, "cannot find spu decoder" );
2129 return VLC_EGENERIC;
2132 if( !p_sys->b_soverlay )
2135 /* Initialization of encoder format structures */
2136 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
2137 id->p_decoder->fmt_in.i_codec );
2139 id->p_encoder->p_cfg = p_sys->p_spu_cfg;
2141 id->p_encoder->p_module =
2142 module_need( id->p_encoder, "encoder", p_sys->psz_senc, true );
2144 if( !id->p_encoder->p_module )
2146 module_unneed( id->p_decoder, id->p_decoder->p_module );
2147 msg_Err( p_stream, "cannot find spu encoder (%s)", p_sys->psz_senc );
2148 return VLC_EGENERIC;
2154 p_sys->p_spu = spu_Create( p_stream );
2155 spu_Init( p_sys->p_spu );
2161 static void transcode_spu_close( sout_stream_id_t *id)
2164 if( id->p_decoder->p_module )
2165 module_unneed( id->p_decoder, id->p_decoder->p_module );
2166 if( id->p_decoder->p_description )
2167 vlc_meta_Delete( id->p_decoder->p_description );
2170 if( id->p_encoder->p_module )
2171 module_unneed( id->p_encoder, id->p_encoder->p_module );
2174 static int transcode_spu_process( sout_stream_t *p_stream,
2175 sout_stream_id_t *id,
2176 block_t *in, block_t **out )
2178 sout_stream_sys_t *p_sys = p_stream->p_sys;
2179 subpicture_t *p_subpic;
2182 p_subpic = id->p_decoder->pf_decode_sub( id->p_decoder, &in );
2184 return VLC_EGENERIC;
2186 sout_UpdateStatistic( p_stream->p_sout, SOUT_STATISTIC_DECODED_SUBTITLE, 1 );
2188 if( p_sys->b_master_sync && p_sys->i_master_drift )
2190 p_subpic->i_start -= p_sys->i_master_drift;
2191 if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2194 if( p_sys->b_soverlay )
2196 spu_DisplaySubpicture( p_sys->p_spu, p_subpic );
2202 p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
2203 spu_del_buffer( id->p_decoder, p_subpic );
2206 block_ChainAppend( out, p_block );
2211 return VLC_EGENERIC;
2214 static subpicture_t *spu_new_buffer( decoder_t *p_dec )
2216 VLC_UNUSED( p_dec );
2217 return subpicture_New();
2220 static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_subpic )
2222 VLC_UNUSED( p_dec );
2223 subpicture_Delete( p_subpic );
2229 static int transcode_osd_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2231 sout_stream_sys_t *p_sys = p_stream->p_sys;
2233 id->p_decoder->fmt_in.i_cat = SPU_ES;
2234 id->p_encoder->fmt_out.psz_language = strdup( "osd" );
2236 if( p_sys->i_osdcodec != 0 || p_sys->psz_osdenc )
2238 msg_Dbg( p_stream, "creating osdmenu transcoding from fcc=`%4.4s' "
2239 "to fcc=`%4.4s'", (char*)&id->p_encoder->fmt_out.i_codec,
2240 (char*)&p_sys->i_osdcodec );
2242 /* Complete destination format */
2243 id->p_encoder->fmt_out.i_codec = p_sys->i_osdcodec;
2246 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
2248 id->p_encoder->fmt_in.psz_language = strdup( "osd" );
2250 id->p_encoder->p_cfg = p_sys->p_osd_cfg;
2252 id->p_encoder->p_module =
2253 module_need( id->p_encoder, "encoder", p_sys->psz_osdenc, true );
2255 if( !id->p_encoder->p_module )
2257 msg_Err( p_stream, "cannot find spu encoder (%s)", p_sys->psz_osdenc );
2261 /* open output stream */
2262 id->id = sout_StreamIdAdd( p_sys->p_out, &id->p_encoder->fmt_out );
2263 id->b_transcode = true;
2265 if( !id->id ) goto error;
2269 msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
2270 (char*)&id->p_decoder->fmt_out.i_codec );
2271 id->id = sout_StreamIdAdd( p_sys->p_out, &id->p_decoder->fmt_out );
2272 id->b_transcode = false;
2274 if( !id->id ) goto error;
2279 p_sys->p_spu = spu_Create( p_stream );
2280 spu_Init( p_sys->p_spu );
2286 msg_Err( p_stream, "starting osd encoding thread failed" );
2287 if( id->p_encoder->p_module )
2288 module_unneed( id->p_encoder, id->p_encoder->p_module );
2289 p_sys->b_osd = false;
2290 return VLC_EGENERIC;
2293 static void transcode_osd_close( sout_stream_t *p_stream, sout_stream_id_t *id)
2295 sout_stream_sys_t *p_sys = p_stream->p_sys;
2300 if( id->p_encoder->p_module )
2301 module_unneed( id->p_encoder, id->p_encoder->p_module );
2303 p_sys->b_osd = false;
2306 static int transcode_osd_process( sout_stream_t *p_stream,
2307 sout_stream_id_t *id,
2308 block_t *in, block_t **out )
2310 sout_stream_sys_t *p_sys = p_stream->p_sys;
2311 subpicture_t *p_subpic = NULL;
2313 /* Check if we have a subpicture to send */
2314 if( p_sys->p_spu && in->i_dts > 0)
2316 p_subpic = spu_SortSubpictures( p_sys->p_spu, in->i_dts, false );
2320 msg_Warn( p_stream, "spu channel not initialized, doing it now" );
2323 p_sys->p_spu = spu_Create( p_stream );
2324 spu_Init( p_sys->p_spu );
2330 block_t *p_block = NULL;
2332 if( p_sys->b_master_sync && p_sys->i_master_drift )
2334 p_subpic->i_start -= p_sys->i_master_drift;
2335 if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2338 p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
2339 subpicture_Delete( p_subpic );
2342 p_block->i_dts = p_block->i_pts = in->i_dts;
2343 block_ChainAppend( out, p_block );
2347 return VLC_EGENERIC;