]> git.sesse.net Git - vlc/blob - modules/stream_out/transcode/transcode.c
transcode: initialize audio encoder after first packet arrives
[vlc] / modules / stream_out / transcode / transcode.c
1 /*****************************************************************************
2  * transcode.c: transcoding stream output module
3  *****************************************************************************
4  * Copyright (C) 2003-2009 VLC authors and VideoLAN
5  * $Id$
6  *
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>
12  *
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.
17  *
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.
22  *
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  *****************************************************************************/
27
28 /*****************************************************************************
29  * Preamble
30  *****************************************************************************/
31 #ifdef HAVE_CONFIG_H
32 # include "config.h"
33 #endif
34
35 #include <vlc_common.h>
36 #include <vlc_plugin.h>
37
38 #include <vlc_spu.h>
39
40 #include "transcode.h"
41
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." )
83
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." )
107
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." )
115
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" )
122
123 #define OSD_TEXT N_("OSD menu")
124 #define OSD_LONGTEXT N_(\
125     "Stream the On Screen Display menu (using the osdmenu subpicture module)." )
126
127 #define THREADS_TEXT N_("Number of threads")
128 #define THREADS_LONGTEXT N_( \
129     "Number of threads used for the transcoding." )
130 #define HP_TEXT N_("High priority")
131 #define HP_LONGTEXT N_( \
132     "Runs the optional encoder thread at the OUTPUT priority instead of " \
133     "VIDEO." )
134
135 #define ASYNC_TEXT N_("Synchronise on audio track")
136 #define ASYNC_LONGTEXT N_( \
137     "This option will drop/duplicate video frames to synchronise the video " \
138     "track on the audio track." )
139
140 #define HURRYUP_TEXT N_( "Hurry up" )
141 #define HURRYUP_LONGTEXT N_( "The transcoder will drop frames if your CPU " \
142                 "can't keep up with the encoding rate." )
143
144 static const char *const ppsz_deinterlace_type[] =
145 {
146     "deinterlace", "ffmpeg-deinterlace"
147 };
148
149 static int  Open ( vlc_object_t * );
150 static void Close( vlc_object_t * );
151
152 #define SOUT_CFG_PREFIX "sout-transcode-"
153
154 vlc_module_begin ()
155     set_shortname( N_("Transcode"))
156     set_description( N_("Transcode stream output") )
157     set_capability( "sout stream", 50 )
158     add_shortcut( "transcode" )
159     set_callbacks( Open, Close )
160     set_category( CAT_SOUT )
161     set_subcategory( SUBCAT_SOUT_STREAM )
162     set_section( N_("Video"), NULL )
163     add_module( SOUT_CFG_PREFIX "venc", "encoder", NULL, VENC_TEXT,
164                 VENC_LONGTEXT, false )
165     add_string( SOUT_CFG_PREFIX "vcodec", NULL, VCODEC_TEXT,
166                 VCODEC_LONGTEXT, false )
167     add_integer( SOUT_CFG_PREFIX "vb", 0, VB_TEXT,
168                  VB_LONGTEXT, false )
169     add_float( SOUT_CFG_PREFIX "scale", 0, SCALE_TEXT,
170                SCALE_LONGTEXT, false )
171     add_float( SOUT_CFG_PREFIX "fps", 0, FPS_TEXT,
172                FPS_LONGTEXT, false )
173     add_bool( SOUT_CFG_PREFIX "hurry-up", false, HURRYUP_TEXT,
174                HURRYUP_LONGTEXT, false )
175     add_bool( SOUT_CFG_PREFIX "deinterlace", false, DEINTERLACE_TEXT,
176               DEINTERLACE_LONGTEXT, false )
177     add_string( SOUT_CFG_PREFIX "deinterlace-module", "deinterlace",
178                 DEINTERLACE_MODULE_TEXT, DEINTERLACE_MODULE_LONGTEXT,
179                 false )
180         change_string_list( ppsz_deinterlace_type, ppsz_deinterlace_type )
181     add_integer( SOUT_CFG_PREFIX "width", 0, WIDTH_TEXT,
182                  WIDTH_LONGTEXT, true )
183     add_integer( SOUT_CFG_PREFIX "height", 0, HEIGHT_TEXT,
184                  HEIGHT_LONGTEXT, true )
185     add_integer( SOUT_CFG_PREFIX "maxwidth", 0, MAXWIDTH_TEXT,
186                  MAXWIDTH_LONGTEXT, true )
187     add_integer( SOUT_CFG_PREFIX "maxheight", 0, MAXHEIGHT_TEXT,
188                  MAXHEIGHT_LONGTEXT, true )
189     add_module_list( SOUT_CFG_PREFIX "vfilter", "video filter2",
190                      NULL, VFILTER_TEXT, VFILTER_LONGTEXT, false )
191
192     set_section( N_("Audio"), NULL )
193     add_module( SOUT_CFG_PREFIX "aenc", "encoder", NULL, AENC_TEXT,
194                 AENC_LONGTEXT, false )
195     add_string( SOUT_CFG_PREFIX "acodec", NULL, ACODEC_TEXT,
196                 ACODEC_LONGTEXT, false )
197     add_integer( SOUT_CFG_PREFIX "ab", 96, AB_TEXT,
198                  AB_LONGTEXT, false )
199     add_string( SOUT_CFG_PREFIX "alang", NULL, ALANG_TEXT,
200                 ALANG_LONGTEXT, true )
201     add_integer( SOUT_CFG_PREFIX "channels", 0, ACHANS_TEXT,
202                  ACHANS_LONGTEXT, false )
203     add_integer( SOUT_CFG_PREFIX "samplerate", 0, ARATE_TEXT,
204                  ARATE_LONGTEXT, true )
205     add_bool( SOUT_CFG_PREFIX "audio-sync", false, ASYNC_TEXT,
206               ASYNC_LONGTEXT, false )
207     add_module_list( SOUT_CFG_PREFIX "afilter",  "audio filter",
208                      NULL, AFILTER_TEXT, AFILTER_LONGTEXT, false )
209
210     set_section( N_("Overlays/Subtitles"), NULL )
211     add_module( SOUT_CFG_PREFIX "senc", "encoder", NULL, SENC_TEXT,
212                 SENC_LONGTEXT, false )
213     add_string( SOUT_CFG_PREFIX "scodec", NULL, SCODEC_TEXT,
214                 SCODEC_LONGTEXT, false )
215     add_bool( SOUT_CFG_PREFIX "soverlay", false, SCODEC_TEXT,
216                SCODEC_LONGTEXT, false )
217     add_module_list( SOUT_CFG_PREFIX "sfilter", "video filter",
218                      NULL, SFILTER_TEXT, SFILTER_LONGTEXT, false )
219
220     set_section( N_("On Screen Display"), NULL )
221     add_bool( SOUT_CFG_PREFIX "osd", false, OSD_TEXT,
222               OSD_LONGTEXT, false )
223
224     set_section( N_("Miscellaneous"), NULL )
225     add_integer( SOUT_CFG_PREFIX "threads", 0, THREADS_TEXT,
226                  THREADS_LONGTEXT, true )
227     add_bool( SOUT_CFG_PREFIX "high-priority", false, HP_TEXT, HP_LONGTEXT,
228               true )
229
230 vlc_module_end ()
231
232 static const char *const ppsz_sout_options[] = {
233     "venc", "vcodec", "vb",
234     "scale", "fps", "width", "height", "vfilter", "deinterlace",
235     "deinterlace-module", "threads", "hurry-up", "aenc", "acodec", "ab", "alang",
236     "afilter", "samplerate", "channels", "senc", "scodec", "soverlay",
237     "sfilter", "osd", "audio-sync", "high-priority", "maxwidth", "maxheight",
238     NULL
239 };
240
241 /*****************************************************************************
242  * Exported prototypes
243  *****************************************************************************/
244 static sout_stream_id_t *Add ( sout_stream_t *, es_format_t * );
245 static int               Del ( sout_stream_t *, sout_stream_id_t * );
246 static int               Send( sout_stream_t *, sout_stream_id_t *, block_t* );
247
248 /*****************************************************************************
249  * Open:
250  *****************************************************************************/
251 static int Open( vlc_object_t *p_this )
252 {
253     sout_stream_t     *p_stream = (sout_stream_t*)p_this;
254     sout_stream_sys_t *p_sys;
255     char              *psz_string;
256
257     if( !p_stream->p_next )
258     {
259         msg_Err( p_stream, "cannot create chain" );
260         return VLC_EGENERIC;
261     }
262     p_sys = calloc( 1, sizeof( *p_sys ) );
263     p_sys->i_master_drift = 0;
264
265     config_ChainParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
266                    p_stream->p_cfg );
267
268     /* Audio transcoding parameters */
269     psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "aenc" );
270     p_sys->psz_aenc = NULL;
271     p_sys->p_audio_cfg = NULL;
272     if( psz_string && *psz_string )
273     {
274         char *psz_next;
275         psz_next = config_ChainCreate( &p_sys->psz_aenc, &p_sys->p_audio_cfg,
276                                        psz_string );
277         free( psz_next );
278     }
279     free( psz_string );
280
281     psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "acodec" );
282     p_sys->i_acodec = 0;
283     if( psz_string && *psz_string )
284     {
285         char fcc[4] = "    ";
286         memcpy( fcc, psz_string, __MIN( strlen( psz_string ), 4 ) );
287         p_sys->i_acodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
288     }
289     free( psz_string );
290
291     p_sys->psz_alang = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "alang" );
292
293     p_sys->i_abitrate = var_GetInteger( p_stream, SOUT_CFG_PREFIX "ab" );
294     if( p_sys->i_abitrate < 4000 ) p_sys->i_abitrate *= 1000;
295
296     p_sys->i_sample_rate = var_GetInteger( p_stream, SOUT_CFG_PREFIX "samplerate" );
297
298     p_sys->i_channels = var_GetInteger( p_stream, SOUT_CFG_PREFIX "channels" );
299
300     if( p_sys->i_acodec )
301     {
302         if( ( p_sys->i_acodec == VLC_CODEC_MP3 ||
303               p_sys->i_acodec == VLC_CODEC_MP2 ||
304               p_sys->i_acodec == VLC_CODEC_MPGA ) && p_sys->i_channels > 2 )
305         {
306             msg_Warn( p_stream, "%d channels invalid for mp2/mp3, forcing to 2",
307                       p_sys->i_channels );
308             p_sys->i_channels = 2;
309         }
310         msg_Dbg( p_stream, "codec audio=%4.4s %dHz %d channels %dKb/s",
311                  (char *)&p_sys->i_acodec, p_sys->i_sample_rate,
312                  p_sys->i_channels, p_sys->i_abitrate / 1000 );
313     }
314
315     psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "afilter" );
316     if( psz_string && *psz_string )
317         p_sys->psz_af = strdup( psz_string );
318     else
319         p_sys->psz_af = NULL;
320     free( psz_string );
321
322     /* Video transcoding parameters */
323     psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "venc" );
324     p_sys->psz_venc = NULL;
325     p_sys->p_video_cfg = NULL;
326     if( psz_string && *psz_string )
327     {
328         char *psz_next;
329         psz_next = config_ChainCreate( &p_sys->psz_venc, &p_sys->p_video_cfg,
330                                    psz_string );
331         free( psz_next );
332     }
333     free( psz_string );
334
335     psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "vcodec" );
336     p_sys->i_vcodec = 0;
337     if( psz_string && *psz_string )
338     {
339         char fcc[4] = "    ";
340         memcpy( fcc, psz_string, __MIN( strlen( psz_string ), 4 ) );
341         p_sys->i_vcodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
342     }
343     free( psz_string );
344
345     p_sys->i_vbitrate = var_GetInteger( p_stream, SOUT_CFG_PREFIX "vb" );
346     if( p_sys->i_vbitrate < 16000 ) p_sys->i_vbitrate *= 1000;
347
348     p_sys->f_scale = var_GetFloat( p_stream, SOUT_CFG_PREFIX "scale" );
349
350     p_sys->f_fps = var_GetFloat( p_stream, SOUT_CFG_PREFIX "fps" );
351
352     p_sys->b_hurry_up = var_GetBool( p_stream, SOUT_CFG_PREFIX "hurry-up" );
353
354     p_sys->i_width = var_GetInteger( p_stream, SOUT_CFG_PREFIX "width" );
355
356     p_sys->i_height = var_GetInteger( p_stream, SOUT_CFG_PREFIX "height" );
357
358     p_sys->i_maxwidth = var_GetInteger( p_stream, SOUT_CFG_PREFIX "maxwidth" );
359
360     p_sys->i_maxheight = var_GetInteger( p_stream, SOUT_CFG_PREFIX "maxheight" );
361
362     psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "vfilter" );
363     if( psz_string && *psz_string )
364         p_sys->psz_vf2 = strdup(psz_string );
365     else
366         p_sys->psz_vf2 = NULL;
367     free( psz_string );
368
369     p_sys->b_deinterlace = var_GetBool( p_stream, SOUT_CFG_PREFIX "deinterlace" );
370
371     psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "deinterlace-module" );
372     p_sys->psz_deinterlace = NULL;
373     p_sys->p_deinterlace_cfg = NULL;
374     if( psz_string && *psz_string )
375     {
376         char *psz_next;
377         psz_next = config_ChainCreate( &p_sys->psz_deinterlace,
378                                    &p_sys->p_deinterlace_cfg,
379                                    psz_string );
380         free( psz_next );
381     }
382     free( psz_string );
383
384     p_sys->i_threads = var_GetInteger( p_stream, SOUT_CFG_PREFIX "threads" );
385     p_sys->b_high_priority = var_GetBool( p_stream, SOUT_CFG_PREFIX "high-priority" );
386
387     if( p_sys->i_vcodec )
388     {
389         msg_Dbg( p_stream, "codec video=%4.4s %dx%d scaling: %f %dkb/s",
390                  (char *)&p_sys->i_vcodec, p_sys->i_width, p_sys->i_height,
391                  p_sys->f_scale, p_sys->i_vbitrate / 1000 );
392     }
393
394     /* Subpictures transcoding parameters */
395     p_sys->p_spu = NULL;
396     p_sys->p_spu_blend = NULL;
397     p_sys->psz_senc = NULL;
398     p_sys->p_spu_cfg = NULL;
399     p_sys->i_scodec = 0;
400
401     psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "senc" );
402     if( psz_string && *psz_string )
403     {
404         char *psz_next;
405         psz_next = config_ChainCreate( &p_sys->psz_senc, &p_sys->p_spu_cfg,
406                                    psz_string );
407         free( psz_next );
408     }
409     free( psz_string );
410
411     psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "scodec" );
412     if( psz_string && *psz_string )
413     {
414         char fcc[4] = "    ";
415         memcpy( fcc, psz_string, __MIN( strlen( psz_string ), 4 ) );
416         p_sys->i_scodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
417     }
418     free( psz_string );
419
420     if( p_sys->i_scodec )
421     {
422         msg_Dbg( p_stream, "codec spu=%4.4s", (char *)&p_sys->i_scodec );
423     }
424
425     p_sys->b_soverlay = var_GetBool( p_stream, SOUT_CFG_PREFIX "soverlay" );
426
427     psz_string = var_GetString( p_stream, SOUT_CFG_PREFIX "sfilter" );
428     if( psz_string && *psz_string )
429     {
430         p_sys->p_spu = spu_Create( p_stream );
431         if( p_sys->p_spu )
432             spu_ChangeSources( p_sys->p_spu, psz_string );
433     }
434     free( psz_string );
435
436     /* OSD menu transcoding parameters */
437     p_sys->psz_osdenc = NULL;
438     p_sys->p_osd_cfg  = NULL;
439     p_sys->i_osdcodec = 0;
440     p_sys->b_osd   = var_GetBool( p_stream, SOUT_CFG_PREFIX "osd" );
441
442     if( p_sys->b_osd )
443     {
444         char *psz_next;
445
446         psz_next = config_ChainCreate( &p_sys->psz_osdenc,
447                                    &p_sys->p_osd_cfg, strdup( "dvbsub") );
448         free( psz_next );
449
450         p_sys->i_osdcodec = VLC_CODEC_YUVP;
451
452         msg_Dbg( p_stream, "codec osd=%4.4s", (char *)&p_sys->i_osdcodec );
453
454         if( !p_sys->p_spu )
455         {
456             p_sys->p_spu = spu_Create( p_stream );
457             if( p_sys->p_spu )
458                 spu_ChangeSources( p_sys->p_spu, "osdmenu" );
459         }
460         else
461         {
462             spu_ChangeSources( p_sys->p_spu, "osdmenu" );
463         }
464     }
465
466     /* Audio settings */
467     p_sys->b_master_sync = var_GetBool( p_stream, SOUT_CFG_PREFIX "audio-sync" );
468     if( p_sys->f_fps > 0 ) p_sys->b_master_sync = true;
469
470     p_stream->pf_add    = Add;
471     p_stream->pf_del    = Del;
472     p_stream->pf_send   = Send;
473     p_stream->p_sys     = p_sys;
474
475     return VLC_SUCCESS;
476 }
477
478 /*****************************************************************************
479  * Close:
480  *****************************************************************************/
481 static void Close( vlc_object_t * p_this )
482 {
483     sout_stream_t       *p_stream = (sout_stream_t*)p_this;
484     sout_stream_sys_t   *p_sys = p_stream->p_sys;
485
486     free( p_sys->psz_af );
487
488     config_ChainDestroy( p_sys->p_audio_cfg );
489     free( p_sys->psz_aenc );
490     free( p_sys->psz_alang );
491
492     free( p_sys->psz_vf2 );
493
494     config_ChainDestroy( p_sys->p_video_cfg );
495     free( p_sys->psz_venc );
496
497     config_ChainDestroy( p_sys->p_deinterlace_cfg );
498     free( p_sys->psz_deinterlace );
499
500     config_ChainDestroy( p_sys->p_spu_cfg );
501     free( p_sys->psz_senc );
502
503     if( p_sys->p_spu ) spu_Destroy( p_sys->p_spu );
504     if( p_sys->p_spu_blend ) filter_DeleteBlend( p_sys->p_spu_blend );
505
506     config_ChainDestroy( p_sys->p_osd_cfg );
507     free( p_sys->psz_osdenc );
508
509     free( p_sys );
510 }
511
512 static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
513 {
514     sout_stream_sys_t *p_sys = p_stream->p_sys;
515     sout_stream_id_t *id;
516
517     id = calloc( 1, sizeof( sout_stream_id_t ) );
518     if( !id )
519         goto error;
520
521     id->id = NULL;
522     id->p_decoder = NULL;
523     id->p_encoder = NULL;
524
525     /* Create decoder object */
526     id->p_decoder = vlc_object_create( p_stream, sizeof( decoder_t ) );
527     if( !id->p_decoder )
528         goto error;
529     id->p_decoder->p_module = NULL;
530     id->p_decoder->fmt_in = *p_fmt;
531     id->p_decoder->b_pace_control = true;
532
533     /* Create encoder object */
534     id->p_encoder = sout_EncoderCreate( p_stream );
535     if( !id->p_encoder )
536         goto error;
537     id->p_encoder->p_module = NULL;
538
539     /* Create destination format */
540     es_format_Init( &id->p_encoder->fmt_out, p_fmt->i_cat, 0 );
541     id->p_encoder->fmt_out.i_id    = p_fmt->i_id;
542     id->p_encoder->fmt_out.i_group = p_fmt->i_group;
543
544     if( p_sys->psz_alang )
545         id->p_encoder->fmt_out.psz_language = strdup( p_sys->psz_alang );
546     else if( p_fmt->psz_language )
547         id->p_encoder->fmt_out.psz_language = strdup( p_fmt->psz_language );
548
549     bool success;
550
551     if( p_fmt->i_cat == AUDIO_ES && (p_sys->i_acodec || p_sys->psz_aenc) )
552         success = transcode_audio_add(p_stream, p_fmt, id);
553     else if( p_fmt->i_cat == VIDEO_ES && (p_sys->i_vcodec || p_sys->psz_venc) )
554         success = transcode_video_add(p_stream, p_fmt, id);
555     else if( ( p_fmt->i_cat == SPU_ES ) &&
556              ( p_sys->i_scodec || p_sys->psz_senc || p_sys->b_soverlay ) )
557         success = transcode_spu_add(p_stream, p_fmt, id);
558     else if( !p_sys->b_osd && (p_sys->i_osdcodec != 0 || p_sys->psz_osdenc) )
559         success = transcode_osd_add(p_stream, p_fmt, id);
560     else
561     {
562         msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
563                  (char*)&p_fmt->i_codec );
564         id->id = sout_StreamIdAdd( p_stream->p_next, p_fmt );
565         id->b_transcode = false;
566
567         success = id->id;
568     }
569
570     if(!success)
571         goto error;
572
573     return id;
574
575 error:
576     if( id )
577     {
578         if( id->p_decoder )
579         {
580             vlc_object_release( id->p_decoder );
581             id->p_decoder = NULL;
582         }
583
584         if( id->p_encoder )
585         {
586             es_format_Clean( &id->p_encoder->fmt_out );
587             vlc_object_release( id->p_encoder );
588             id->p_encoder = NULL;
589         }
590
591         free( id );
592     }
593     return NULL;
594 }
595
596 static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
597 {
598     sout_stream_sys_t *p_sys = p_stream->p_sys;
599
600     if( id->b_transcode )
601     {
602         switch( id->p_decoder->fmt_in.i_cat )
603         {
604         case AUDIO_ES:
605             Send( p_stream, id, NULL );
606             transcode_audio_close( id );
607             break;
608         case VIDEO_ES:
609             Send( p_stream, id, NULL );
610             transcode_video_close( p_stream, id );
611             break;
612         case SPU_ES:
613             if( p_sys->b_osd )
614                 transcode_osd_close( p_stream, id );
615             else
616                 transcode_spu_close( p_stream, id );
617             break;
618         }
619     }
620
621     if( id->id ) sout_StreamIdDel( p_stream->p_next, id->id );
622
623     if( id->p_decoder )
624     {
625         vlc_object_release( id->p_decoder );
626         id->p_decoder = NULL;
627     }
628
629     if( id->p_encoder )
630     {
631         es_format_Clean( &id->p_encoder->fmt_out );
632         vlc_object_release( id->p_encoder );
633         id->p_encoder = NULL;
634     }
635     free( id );
636
637     return VLC_SUCCESS;
638 }
639
640 static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
641                  block_t *p_buffer )
642 {
643     sout_stream_sys_t *p_sys = p_stream->p_sys;
644     block_t *p_out = NULL;
645
646     if( !id->b_transcode )
647     {
648         if( id->id )
649             return sout_StreamIdSend( p_stream->p_next, id->id, p_buffer );
650
651         block_Release( p_buffer );
652         return VLC_EGENERIC;
653     }
654
655     switch( id->p_decoder->fmt_in.i_cat )
656     {
657     case AUDIO_ES:
658         transcode_audio_process( p_stream, id, p_buffer, &p_out );
659         break;
660
661     case VIDEO_ES:
662         if( transcode_video_process( p_stream, id, p_buffer, &p_out )
663             != VLC_SUCCESS )
664         {
665             return VLC_EGENERIC;
666         }
667         break;
668
669     case SPU_ES:
670         /* Transcode OSD menu pictures. */
671         if( p_sys->b_osd )
672         {
673             if( transcode_osd_process( p_stream, id, p_buffer, &p_out ) !=
674                 VLC_SUCCESS )
675             {
676                 return VLC_EGENERIC;
677             }
678         }
679         else if ( transcode_spu_process( p_stream, id, p_buffer, &p_out ) !=
680             VLC_SUCCESS )
681         {
682             return VLC_EGENERIC;
683         }
684         break;
685
686     default:
687         p_out = NULL;
688         block_Release( p_buffer );
689         break;
690     }
691
692     if( p_out )
693         return sout_StreamIdSend( p_stream->p_next, id->id, p_out );
694     return VLC_SUCCESS;
695 }