sout: transcode: handle controls
[vlc.git] / modules / stream_out / transcode / transcode.c
blob900707e29a916c49ff29c7fd28dd5354436b63eb
1 /*****************************************************************************
2 * transcode.c: transcoding stream output module
3 *****************************************************************************
4 * Copyright (C) 2003-2009 VLC authors and VideoLAN
5 * $Id$
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>
11 * Ilkka Ollakka <ileoo at videolan dot org>
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU Lesser General Public License as published by
15 * the Free Software Foundation; either version 2.1 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License for more details.
23 * You should have received a copy of the GNU Lesser General Public License
24 * along with this program; if not, write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
26 *****************************************************************************/
28 /*****************************************************************************
29 * Preamble
30 *****************************************************************************/
31 #ifdef HAVE_CONFIG_H
32 # include "config.h"
33 #endif
35 #include <vlc_common.h>
36 #include <vlc_plugin.h>
37 #include <vlc_sout.h>
38 #include <vlc_spu.h>
40 #include "transcode.h"
42 /*****************************************************************************
43 * Module descriptor
44 *****************************************************************************/
45 #define VENC_TEXT N_("Video encoder")
46 #define VENC_LONGTEXT N_( \
47 "This is the video encoder module that will be used (and its associated "\
48 "options).")
49 #define VCODEC_TEXT N_("Destination video codec")
50 #define VCODEC_LONGTEXT N_( \
51 "This is the video codec that will be used.")
52 #define VB_TEXT N_("Video bitrate")
53 #define VB_LONGTEXT N_( \
54 "Target bitrate of the transcoded video stream." )
55 #define SCALE_TEXT N_("Video scaling")
56 #define SCALE_LONGTEXT N_( \
57 "Scale factor to apply to the video while transcoding (eg: 0.25)")
58 #define FPS_TEXT N_("Video frame-rate")
59 #define FPS_LONGTEXT N_( \
60 "Target output frame rate for the video stream." )
61 #define DEINTERLACE_TEXT N_("Deinterlace video")
62 #define DEINTERLACE_LONGTEXT N_( \
63 "Deinterlace the video before encoding." )
64 #define DEINTERLACE_MODULE_TEXT N_("Deinterlace module")
65 #define DEINTERLACE_MODULE_LONGTEXT N_( \
66 "Specify the deinterlace module to use." )
67 #define WIDTH_TEXT N_("Video width")
68 #define WIDTH_LONGTEXT N_( \
69 "Output video width." )
70 #define HEIGHT_TEXT N_("Video height")
71 #define HEIGHT_LONGTEXT N_( \
72 "Output video height." )
73 #define MAXWIDTH_TEXT N_("Maximum video width")
74 #define MAXWIDTH_LONGTEXT N_( \
75 "Maximum output video width." )
76 #define MAXHEIGHT_TEXT N_("Maximum video height")
77 #define MAXHEIGHT_LONGTEXT N_( \
78 "Maximum output video height." )
79 #define VFILTER_TEXT N_("Video filter")
80 #define VFILTER_LONGTEXT N_( \
81 "Video filters will be applied to the video streams (after overlays " \
82 "are applied). You can enter a colon-separated list of filters." )
84 #define AENC_TEXT N_("Audio encoder")
85 #define AENC_LONGTEXT N_( \
86 "This is the audio encoder module that will be used (and its associated "\
87 "options).")
88 #define ACODEC_TEXT N_("Destination audio codec")
89 #define ACODEC_LONGTEXT N_( \
90 "This is the audio codec that will be used.")
91 #define AB_TEXT N_("Audio bitrate")
92 #define AB_LONGTEXT N_( \
93 "Target bitrate of the transcoded audio stream." )
94 #define ARATE_TEXT N_("Audio sample rate")
95 #define ARATE_LONGTEXT N_( \
96 "Sample rate of the transcoded audio stream (11250, 22500, 44100 or 48000).")
97 #define ALANG_TEXT N_("Audio language")
98 #define ALANG_LONGTEXT N_( \
99 "This is the language of the audio stream.")
100 #define ACHANS_TEXT N_("Audio channels")
101 #define ACHANS_LONGTEXT N_( \
102 "Number of audio channels in the transcoded streams." )
103 #define AFILTER_TEXT N_("Audio filter")
104 #define AFILTER_LONGTEXT N_( \
105 "Audio filters will be applied to the audio streams (after conversion " \
106 "filters are applied). You can enter a colon-separated list of filters." )
108 #define SENC_TEXT N_("Subtitle encoder")
109 #define SENC_LONGTEXT N_( \
110 "This is the subtitle encoder module that will be used (and its " \
111 "associated options)." )
112 #define SCODEC_TEXT N_("Destination subtitle codec")
113 #define SCODEC_LONGTEXT N_( \
114 "This is the subtitle codec that will be used." )
116 #define SFILTER_TEXT N_("Overlays")
117 #define SFILTER_LONGTEXT N_( \
118 "This allows you to add overlays (also known as \"subpictures\") on the "\
119 "transcoded video stream. The subpictures produced by the filters will "\
120 "be overlayed directly onto the video. You can specify a colon-separated "\
121 "list of subpicture modules." )
123 #define THREADS_TEXT N_("Number of threads")
124 #define THREADS_LONGTEXT N_( \
125 "Number of threads used for the transcoding." )
126 #define HP_TEXT N_("High priority")
127 #define HP_LONGTEXT N_( \
128 "Runs the optional encoder thread at the OUTPUT priority instead of " \
129 "VIDEO." )
130 #define POOL_TEXT N_("Picture pool size")
131 #define POOL_LONGTEXT N_( "Defines how many pictures we allow to be in pool "\
132 "between decoder/encoder threads when threads > 0" )
135 static const char *const ppsz_deinterlace_type[] =
137 "deinterlace", "ffmpeg-deinterlace"
140 static int Open ( vlc_object_t * );
141 static void Close( vlc_object_t * );
143 #define SOUT_CFG_PREFIX "sout-transcode-"
145 vlc_module_begin ()
146 set_shortname( N_("Transcode"))
147 set_description( N_("Transcode stream output") )
148 set_capability( "sout stream", 50 )
149 add_shortcut( "transcode" )
150 set_callbacks( Open, Close )
151 set_category( CAT_SOUT )
152 set_subcategory( SUBCAT_SOUT_STREAM )
153 set_section( N_("Video"), NULL )
154 add_module(SOUT_CFG_PREFIX "venc", "encoder", NULL,
155 VENC_TEXT, VENC_LONGTEXT)
156 add_string( SOUT_CFG_PREFIX "vcodec", NULL, VCODEC_TEXT,
157 VCODEC_LONGTEXT, false )
158 add_integer( SOUT_CFG_PREFIX "vb", 0, VB_TEXT,
159 VB_LONGTEXT, false )
160 add_float( SOUT_CFG_PREFIX "scale", 0, SCALE_TEXT,
161 SCALE_LONGTEXT, false )
162 add_string( SOUT_CFG_PREFIX "fps", NULL, FPS_TEXT,
163 FPS_LONGTEXT, false )
164 add_obsolete_bool( SOUT_CFG_PREFIX "hurry-up"); /* Since 2.2.0 */
165 add_bool( SOUT_CFG_PREFIX "deinterlace", false, DEINTERLACE_TEXT,
166 DEINTERLACE_LONGTEXT, false )
167 add_string( SOUT_CFG_PREFIX "deinterlace-module", "deinterlace",
168 DEINTERLACE_MODULE_TEXT, DEINTERLACE_MODULE_LONGTEXT,
169 false )
170 change_string_list( ppsz_deinterlace_type, ppsz_deinterlace_type )
171 add_integer( SOUT_CFG_PREFIX "width", 0, WIDTH_TEXT,
172 WIDTH_LONGTEXT, true )
173 add_integer( SOUT_CFG_PREFIX "height", 0, HEIGHT_TEXT,
174 HEIGHT_LONGTEXT, true )
175 add_integer( SOUT_CFG_PREFIX "maxwidth", 0, MAXWIDTH_TEXT,
176 MAXWIDTH_LONGTEXT, true )
177 add_integer( SOUT_CFG_PREFIX "maxheight", 0, MAXHEIGHT_TEXT,
178 MAXHEIGHT_LONGTEXT, true )
179 add_module_list(SOUT_CFG_PREFIX "vfilter", "video filter", NULL,
180 VFILTER_TEXT, VFILTER_LONGTEXT)
182 set_section( N_("Audio"), NULL )
183 add_module(SOUT_CFG_PREFIX "aenc", "encoder", NULL,
184 AENC_TEXT, AENC_LONGTEXT)
185 add_string( SOUT_CFG_PREFIX "acodec", NULL, ACODEC_TEXT,
186 ACODEC_LONGTEXT, false )
187 add_integer( SOUT_CFG_PREFIX "ab", 96, AB_TEXT,
188 AB_LONGTEXT, false )
189 add_string( SOUT_CFG_PREFIX "alang", NULL, ALANG_TEXT,
190 ALANG_LONGTEXT, true )
191 add_integer( SOUT_CFG_PREFIX "channels", 0, ACHANS_TEXT,
192 ACHANS_LONGTEXT, false )
193 change_integer_range( 0, 9 )
194 add_integer( SOUT_CFG_PREFIX "samplerate", 0, ARATE_TEXT,
195 ARATE_LONGTEXT, true )
196 change_integer_range( 0, 48000 )
197 add_obsolete_bool( SOUT_CFG_PREFIX "audio-sync" ) /*Since 2.2.0 */
198 add_module_list(SOUT_CFG_PREFIX "afilter", "audio filter", NULL,
199 AFILTER_TEXT, AFILTER_LONGTEXT)
201 set_section( N_("Overlays/Subtitles"), NULL )
202 add_module(SOUT_CFG_PREFIX "senc", "encoder", NULL,
203 SENC_TEXT, SENC_LONGTEXT)
204 add_string( SOUT_CFG_PREFIX "scodec", NULL, SCODEC_TEXT,
205 SCODEC_LONGTEXT, false )
206 add_bool( SOUT_CFG_PREFIX "soverlay", false, SCODEC_TEXT,
207 SCODEC_LONGTEXT, false )
208 add_module_list(SOUT_CFG_PREFIX "sfilter", "spu source", NULL,
209 SFILTER_TEXT, SFILTER_LONGTEXT)
211 set_section( N_("Miscellaneous"), NULL )
212 add_integer( SOUT_CFG_PREFIX "threads", 0, THREADS_TEXT,
213 THREADS_LONGTEXT, true )
214 change_integer_range( 0, 32 )
215 add_integer( SOUT_CFG_PREFIX "pool-size", 10, POOL_TEXT, POOL_LONGTEXT, true )
216 change_integer_range( 1, 1000 )
217 add_bool( SOUT_CFG_PREFIX "high-priority", false, HP_TEXT, HP_LONGTEXT,
218 true )
220 vlc_module_end ()
222 static const char *const ppsz_sout_options[] = {
223 "venc", "vcodec", "vb",
224 "scale", "fps", "width", "height", "vfilter", "deinterlace",
225 "deinterlace-module", "threads", "aenc", "acodec", "ab", "alang",
226 "afilter", "samplerate", "channels", "senc", "scodec", "soverlay",
227 "sfilter", "high-priority", "maxwidth", "maxheight", "pool-size",
228 NULL
231 /*****************************************************************************
232 * Exported prototypes
233 *****************************************************************************/
234 static void *Add( sout_stream_t *, const es_format_t * );
235 static void Del( sout_stream_t *, void * );
236 static int Send( sout_stream_t *, void *, block_t * );
238 static void SetAudioEncoderConfig( sout_stream_t *p_stream, transcode_encoder_config_t *p_cfg )
240 char *psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "aenc" );
241 if( psz_string && *psz_string )
243 char *psz_next = config_ChainCreate( &p_cfg->psz_name,
244 &p_cfg->p_config_chain,
245 psz_string );
246 free( psz_next );
248 free( psz_string );
250 psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "acodec" );
251 p_cfg->i_codec = 0;
252 if( psz_string && *psz_string )
254 char fcc[5] = " \0";
255 memcpy( fcc, psz_string, __MIN( strlen( psz_string ), 4 ) );
256 p_cfg->i_codec = vlc_fourcc_GetCodecFromString( AUDIO_ES, fcc );
257 msg_Dbg( p_stream, "Checking codec mapping for %s got %4.4s ",
258 fcc, (char*)&p_cfg->i_codec);
260 free( psz_string );
262 p_cfg->audio.i_bitrate = var_GetInteger( p_stream, SOUT_CFG_PREFIX "ab" );
263 if( p_cfg->audio.i_bitrate < 4000 )
264 p_cfg->audio.i_bitrate *= 1000;
266 p_cfg->audio.i_sample_rate = var_GetInteger( p_stream, SOUT_CFG_PREFIX "samplerate" );
267 p_cfg->audio.i_channels = var_GetInteger( p_stream, SOUT_CFG_PREFIX "channels" );
269 if( p_cfg->i_codec )
271 if( ( p_cfg->i_codec == VLC_CODEC_MP3 ||
272 p_cfg->i_codec == VLC_CODEC_MP2 ||
273 p_cfg->i_codec == VLC_CODEC_MPGA ) &&
274 p_cfg->audio.i_channels > 2 )
276 msg_Warn( p_stream, "%d channels invalid for mp2/mp3, forcing to 2",
277 p_cfg->audio.i_channels );
278 p_cfg->audio.i_channels = 2;
280 msg_Dbg( p_stream, "codec audio=%4.4s %dHz %d channels %dKb/s",
281 (char *)&p_cfg->i_codec, p_cfg->audio.i_sample_rate,
282 p_cfg->audio.i_channels, p_cfg->audio.i_bitrate / 1000 );
285 p_cfg->psz_lang = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "alang" );
288 static void SetVideoEncoderConfig( sout_stream_t *p_stream, transcode_encoder_config_t *p_cfg )
290 char *psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "venc" );
291 if( psz_string && *psz_string )
293 char *psz_next;
294 psz_next = config_ChainCreate( &p_cfg->psz_name,
295 &p_cfg->p_config_chain,
296 psz_string );
297 free( psz_next );
299 free( psz_string );
301 psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "vcodec" );
302 if( psz_string && *psz_string )
304 char fcc[5] = " \0";
305 memcpy( fcc, psz_string, __MIN( strlen( psz_string ), 4 ) );
306 p_cfg->i_codec = vlc_fourcc_GetCodecFromString( VIDEO_ES, fcc );
307 msg_Dbg( p_stream, "Checking video codec mapping for %s got %4.4s ",
308 fcc, (char*)&p_cfg->i_codec);
310 free( psz_string );
312 p_cfg->video.i_bitrate = var_GetInteger( p_stream, SOUT_CFG_PREFIX "vb" );
313 if( p_cfg->video.i_bitrate < 16000 )
314 p_cfg->video.i_bitrate *= 1000;
316 p_cfg->video.f_scale = var_GetFloat( p_stream, SOUT_CFG_PREFIX "scale" );
318 var_InheritURational( p_stream, &p_cfg->video.fps.num,
319 &p_cfg->video.fps.den,
320 SOUT_CFG_PREFIX "fps" );
322 p_cfg->video.i_width = var_GetInteger( p_stream, SOUT_CFG_PREFIX "width" );
323 p_cfg->video.i_height = var_GetInteger( p_stream, SOUT_CFG_PREFIX "height" );
324 p_cfg->video.i_maxwidth = var_GetInteger( p_stream, SOUT_CFG_PREFIX "maxwidth" );
325 p_cfg->video.i_maxheight = var_GetInteger( p_stream, SOUT_CFG_PREFIX "maxheight" );
327 p_cfg->video.threads.i_count = var_GetInteger( p_stream, SOUT_CFG_PREFIX "threads" );
328 p_cfg->video.threads.pool_size = var_GetInteger( p_stream, SOUT_CFG_PREFIX "pool-size" );
330 if( var_GetBool( p_stream, SOUT_CFG_PREFIX "high-priority" ) )
331 p_cfg->video.threads.i_priority = VLC_THREAD_PRIORITY_OUTPUT;
332 else
333 p_cfg->video.threads.i_priority = VLC_THREAD_PRIORITY_VIDEO;
336 static void SetSPUEncoderConfig( sout_stream_t *p_stream, transcode_encoder_config_t *p_cfg )
338 char *psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "senc" );
339 if( psz_string && *psz_string )
341 char *psz_next;
342 psz_next = config_ChainCreate( &p_cfg->psz_name, &p_cfg->p_config_chain,
343 psz_string );
344 free( psz_next );
346 free( psz_string );
348 psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "scodec" );
349 if( psz_string && *psz_string )
351 char fcc[5] = " \0";
352 memcpy( fcc, psz_string, __MIN( strlen( psz_string ), 4 ) );
353 p_cfg->i_codec = vlc_fourcc_GetCodecFromString( SPU_ES, fcc );
354 msg_Dbg( p_stream, "Checking spu codec mapping for %s got %4.4s ", fcc, (char*)&p_cfg->i_codec);
356 free( psz_string );
359 /*****************************************************************************
360 * Control
361 *****************************************************************************/
362 static int Control( sout_stream_t *p_stream, int i_query, va_list args )
364 switch( i_query )
366 case SOUT_STREAM_EMPTY:
367 if( p_stream->p_next )
368 return sout_StreamControlVa( p_stream->p_next, i_query, args );
370 return VLC_EGENERIC;
373 /*****************************************************************************
374 * Open:
375 *****************************************************************************/
376 static int Open( vlc_object_t *p_this )
378 sout_stream_t *p_stream = (sout_stream_t*)p_this;
379 sout_stream_sys_t *p_sys;
380 char *psz_string;
382 if( !p_stream->p_next )
384 msg_Err( p_stream, "cannot create chain" );
385 return VLC_EGENERIC;
387 p_sys = calloc( 1, sizeof( *p_sys ) );
389 config_ChainParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
390 p_stream->p_cfg );
392 /* Audio transcoding parameters */
393 transcode_encoder_config_init( &p_sys->aenc_cfg );
394 SetAudioEncoderConfig( p_stream, &p_sys->aenc_cfg );
396 /* Audio Filter Parameters */
397 sout_filters_config_init( &p_sys->afilters_cfg );
399 psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "afilter" );
400 if( psz_string && *psz_string )
401 p_sys->afilters_cfg.psz_filters = psz_string;
402 else
403 free( psz_string );
405 /* Video transcoding parameters */
406 transcode_encoder_config_init( &p_sys->venc_cfg );
408 SetVideoEncoderConfig( p_stream, &p_sys->venc_cfg );
409 p_sys->b_master_sync = (p_sys->venc_cfg.video.fps.num > 0);
410 if( p_sys->venc_cfg.i_codec )
412 msg_Dbg( p_stream, "codec video=%4.4s %dx%d scaling: %f %dkb/s",
413 (char *)&p_sys->venc_cfg.i_codec,
414 p_sys->venc_cfg.video.i_width,
415 p_sys->venc_cfg.video.i_height,
416 p_sys->venc_cfg.video.f_scale,
417 p_sys->venc_cfg.video.i_bitrate / 1000 );
420 /* Video Filter Parameters */
421 sout_filters_config_init( &p_sys->vfilters_cfg );
423 psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "vfilter" );
424 if( psz_string && *psz_string )
425 p_sys->vfilters_cfg.psz_filters = psz_string;
426 else
427 free( psz_string );
429 if( var_GetBool( p_stream, SOUT_CFG_PREFIX "deinterlace" ) )
431 psz_string = var_GetString( p_stream,
432 SOUT_CFG_PREFIX "deinterlace-module" );
433 if( psz_string )
434 free( config_ChainCreate( &p_sys->vfilters_cfg.video.psz_deinterlace,
435 &p_sys->vfilters_cfg.video.p_deinterlace_cfg, psz_string ) );
436 free( psz_string );
439 /* Subpictures SOURCES parameters (not releated to subtitles stream) */
440 psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "sfilter" );
441 if( psz_string && *psz_string )
442 p_sys->vfilters_cfg.video.psz_spu_sources = psz_string;
443 else
444 free( psz_string );
446 /* Subpictures transcoding parameters */
447 transcode_encoder_config_init( &p_sys->senc_cfg );
449 SetSPUEncoderConfig( p_stream, &p_sys->senc_cfg );
450 if( p_sys->senc_cfg.i_codec )
451 msg_Dbg( p_stream, "codec spu=%4.4s", (char *)&p_sys->senc_cfg.i_codec );
453 p_sys->b_soverlay = var_GetBool( p_stream, SOUT_CFG_PREFIX "soverlay" );
454 /* Set default size for TEXT spu non overlay conversion / updater */
455 p_sys->senc_cfg.spu.i_width = (p_sys->venc_cfg.video.i_width) ? p_sys->venc_cfg.video.i_width : 1280;
456 p_sys->senc_cfg.spu.i_height = (p_sys->venc_cfg.video.i_height) ? p_sys->venc_cfg.video.i_height : 720;
458 p_stream->pf_add = Add;
459 p_stream->pf_del = Del;
460 p_stream->pf_send = Send;
461 p_stream->pf_control = Control;
462 p_stream->p_sys = p_sys;
464 return VLC_SUCCESS;
467 /*****************************************************************************
468 * Close:
469 *****************************************************************************/
470 static void Close( vlc_object_t * p_this )
472 sout_stream_t *p_stream = (sout_stream_t*)p_this;
473 sout_stream_sys_t *p_sys = p_stream->p_sys;
475 transcode_encoder_config_clean( &p_sys->venc_cfg );
476 sout_filters_config_clean( &p_sys->vfilters_cfg );
478 transcode_encoder_config_clean( &p_sys->aenc_cfg );
479 sout_filters_config_clean( &p_sys->afilters_cfg );
481 transcode_encoder_config_clean( &p_sys->senc_cfg );
483 free( p_sys );
486 static void DeleteSoutStreamID( sout_stream_id_sys_t *id )
488 if( id )
490 if( id->p_decoder )
492 es_format_Clean( &id->p_decoder->fmt_in );
493 es_format_Clean( &id->p_decoder->fmt_out );
494 vlc_object_release( id->p_decoder );
497 vlc_mutex_destroy(&id->fifo.lock);
498 free( id );
502 static void SendSpuToVideoCallback( void *cbdata, subpicture_t *p_subpicture )
504 sout_stream_t *p_stream = cbdata;
505 sout_stream_sys_t *p_sys = p_stream->p_sys;
506 if( !p_sys->id_video )
507 subpicture_Delete( p_subpicture );
508 else
509 transcode_video_push_spu( p_stream,
510 p_sys->id_video, p_subpicture );
513 static int GetVideoDimensions( void *cbdata, unsigned *w, unsigned *h )
515 sout_stream_t *p_stream = cbdata;
516 sout_stream_sys_t *p_sys = p_stream->p_sys;
517 if( !p_sys->id_video )
518 return VLC_EGENERIC;
519 return transcode_video_get_output_dimensions( p_stream,
520 p_sys->id_video, w, h );
523 static vlc_tick_t GetMasterDrift( void *cbdata )
525 sout_stream_t *p_stream = cbdata;
526 sout_stream_sys_t *p_sys = p_stream->p_sys;
527 if( p_sys->id_master_sync )
529 return p_sys->id_master_sync->i_drift;
531 return 0;
534 static int ValidateDrift( void *cbdata, vlc_tick_t i_drift )
536 sout_stream_t *p_stream = cbdata;
537 if( unlikely(i_drift > MASTER_SYNC_MAX_DRIFT ||
538 i_drift < -MASTER_SYNC_MAX_DRIFT) )
540 msg_Dbg( p_stream, "drift is too high (%"PRId64"), resetting master sync",
541 i_drift );
542 return VLC_EGENERIC;
544 return VLC_SUCCESS;
547 static void *transcode_downstream_Add( sout_stream_t *p_stream,
548 const es_format_t *fmt_orig,
549 const es_format_t *fmt)
551 sout_stream_sys_t *p_sys = p_stream->p_sys;
553 es_format_t tmp;
554 es_format_Init( &tmp, fmt->i_cat, fmt->i_codec );
555 es_format_Copy( &tmp, fmt );
557 if( !fmt->psz_language )
559 if( p_sys->aenc_cfg.psz_lang )
560 tmp.psz_language = strdup( p_sys->aenc_cfg.psz_lang );
561 else if( fmt_orig->psz_language )
562 tmp.psz_language = strdup( fmt_orig->psz_language );
565 if( tmp.i_id != fmt_orig->i_id )
566 tmp.i_id = fmt_orig->i_id;
567 if( tmp.i_group != fmt_orig->i_group )
568 tmp.i_group = fmt_orig->i_group;
570 void *downstream = sout_StreamIdAdd( p_stream->p_next, &tmp );
571 es_format_Clean( &tmp );
572 return downstream;
575 static void *Add( sout_stream_t *p_stream, const es_format_t *p_fmt )
577 sout_stream_sys_t *p_sys = p_stream->p_sys;
578 sout_stream_id_sys_t *id;
580 id = calloc( 1, sizeof( sout_stream_id_sys_t ) );
581 if( !id )
582 return NULL;
584 vlc_mutex_init(&id->fifo.lock);
585 id->pf_transcode_downstream_add = transcode_downstream_Add;
587 /* Create decoder object */
588 struct decoder_owner * p_owner = vlc_object_create( p_stream, sizeof( *p_owner ) );
589 if( !p_owner )
590 goto error;
591 p_owner->p_obj = VLC_OBJECT(p_stream);
593 id->p_decoder = &p_owner->dec;
594 id->p_decoder->p_module = NULL;
595 es_format_Init( &id->p_decoder->fmt_out, p_fmt->i_cat, 0 );
596 es_format_Copy( &id->p_decoder->fmt_in, p_fmt );
597 es_format_SetMeta( &id->p_decoder->fmt_out, &id->p_decoder->fmt_in );
598 id->p_decoder->b_frame_drop_allowed = false;
600 switch( p_fmt->i_cat )
602 case AUDIO_ES:
603 id->p_filterscfg = &p_sys->afilters_cfg;
604 id->p_enccfg = &p_sys->aenc_cfg;
605 if( p_sys->b_master_sync )
607 id->pf_drift_validate = ValidateDrift;
608 id->callback_data = p_sys;
610 break;
611 case VIDEO_ES:
612 id->p_filterscfg = &p_sys->vfilters_cfg;
613 id->p_enccfg = &p_sys->venc_cfg;
614 break;
615 case SPU_ES:
616 id->p_filterscfg = NULL;
617 id->p_enccfg = &p_sys->senc_cfg;
618 id->pf_send_subpicture = SendSpuToVideoCallback;
619 id->pf_get_output_dimensions = GetVideoDimensions;
620 if( p_sys->b_master_sync )
621 id->pf_get_master_drift = GetMasterDrift;
622 id->callback_data = p_stream;
623 break;
624 default:
625 break;
628 bool success;
630 if( p_fmt->i_cat == AUDIO_ES && id->p_enccfg->i_codec )
632 success = !transcode_audio_init(p_stream, p_fmt, id);
633 if( success && p_sys->b_master_sync && !p_sys->id_master_sync )
634 p_sys->id_master_sync = id;
636 else if( p_fmt->i_cat == VIDEO_ES && id->p_enccfg->i_codec )
638 success = !transcode_video_init(p_stream, p_fmt, id);
639 if( success && !p_sys->id_video )
640 p_sys->id_video = id;
642 else if( ( p_fmt->i_cat == SPU_ES ) &&
643 ( id->p_enccfg->i_codec || p_sys->b_soverlay ) )
644 success = !transcode_spu_init(p_stream, p_fmt, id);
645 else
647 msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
648 (char*)&p_fmt->i_codec );
649 id->downstream_id = transcode_downstream_Add( p_stream, p_fmt, p_fmt );
650 id->b_transcode = false;
652 success = id->downstream_id;
655 if(!success)
656 goto error;
658 return id;
660 error:
661 DeleteSoutStreamID( id );
662 return NULL;
665 static void Del( sout_stream_t *p_stream, void *_id )
667 sout_stream_sys_t *p_sys = p_stream->p_sys;
668 sout_stream_id_sys_t *id = (sout_stream_id_sys_t *)_id;
669 if( id->b_transcode )
671 switch( id->p_decoder->fmt_in.i_cat )
673 case AUDIO_ES:
674 Send( p_stream, id, NULL );
675 transcode_audio_clean( id );
676 if( id == p_sys->id_master_sync )
677 p_sys->id_master_sync = NULL;
678 break;
679 case VIDEO_ES:
680 Send( p_stream, id, NULL );
681 if( id == p_sys->id_video )
682 p_sys->id_video = NULL;
683 transcode_video_clean( p_stream, id );
684 break;
685 case SPU_ES:
686 transcode_spu_clean( p_stream, id );
687 break;
688 default:
689 break;
693 if( id->downstream_id ) sout_StreamIdDel( p_stream->p_next, id->downstream_id );
695 DeleteSoutStreamID( id );
698 static int Send( sout_stream_t *p_stream, void *_id, block_t *p_buffer )
700 sout_stream_id_sys_t *id = (sout_stream_id_sys_t *)_id;
701 block_t *p_out = NULL;
703 if( id->b_error )
704 goto error;
706 if( !id->b_transcode )
708 if( id->downstream_id )
709 return sout_StreamIdSend( p_stream->p_next, id->downstream_id, p_buffer );
710 else
711 goto error;
714 int i_ret;
715 switch( id->p_decoder->fmt_in.i_cat )
717 case AUDIO_ES:
718 i_ret = transcode_audio_process( p_stream, id, p_buffer, &p_out );
719 break;
721 case VIDEO_ES:
722 i_ret = transcode_video_process( p_stream, id, p_buffer, &p_out );
723 break;
725 case SPU_ES:
726 i_ret = transcode_spu_process( p_stream, id, p_buffer, &p_out );
727 break;
729 default:
730 goto error;
733 if( p_out &&
734 sout_StreamIdSend( p_stream->p_next, id->downstream_id, p_out ) )
735 i_ret = VLC_EGENERIC;
737 return i_ret;
738 error:
739 if( p_buffer )
740 block_Release( p_buffer );
741 return VLC_EGENERIC;