]> git.sesse.net Git - vlc/blob - modules/stream_out/transcode.c
use add_module_list
[vlc] / modules / stream_out / transcode.c
1 /*****************************************************************************
2  * transcode.c: transcoding stream output module
3  *****************************************************************************
4  * Copyright (C) 2003-2004 the VideoLAN team
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  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24  *****************************************************************************/
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include <vlc/vlc.h>
30 #include <vlc_input.h>
31 #include <vlc_sout.h>
32 #include <vlc_aout.h>
33 #include <vlc_vout.h>
34 #include <vlc_codec.h>
35 #include <vlc_block.h>
36 #include <vlc_filter.h>
37 #include <vlc_osd.h>
38
39 #include <math.h>
40
41 #define MASTER_SYNC_MAX_DRIFT 100000
42
43 /*****************************************************************************
44  * Module descriptor
45  *****************************************************************************/
46 #define VENC_TEXT N_("Video encoder")
47 #define VENC_LONGTEXT N_( \
48     "This is the video encoder module that will be used (and its associated "\
49     "options).")
50 #define VCODEC_TEXT N_("Destination video codec")
51 #define VCODEC_LONGTEXT N_( \
52     "This is the video codec that will be used.")
53 #define VB_TEXT N_("Video bitrate")
54 #define VB_LONGTEXT N_( \
55     "Target bitrate of the transcoded video stream." )
56 #define SCALE_TEXT N_("Video scaling")
57 #define SCALE_LONGTEXT N_( \
58     "Scale factor to apply to the video while transcoding (eg: 0.25)")
59 #define FPS_TEXT N_("Video frame-rate")
60 #define FPS_LONGTEXT N_( \
61     "Target output frame rate for the video stream." )
62 #define DEINTERLACE_TEXT N_("Deinterlace video")
63 #define DEINTERLACE_LONGTEXT N_( \
64     "Deinterlace the video before encoding." )
65 #define DEINTERLACE_MODULE_TEXT N_("Deinterlace module")
66 #define DEINTERLACE_MODULE_LONGTEXT N_( \
67     "Specify the deinterlace module to use." )
68 #define WIDTH_TEXT N_("Video width")
69 #define WIDTH_LONGTEXT N_( \
70     "Output video width." )
71 #define HEIGHT_TEXT N_("Video height")
72 #define HEIGHT_LONGTEXT N_( \
73     "Output video height." )
74 #define MAXWIDTH_TEXT N_("Maximum video width")
75 #define MAXWIDTH_LONGTEXT N_( \
76     "Maximum output video width." )
77 #define MAXHEIGHT_TEXT N_("Maximum video height")
78 #define MAXHEIGHT_LONGTEXT N_( \
79     "Maximum output video height." )
80 #define VFILTER_TEXT N_("Video filter")
81 #define VFILTER_LONGTEXT N_( \
82     "Video filters will be applied to the video streams (after overlays " \
83     "are applied). You must enter a comma-separated list of filters." )
84
85 #define CROPTOP_TEXT N_("Video crop (top)")
86 #define CROPTOP_LONGTEXT N_( \
87     "Number of pixels to crop at the top of the video." )
88 #define CROPLEFT_TEXT N_("Video crop (left)")
89 #define CROPLEFT_LONGTEXT N_( \
90     "Number of pixels to crop at the left of the video." )
91 #define CROPBOTTOM_TEXT N_("Video crop (bottom)")
92 #define CROPBOTTOM_LONGTEXT N_( \
93     "Number of pixels to crop at the bottom of the video." )
94 #define CROPRIGHT_TEXT N_("Video crop (right)")
95 #define CROPRIGHT_LONGTEXT N_( \
96     "Number of pixels to crop at the right of the video." )
97
98 #define PADDTOP_TEXT N_("Video padding (top)")
99 #define PADDTOP_LONGTEXT N_( \
100     "Size of the black border to add at the top of the video." )
101 #define PADDLEFT_TEXT N_("Video padding (left)")
102 #define PADDLEFT_LONGTEXT N_( \
103     "Size of the black border to add at the left of the video." )
104 #define PADDBOTTOM_TEXT N_("Video padding (bottom)")
105 #define PADDBOTTOM_LONGTEXT N_( \
106     "Size of the black border to add at the bottom of the video." )
107 #define PADDRIGHT_TEXT N_("Video padding (right)")
108 #define PADDRIGHT_LONGTEXT N_( \
109     "Size of the black border to add at the right of the video." )
110
111 #define CANVAS_WIDTH_TEXT N_("Video canvas width")
112 #define CANVAS_WIDTH_LONGTEXT N_( \
113     "This will automatically crod and pad the video to a specified width." )
114 #define CANVAS_HEIGHT_TEXT N_("Video canvas height")
115 #define CANVAS_HEIGHT_LONGTEXT N_( \
116     "This will automatically crod and pad the video to a specified height." )
117 #define CANVAS_ASPECT_TEXT N_("Video canvas aspect ratio")
118 #define CANVAS_ASPECT_LONGTEXT N_( \
119     "This sets aspect (like 4:3) of the video canvas and letterbox the video "\
120     "accordingly." )
121
122 #define AENC_TEXT N_("Audio encoder")
123 #define AENC_LONGTEXT N_( \
124     "This is the audio encoder module that will be used (and its associated "\
125     "options).")
126 #define ACODEC_TEXT N_("Destination audio codec")
127 #define ACODEC_LONGTEXT N_( \
128     "This is the audio codec that will be used.")
129 #define AB_TEXT N_("Audio bitrate")
130 #define AB_LONGTEXT N_( \
131     "Target bitrate of the transcoded audio stream." )
132 #define ARATE_TEXT N_("Audio sample rate")
133 #define ARATE_LONGTEXT N_( \
134  "Sample rate of the transcoded audio stream (11250, 22500, 44100 or 48000).")
135 #define ACHANS_TEXT N_("Audio channels")
136 #define ACHANS_LONGTEXT N_( \
137     "Number of audio channels in the transcoded streams." )
138 #define AFILTER_TEXT N_("Audio filter")
139 #define AFILTER_LONGTEXT N_( \
140     "Audio filters will be applied to the audio streams (after conversion " \
141     "filters are applied). You must enter a comma-separated list of filters." )
142
143 #define SENC_TEXT N_("Subtitles encoder")
144 #define SENC_LONGTEXT N_( \
145     "This is the subtitles encoder module that will be used (and its " \
146     "associated options)." )
147 #define SCODEC_TEXT N_("Destination subtitles codec")
148 #define SCODEC_LONGTEXT N_( \
149     "This is the subtitles codec that will be used." )
150
151 #define SFILTER_TEXT N_("Overlays")
152 #define SFILTER_LONGTEXT N_( \
153     "This allows you to add overlays (also known as \"subpictures\" on the "\
154     "transcoded video stream. The subpictures produced by the filters will "\
155     "be overlayed directly onto the video. You must specify a comma-separated "\
156     "list of subpicture modules" )
157
158 #define OSD_TEXT N_("OSD menu")
159 #define OSD_LONGTEXT N_(\
160     "Stream the On Screen Display menu (using the osdmenu subpicture module)." )
161
162 #define THREADS_TEXT N_("Number of threads")
163 #define THREADS_LONGTEXT N_( \
164     "Number of threads used for the transcoding." )
165 #define HP_TEXT N_("High priority")
166 #define HP_LONGTEXT N_( \
167     "Runs the optional encoder thread at the OUTPUT priority instead of " \
168     "VIDEO." )
169
170 #define ASYNC_TEXT N_("Synchronise on audio track")
171 #define ASYNC_LONGTEXT N_( \
172     "This option will drop/duplicate video frames to synchronise the video " \
173     "track on the audio track." )
174
175 #define HURRYUP_TEXT N_( "Hurry up" )
176 #define HURRYUP_LONGTEXT N_( "The transcoder will drop frames if your CPU " \
177                 "can't keep up with the encoding rate." )
178
179 static const char *ppsz_deinterlace_type[] =
180 {
181     "deinterlace", "ffmpeg-deinterlace"
182 };
183
184 static int  Open ( vlc_object_t * );
185 static void Close( vlc_object_t * );
186
187 #define SOUT_CFG_PREFIX "sout-transcode-"
188
189 vlc_module_begin();
190     set_shortname( _("Transcode"));
191     set_description( _("Transcode stream output") );
192     set_capability( "sout stream", 50 );
193     add_shortcut( "transcode" );
194     set_callbacks( Open, Close );
195     set_category( CAT_SOUT );
196     set_subcategory( SUBCAT_SOUT_STREAM );
197     set_section( N_("Video"), NULL );
198     add_string( SOUT_CFG_PREFIX "venc", NULL, NULL, VENC_TEXT,
199                 VENC_LONGTEXT, VLC_FALSE );
200     add_string( SOUT_CFG_PREFIX "vcodec", NULL, NULL, VCODEC_TEXT,
201                 VCODEC_LONGTEXT, VLC_FALSE );
202     add_integer( SOUT_CFG_PREFIX "vb", 800 * 1000, NULL, VB_TEXT,
203                  VB_LONGTEXT, VLC_FALSE );
204     add_float( SOUT_CFG_PREFIX "scale", 1, NULL, SCALE_TEXT,
205                SCALE_LONGTEXT, VLC_FALSE );
206     add_float( SOUT_CFG_PREFIX "fps", 0, NULL, FPS_TEXT,
207                FPS_LONGTEXT, VLC_FALSE );
208     add_bool( SOUT_CFG_PREFIX "hurry-up", VLC_TRUE, NULL, HURRYUP_TEXT,
209                HURRYUP_LONGTEXT, VLC_FALSE );
210     add_bool( SOUT_CFG_PREFIX "deinterlace", 0, NULL, DEINTERLACE_TEXT,
211               DEINTERLACE_LONGTEXT, VLC_FALSE );
212     add_string( SOUT_CFG_PREFIX "deinterlace-module", "deinterlace", NULL,
213                 DEINTERLACE_MODULE_TEXT, DEINTERLACE_MODULE_LONGTEXT,
214                 VLC_FALSE );
215         change_string_list( ppsz_deinterlace_type, 0, 0 );
216     add_integer( SOUT_CFG_PREFIX "width", 0, NULL, WIDTH_TEXT,
217                  WIDTH_LONGTEXT, VLC_TRUE );
218     add_integer( SOUT_CFG_PREFIX "height", 0, NULL, HEIGHT_TEXT,
219                  HEIGHT_LONGTEXT, VLC_TRUE );
220     add_integer( SOUT_CFG_PREFIX "maxwidth", 0, NULL, MAXWIDTH_TEXT,
221                  MAXWIDTH_LONGTEXT, VLC_TRUE );
222     add_integer( SOUT_CFG_PREFIX "maxheight", 0, NULL, MAXHEIGHT_TEXT,
223                  MAXHEIGHT_LONGTEXT, VLC_TRUE );
224     add_module_list( SOUT_CFG_PREFIX "vfilter", "video filter2",
225                      NULL, NULL,
226                      VFILTER_TEXT, VFILTER_LONGTEXT, VLC_FALSE );
227
228     add_integer( SOUT_CFG_PREFIX "croptop", 0, NULL, CROPTOP_TEXT,
229                  CROPTOP_LONGTEXT, VLC_TRUE );
230     add_integer( SOUT_CFG_PREFIX "cropleft", 0, NULL, CROPLEFT_TEXT,
231                  CROPLEFT_LONGTEXT, VLC_TRUE );
232     add_integer( SOUT_CFG_PREFIX "cropbottom", 0, NULL, CROPBOTTOM_TEXT,
233                  CROPBOTTOM_LONGTEXT, VLC_TRUE );
234     add_integer( SOUT_CFG_PREFIX "cropright", 0, NULL, CROPRIGHT_TEXT,
235                  CROPRIGHT_LONGTEXT, VLC_TRUE );
236
237     add_integer( SOUT_CFG_PREFIX "paddtop", 0, NULL, PADDTOP_TEXT,
238                  PADDTOP_LONGTEXT, VLC_TRUE );
239     add_integer( SOUT_CFG_PREFIX "paddleft", 0, NULL, PADDLEFT_TEXT,
240                  PADDLEFT_LONGTEXT, VLC_TRUE );
241     add_integer( SOUT_CFG_PREFIX "paddbottom", 0, NULL, PADDBOTTOM_TEXT,
242                  PADDBOTTOM_LONGTEXT, VLC_TRUE );
243     add_integer( SOUT_CFG_PREFIX "paddright", 0, NULL, PADDRIGHT_TEXT,
244                  PADDRIGHT_LONGTEXT, VLC_TRUE );
245
246     add_integer( SOUT_CFG_PREFIX "canvas-width", 0, NULL, CANVAS_WIDTH_TEXT,
247                  CANVAS_WIDTH_LONGTEXT, VLC_TRUE );
248     add_integer( SOUT_CFG_PREFIX "canvas-height", 0, NULL, CANVAS_HEIGHT_TEXT,
249                  CANVAS_HEIGHT_LONGTEXT, VLC_TRUE );
250     add_string( SOUT_CFG_PREFIX "canvas-aspect", NULL, NULL, CANVAS_ASPECT_TEXT,
251                 CANVAS_ASPECT_LONGTEXT, VLC_FALSE );
252
253     set_section( N_("Audio"), NULL );
254     add_string( SOUT_CFG_PREFIX "aenc", NULL, NULL, AENC_TEXT,
255                 AENC_LONGTEXT, VLC_FALSE );
256     add_string( SOUT_CFG_PREFIX "acodec", NULL, NULL, ACODEC_TEXT,
257                 ACODEC_LONGTEXT, VLC_FALSE );
258     add_integer( SOUT_CFG_PREFIX "ab", 0, NULL, AB_TEXT,
259                  AB_LONGTEXT, VLC_FALSE );
260     add_integer( SOUT_CFG_PREFIX "channels", 0, NULL, ACHANS_TEXT,
261                  ACHANS_LONGTEXT, VLC_FALSE );
262     add_integer( SOUT_CFG_PREFIX "samplerate", 0, NULL, ARATE_TEXT,
263                  ARATE_LONGTEXT, VLC_TRUE );
264     add_bool( SOUT_CFG_PREFIX "audio-sync", 0, NULL, ASYNC_TEXT,
265               ASYNC_LONGTEXT, VLC_FALSE );
266     add_module_list( SOUT_CFG_PREFIX "afilter",  "audio filter2",
267                      NULL, NULL,
268                      AFILTER_TEXT, AFILTER_LONGTEXT, VLC_FALSE );
269
270     set_section( N_("Overlays/Subtitles"), NULL );
271     add_string( SOUT_CFG_PREFIX "senc", NULL, NULL, SENC_TEXT,
272                 SENC_LONGTEXT, VLC_FALSE );
273     add_string( SOUT_CFG_PREFIX "scodec", NULL, NULL, SCODEC_TEXT,
274                 SCODEC_LONGTEXT, VLC_FALSE );
275     add_bool( SOUT_CFG_PREFIX "soverlay", 0, NULL, SCODEC_TEXT,
276                SCODEC_LONGTEXT, VLC_FALSE );
277     add_module_list( SOUT_CFG_PREFIX "sfilter", "video filter",
278                      NULL, NULL,
279                      SFILTER_TEXT, SFILTER_LONGTEXT, VLC_FALSE );
280
281     set_section( N_("On Screen Display"), NULL );
282     add_bool( SOUT_CFG_PREFIX "osd", 0, NULL, OSD_TEXT,
283               OSD_LONGTEXT, VLC_FALSE );
284
285     set_section( N_("Miscellaneous"), NULL );
286     add_integer( SOUT_CFG_PREFIX "threads", 0, NULL, THREADS_TEXT,
287                  THREADS_LONGTEXT, VLC_TRUE );
288     add_bool( SOUT_CFG_PREFIX "high-priority", 0, NULL, HP_TEXT, HP_LONGTEXT,
289               VLC_TRUE );
290
291 vlc_module_end();
292
293 static const char *ppsz_sout_options[] = {
294     "venc", "vcodec", "vb", "croptop", "cropbottom", "cropleft", "cropright",
295     "paddtop", "paddbottom", "paddleft", "paddright",
296     "canvas-width", "canvas-height", "canvas-aspect",
297     "scale", "fps", "width", "height", "vfilter", "deinterlace",
298     "deinterlace-module", "threads", "hurry-up", "aenc", "acodec", "ab",
299     "afilter", "samplerate", "channels", "senc", "scodec", "soverlay",
300     "sfilter", "osd", "audio-sync", "high-priority", "maxwidth", "maxheight",
301     NULL
302 };
303
304 /*****************************************************************************
305  * Exported prototypes
306  *****************************************************************************/
307 static sout_stream_id_t *Add ( sout_stream_t *, es_format_t * );
308 static int               Del ( sout_stream_t *, sout_stream_id_t * );
309 static int               Send( sout_stream_t *, sout_stream_id_t *, block_t* );
310
311 static int  transcode_audio_new    ( sout_stream_t *, sout_stream_id_t * );
312 static void transcode_audio_close  ( sout_stream_t *, sout_stream_id_t * );
313 static int  transcode_audio_process( sout_stream_t *, sout_stream_id_t *,
314                                      block_t *, block_t ** );
315
316 static aout_buffer_t *audio_new_buffer( decoder_t *, int );
317 static void audio_del_buffer( decoder_t *, aout_buffer_t * );
318
319 static int  transcode_video_new    ( sout_stream_t *, sout_stream_id_t * );
320 static void transcode_video_close  ( sout_stream_t *, sout_stream_id_t * );
321 static int  transcode_video_encoder_open( sout_stream_t *, sout_stream_id_t *);
322 static int  transcode_video_process( sout_stream_t *, sout_stream_id_t *,
323                                      block_t *, block_t ** );
324
325 static void video_del_buffer( vlc_object_t *, picture_t * );
326 static picture_t *video_new_buffer_decoder( decoder_t * );
327 static void video_del_buffer_decoder( decoder_t *, picture_t * );
328 static void video_link_picture_decoder( decoder_t *, picture_t * );
329 static void video_unlink_picture_decoder( decoder_t *, picture_t * );
330 static picture_t *video_new_buffer_filter( filter_t * );
331 static void video_del_buffer_filter( filter_t *, picture_t * );
332
333 static int  transcode_spu_new    ( sout_stream_t *, sout_stream_id_t * );
334 static void transcode_spu_close  ( sout_stream_t *, sout_stream_id_t * );
335 static int  transcode_spu_process( sout_stream_t *, sout_stream_id_t *,
336                                    block_t *, block_t ** );
337
338 static int  transcode_osd_new    ( sout_stream_t *, sout_stream_id_t * );
339 static void transcode_osd_close  ( sout_stream_t *, sout_stream_id_t * );
340 static int  transcode_osd_process( sout_stream_t *, sout_stream_id_t *,
341                                    block_t *, block_t ** );
342
343 static int  EncoderThread( struct sout_stream_sys_t * p_sys );
344
345 static int pi_channels_maps[6] =
346 {
347     0,
348     AOUT_CHAN_CENTER,   AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
349     AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
350     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
351      | AOUT_CHAN_REARRIGHT,
352     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
353      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
354 };
355
356 #define PICTURE_RING_SIZE 64
357 #define SUBPICTURE_RING_SIZE 20
358 #define TRANSCODE_FILTERS 10
359
360 struct sout_stream_sys_t
361 {
362     VLC_COMMON_MEMBERS
363
364     sout_stream_t   *p_out;
365     sout_stream_id_t *id_video;
366     block_t         *p_buffers;
367     vlc_mutex_t     lock_out;
368     vlc_cond_t      cond;
369     picture_t *     pp_pics[PICTURE_RING_SIZE];
370     int             i_first_pic, i_last_pic;
371
372     /* Audio */
373     vlc_fourcc_t    i_acodec;   /* codec audio (0 if not transcode) */
374     char            *psz_aenc;
375     config_chain_t  *p_audio_cfg;
376     int             i_sample_rate;
377     int             i_channels;
378     int             i_abitrate;
379     char            *psz_afilters[TRANSCODE_FILTERS];
380     config_chain_t  *p_afilters_cfg[TRANSCODE_FILTERS];
381     int             i_afilters;
382
383     /* Video */
384     vlc_fourcc_t    i_vcodec;   /* codec video (0 if not transcode) */
385     char            *psz_venc;
386     config_chain_t  *p_video_cfg;
387     int             i_vbitrate;
388     double          f_scale;
389     double          f_fps;
390     unsigned int    i_width, i_maxwidth;
391     unsigned int    i_height, i_maxheight;
392     vlc_bool_t      b_deinterlace;
393     char            *psz_deinterlace;
394     config_chain_t  *p_deinterlace_cfg;
395     int             i_threads;
396     vlc_bool_t      b_high_priority;
397     vlc_bool_t      b_hurry_up;
398     char            *psz_vfilters[TRANSCODE_FILTERS];
399     config_chain_t  *p_vfilters_cfg[TRANSCODE_FILTERS];
400     int             i_vfilters;
401
402     int             i_crop_top;
403     int             i_crop_bottom;
404     int             i_crop_right;
405     int             i_crop_left;
406
407     int             i_padd_top;
408     int             i_padd_bottom;
409     int             i_padd_right;
410     int             i_padd_left;
411
412     int             i_canvas_width;
413     int             i_canvas_height;
414     int             i_canvas_aspect;
415
416     /* Video, calculated */
417     int             i_src_x_offset;
418     int             i_src_y_offset;
419     int             i_crop_width;
420     int             i_crop_height;
421
422     int             i_dst_x_offset;
423     int             i_dst_y_offset;
424     int             i_nopadd_width;
425     int             i_nopadd_height;
426
427     /* SPU */
428     vlc_fourcc_t    i_scodec;   /* codec spu (0 if not transcode) */
429     char            *psz_senc;
430     vlc_bool_t      b_soverlay;
431     config_chain_t  *p_spu_cfg;
432     spu_t           *p_spu;
433
434     /* OSD Menu */
435     vlc_fourcc_t    i_osdcodec; /* codec osd menu (0 if not transcode) */
436     char            *psz_osdenc;
437     config_chain_t  *p_osd_cfg;
438     vlc_bool_t      b_osd;   /* VLC_TRUE when osd es is registered */
439
440     /* Sync */
441     vlc_bool_t      b_master_sync;
442     mtime_t         i_master_drift;
443 };
444
445 struct decoder_owner_sys_t
446 {
447     picture_t *pp_pics[PICTURE_RING_SIZE];
448     sout_stream_sys_t *p_sys;
449 };
450 struct filter_owner_sys_t
451 {
452     picture_t *pp_pics[PICTURE_RING_SIZE];
453     sout_stream_sys_t *p_sys;
454 };
455
456 /*****************************************************************************
457  * Open:
458  *****************************************************************************/
459 static int Open( vlc_object_t *p_this )
460 {
461     sout_stream_t     *p_stream = (sout_stream_t*)p_this;
462     sout_stream_sys_t *p_sys;
463     vlc_value_t       val;
464
465     p_sys = vlc_object_create( p_this, sizeof( sout_stream_sys_t ) );
466
467     p_sys->p_out = sout_StreamNew( p_stream->p_sout, p_stream->psz_next );
468     if( !p_sys->p_out )
469     {
470         msg_Err( p_stream, "cannot create chain" );
471         vlc_object_destroy( p_sys );
472         return VLC_EGENERIC;
473     }
474
475     p_sys->i_master_drift = 0;
476
477     config_ChainParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
478                    p_stream->p_cfg );
479
480     /* Audio transcoding parameters */
481     var_Get( p_stream, SOUT_CFG_PREFIX "aenc", &val );
482     p_sys->psz_aenc = NULL;
483     p_sys->p_audio_cfg = NULL;
484     if( val.psz_string && *val.psz_string )
485     {
486         char *psz_next;
487         psz_next = config_ChainCreate( &p_sys->psz_aenc, &p_sys->p_audio_cfg,
488                                        val.psz_string );
489         if( psz_next ) free( psz_next );
490     }
491     if( val.psz_string ) free( val.psz_string );
492
493     var_Get( p_stream, SOUT_CFG_PREFIX "acodec", &val );
494     p_sys->i_acodec = 0;
495     if( val.psz_string && *val.psz_string )
496     {
497         char fcc[4] = "    ";
498         memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
499         p_sys->i_acodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
500     }
501     if( val.psz_string ) free( val.psz_string );
502
503     var_Get( p_stream, SOUT_CFG_PREFIX "ab", &val );
504     p_sys->i_abitrate = val.i_int;
505     if( p_sys->i_abitrate < 4000 ) p_sys->i_abitrate *= 1000;
506
507     var_Get( p_stream, SOUT_CFG_PREFIX "samplerate", &val );
508     p_sys->i_sample_rate = val.i_int;
509
510     var_Get( p_stream, SOUT_CFG_PREFIX "channels", &val );
511     p_sys->i_channels = val.i_int;
512
513     if( p_sys->i_acodec )
514     {
515         if( p_sys->i_acodec == VLC_FOURCC('m','p','3',0) &&
516             p_sys->i_channels > 2 )
517         {
518             msg_Warn( p_stream, "%d channels invalid for mp3, forcing to 2",
519                       p_sys->i_channels );
520             p_sys->i_channels = 2;
521         }
522         msg_Dbg( p_stream, "codec audio=%4.4s %dHz %d channels %dKb/s",
523                  (char *)&p_sys->i_acodec, p_sys->i_sample_rate,
524                  p_sys->i_channels, p_sys->i_abitrate / 1000 );
525     }
526
527     var_Get( p_stream, SOUT_CFG_PREFIX "afilter", &val );
528     p_sys->i_afilters = 0;
529     if( val.psz_string && *val.psz_string )
530     {
531         char *psz_parser = val.psz_string;
532
533         while( (psz_parser != NULL) && (*psz_parser != '\0')
534                 && (p_sys->i_afilters < TRANSCODE_FILTERS) )
535         {
536             psz_parser = config_ChainCreate(
537                                    &p_sys->psz_afilters[p_sys->i_afilters],
538                                    &p_sys->p_afilters_cfg[p_sys->i_afilters],
539                                    psz_parser );
540             p_sys->i_afilters++;
541             if( (psz_parser != NULL) && (*psz_parser != '\0') ) psz_parser++;
542         }
543     }
544     if( val.psz_string ) free( val.psz_string );
545     if( p_sys->i_afilters < TRANSCODE_FILTERS-1 )
546     {
547         p_sys->psz_afilters[p_sys->i_afilters] = NULL;
548         p_sys->p_afilters_cfg[p_sys->i_afilters] = NULL;
549     }
550
551     /* Video transcoding parameters */
552     var_Get( p_stream, SOUT_CFG_PREFIX "venc", &val );
553     p_sys->psz_venc = NULL;
554     p_sys->p_video_cfg = NULL;
555     if( val.psz_string && *val.psz_string )
556     {
557         char *psz_next;
558         psz_next = config_ChainCreate( &p_sys->psz_venc, &p_sys->p_video_cfg,
559                                    val.psz_string );
560         if( psz_next ) free( psz_next );
561     }
562     if( val.psz_string ) free( val.psz_string );
563
564     var_Get( p_stream, SOUT_CFG_PREFIX "vcodec", &val );
565     p_sys->i_vcodec = 0;
566     if( val.psz_string && *val.psz_string )
567     {
568         char fcc[4] = "    ";
569         memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
570         p_sys->i_vcodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
571     }
572     if( val.psz_string ) free( val.psz_string );
573
574     var_Get( p_stream, SOUT_CFG_PREFIX "vb", &val );
575     p_sys->i_vbitrate = val.i_int;
576     if( p_sys->i_vbitrate < 16000 ) p_sys->i_vbitrate *= 1000;
577
578     var_Get( p_stream, SOUT_CFG_PREFIX "scale", &val );
579     p_sys->f_scale = val.f_float;
580
581     var_Get( p_stream, SOUT_CFG_PREFIX "fps", &val );
582     p_sys->f_fps = val.f_float;
583
584     var_Get( p_stream, SOUT_CFG_PREFIX "hurry-up", &val );
585     p_sys->b_hurry_up = val.b_bool;
586
587     var_Get( p_stream, SOUT_CFG_PREFIX "width", &val );
588     p_sys->i_width = val.i_int;
589
590     var_Get( p_stream, SOUT_CFG_PREFIX "height", &val );
591     p_sys->i_height = val.i_int;
592
593     var_Get( p_stream, SOUT_CFG_PREFIX "maxwidth", &val );
594     p_sys->i_maxwidth = val.i_int;
595
596     var_Get( p_stream, SOUT_CFG_PREFIX "maxheight", &val );
597     p_sys->i_maxheight = val.i_int;
598
599     var_Get( p_stream, SOUT_CFG_PREFIX "vfilter", &val );
600     p_sys->i_vfilters = 0;
601     if( val.psz_string && *val.psz_string )
602     {
603         char *psz_parser = val.psz_string;
604
605         while( (psz_parser != NULL) && (*psz_parser != '\0')
606                 && (p_sys->i_vfilters < TRANSCODE_FILTERS) )
607         {
608             psz_parser = config_ChainCreate(
609                                    &p_sys->psz_vfilters[p_sys->i_vfilters],
610                                    &p_sys->p_vfilters_cfg[p_sys->i_vfilters],
611                                    psz_parser );
612             p_sys->i_vfilters++;
613             if( psz_parser != NULL && *psz_parser != '\0' ) psz_parser++;
614         }
615     }
616     if( val.psz_string ) free( val.psz_string );
617     if( p_sys->i_vfilters < TRANSCODE_FILTERS-1 )
618     {
619         p_sys->psz_vfilters[p_sys->i_vfilters] = NULL;
620         p_sys->p_vfilters_cfg[p_sys->i_vfilters] = NULL;
621     }
622
623     var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace", &val );
624     p_sys->b_deinterlace = val.b_bool;
625
626     var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace-module", &val );
627     p_sys->psz_deinterlace = NULL;
628     p_sys->p_deinterlace_cfg = NULL;
629     if( val.psz_string && *val.psz_string )
630     {
631         char *psz_next;
632         psz_next = config_ChainCreate( &p_sys->psz_deinterlace,
633                                    &p_sys->p_deinterlace_cfg,
634                                    val.psz_string );
635         if( psz_next ) free( psz_next );
636     }
637     if( val.psz_string ) free( val.psz_string );
638
639     var_Get( p_stream, SOUT_CFG_PREFIX "croptop", &val );
640     p_sys->i_crop_top = val.i_int;
641     var_Get( p_stream, SOUT_CFG_PREFIX "cropbottom", &val );
642     p_sys->i_crop_bottom = val.i_int;
643     var_Get( p_stream, SOUT_CFG_PREFIX "cropleft", &val );
644     p_sys->i_crop_left = val.i_int;
645     var_Get( p_stream, SOUT_CFG_PREFIX "cropright", &val );
646     p_sys->i_crop_right = val.i_int;
647
648     var_Get( p_stream, SOUT_CFG_PREFIX "paddtop", &val );
649     p_sys->i_padd_top = val.i_int;
650     var_Get( p_stream, SOUT_CFG_PREFIX "paddbottom", &val );
651     p_sys->i_padd_bottom = val.i_int;
652     var_Get( p_stream, SOUT_CFG_PREFIX "paddleft", &val );
653     p_sys->i_padd_left = val.i_int;
654     var_Get( p_stream, SOUT_CFG_PREFIX "paddright", &val );
655     p_sys->i_padd_right = val.i_int;
656
657     var_Get( p_stream, SOUT_CFG_PREFIX "canvas-width", &val );
658     p_sys->i_canvas_width = val.i_int;
659     var_Get( p_stream, SOUT_CFG_PREFIX "canvas-height", &val );
660     p_sys->i_canvas_height = val.i_int;
661
662     var_Get( p_stream, SOUT_CFG_PREFIX "canvas-aspect", &val );
663     p_sys->i_canvas_aspect = 0;
664     if( val.psz_string && *val.psz_string )
665     {
666         char *psz_parser = strchr( val.psz_string, ':' );
667         if( psz_parser )
668         {
669             *psz_parser++ = '\0';
670             p_sys->i_canvas_aspect = atoi( val.psz_string ) *
671                 VOUT_ASPECT_FACTOR / atoi( psz_parser );
672         }
673         else msg_Warn( p_stream, "bad aspect ratio %s", val.psz_string );
674
675     }
676     if( val.psz_string ) free( val.psz_string );
677
678     var_Get( p_stream, SOUT_CFG_PREFIX "threads", &val );
679     p_sys->i_threads = val.i_int;
680     var_Get( p_stream, SOUT_CFG_PREFIX "high-priority", &val );
681     p_sys->b_high_priority = val.b_bool;
682
683     if( p_sys->i_vcodec )
684     {
685         msg_Dbg( p_stream, "codec video=%4.4s %dx%d scaling: %f %dkb/s",
686                  (char *)&p_sys->i_vcodec, p_sys->i_width, p_sys->i_height,
687                  p_sys->f_scale, p_sys->i_vbitrate / 1000 );
688     }
689
690     /* Subpictures transcoding parameters */
691     p_sys->p_spu = NULL;
692     p_sys->psz_senc = NULL;
693     p_sys->p_spu_cfg = NULL;
694     p_sys->i_scodec = 0;
695
696     var_Get( p_stream, SOUT_CFG_PREFIX "senc", &val );
697     if( val.psz_string && *val.psz_string )
698     {
699         char *psz_next;
700         psz_next = config_ChainCreate( &p_sys->psz_senc, &p_sys->p_spu_cfg,
701                                    val.psz_string );
702         if( psz_next ) free( psz_next );
703     }
704     if( val.psz_string ) free( val.psz_string );
705
706     var_Get( p_stream, SOUT_CFG_PREFIX "scodec", &val );
707     if( val.psz_string && *val.psz_string )
708     {
709         char fcc[4] = "    ";
710         memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
711         p_sys->i_scodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
712     }
713     if( val.psz_string ) free( val.psz_string );
714
715     if( p_sys->i_scodec )
716     {
717         msg_Dbg( p_stream, "codec spu=%4.4s", (char *)&p_sys->i_scodec );
718     }
719
720     var_Get( p_stream, SOUT_CFG_PREFIX "soverlay", &val );
721     p_sys->b_soverlay = val.b_bool;
722
723     var_Get( p_stream, SOUT_CFG_PREFIX "sfilter", &val );
724     if( val.psz_string && *val.psz_string )
725     {
726         p_sys->p_spu = spu_Create( p_stream );
727         var_Create( p_sys->p_spu, "sub-filter", VLC_VAR_STRING );
728         var_Set( p_sys->p_spu, "sub-filter", val );
729         spu_Init( p_sys->p_spu );
730     }
731     if( val.psz_string ) free( val.psz_string );
732
733     /* OSD menu transcoding parameters */
734     p_sys->psz_osdenc = NULL;
735     p_sys->p_osd_cfg  = NULL;
736     p_sys->i_osdcodec = 0;
737     p_sys->b_osd   = VLC_FALSE;
738
739     var_Get( p_stream, SOUT_CFG_PREFIX "osd", &val );
740     if( val.b_bool )
741     {
742         vlc_value_t osd_val;
743         char *psz_next;
744
745         psz_next = config_ChainCreate( &p_sys->psz_osdenc,
746                                    &p_sys->p_osd_cfg, strdup( "dvbsub") );
747         if( psz_next ) free( psz_next );
748
749         p_sys->i_osdcodec = VLC_FOURCC('Y','U','V','P' );
750
751         msg_Dbg( p_stream, "codec osd=%4.4s", (char *)&p_sys->i_osdcodec );
752
753         if( !p_sys->p_spu )
754         {
755             osd_val.psz_string = strdup("osdmenu");
756             p_sys->p_spu = spu_Create( p_stream );
757             var_Create( p_sys->p_spu, "sub-filter", VLC_VAR_STRING );
758             var_Set( p_sys->p_spu, "sub-filter", osd_val );
759             spu_Init( p_sys->p_spu );
760             if( osd_val.psz_string ) free( osd_val.psz_string );
761         }
762         else
763         {
764             osd_val.psz_string = strdup("osdmenu");
765             var_Set( p_sys->p_spu, "sub-filter", osd_val );
766             if( osd_val.psz_string ) free( osd_val.psz_string );
767         }
768     }
769
770     /* Audio settings */
771     var_Get( p_stream, SOUT_CFG_PREFIX "audio-sync", &val );
772     p_sys->b_master_sync = val.b_bool;
773     if( p_sys->f_fps > 0 ) p_sys->b_master_sync = VLC_TRUE;
774
775     p_stream->pf_add    = Add;
776     p_stream->pf_del    = Del;
777     p_stream->pf_send   = Send;
778     p_stream->p_sys     = p_sys;
779
780     return VLC_SUCCESS;
781 }
782
783 /*****************************************************************************
784  * Close:
785  *****************************************************************************/
786 static void Close( vlc_object_t * p_this )
787 {
788     sout_stream_t       *p_stream = (sout_stream_t*)p_this;
789     sout_stream_sys_t   *p_sys = p_stream->p_sys;
790
791     sout_StreamDelete( p_sys->p_out );
792
793     while( p_sys->i_afilters )
794     {
795         p_sys->i_afilters--;
796         if( p_sys->psz_afilters[p_sys->i_afilters] )
797             free( p_sys->psz_afilters[p_sys->i_afilters] );
798         if( p_sys->p_afilters_cfg[p_sys->i_afilters] )
799             free( p_sys->p_afilters_cfg[p_sys->i_afilters] );
800     }
801
802     while( p_sys->p_audio_cfg != NULL )
803     {
804         config_chain_t *p_next = p_sys->p_audio_cfg->p_next;
805
806         if( p_sys->p_audio_cfg->psz_name )
807             free( p_sys->p_audio_cfg->psz_name );
808         if( p_sys->p_audio_cfg->psz_value )
809             free( p_sys->p_audio_cfg->psz_value );
810         free( p_sys->p_audio_cfg );
811
812         p_sys->p_audio_cfg = p_next;
813     }
814     if( p_sys->psz_aenc ) free( p_sys->psz_aenc );
815
816     while( p_sys->i_vfilters )
817     {
818         p_sys->i_vfilters--;
819         if( p_sys->psz_vfilters[p_sys->i_vfilters] )
820             free( p_sys->psz_vfilters[p_sys->i_vfilters] );
821         if( p_sys->p_vfilters_cfg[p_sys->i_vfilters] )
822             free( p_sys->p_vfilters_cfg[p_sys->i_vfilters] );
823     }
824
825     while( p_sys->p_video_cfg != NULL )
826     {
827         config_chain_t *p_next = p_sys->p_video_cfg->p_next;
828
829         if( p_sys->p_video_cfg->psz_name )
830             free( p_sys->p_video_cfg->psz_name );
831         if( p_sys->p_video_cfg->psz_value )
832             free( p_sys->p_video_cfg->psz_value );
833         free( p_sys->p_video_cfg );
834
835         p_sys->p_video_cfg = p_next;
836     }
837     if( p_sys->psz_venc ) free( p_sys->psz_venc );
838
839     while( p_sys->p_deinterlace_cfg != NULL )
840     {
841         config_chain_t *p_next = p_sys->p_deinterlace_cfg->p_next;
842
843         if( p_sys->p_deinterlace_cfg->psz_name )
844             free( p_sys->p_deinterlace_cfg->psz_name );
845         if( p_sys->p_deinterlace_cfg->psz_value )
846             free( p_sys->p_deinterlace_cfg->psz_value );
847         free( p_sys->p_deinterlace_cfg );
848
849         p_sys->p_deinterlace_cfg = p_next;
850     }
851     if( p_sys->psz_deinterlace ) free( p_sys->psz_deinterlace );
852
853     while( p_sys->p_spu_cfg != NULL )
854     {
855         config_chain_t *p_next = p_sys->p_spu_cfg->p_next;
856
857         if( p_sys->p_spu_cfg->psz_name )
858             free( p_sys->p_spu_cfg->psz_name );
859         if( p_sys->p_spu_cfg->psz_value )
860             free( p_sys->p_spu_cfg->psz_value );
861         free( p_sys->p_spu_cfg );
862
863         p_sys->p_spu_cfg = p_next;
864     }
865     if( p_sys->psz_senc ) free( p_sys->psz_senc );
866
867     if( p_sys->p_spu ) spu_Destroy( p_sys->p_spu );
868
869     while( p_sys->p_osd_cfg != NULL )
870     {
871         config_chain_t *p_next = p_sys->p_osd_cfg->p_next;
872
873         if( p_sys->p_osd_cfg->psz_name )
874             free( p_sys->p_osd_cfg->psz_name );
875         if( p_sys->p_osd_cfg->psz_value )
876             free( p_sys->p_osd_cfg->psz_value );
877         free( p_sys->p_osd_cfg );
878
879         p_sys->p_osd_cfg = p_next;
880     }
881     if( p_sys->psz_osdenc ) free( p_sys->psz_osdenc );
882
883     vlc_object_destroy( p_sys );
884 }
885
886 struct sout_stream_id_t
887 {
888     vlc_fourcc_t  b_transcode;
889
890     /* id of the out stream */
891     void *id;
892
893     /* Decoder */
894     decoder_t       *p_decoder;
895
896     /* Filters */
897     filter_t        *pp_filter[TRANSCODE_FILTERS];
898     int             i_filter;
899     /* User specified filters */
900     filter_t        *pp_ufilter[TRANSCODE_FILTERS];
901     int             i_ufilter;
902
903     /* Encoder */
904     encoder_t       *p_encoder;
905
906     /* Sync */
907     date_t          interpolated_pts;
908 };
909
910 static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
911 {
912     sout_stream_sys_t *p_sys = p_stream->p_sys;
913     sout_stream_id_t *id;
914
915     id = malloc( sizeof( sout_stream_id_t ) );
916     if( !id )
917     {
918         msg_Err( p_stream, "out of memory" );
919         goto error;
920     }
921     memset( id, 0, sizeof(sout_stream_id_t) );
922
923     id->id = NULL;
924     id->p_decoder = NULL;
925     id->p_encoder = NULL;
926
927     /* Create decoder object */
928     id->p_decoder = vlc_object_create( p_stream, VLC_OBJECT_DECODER );
929     if( !id->p_decoder )
930     {
931         msg_Err( p_stream, "out of memory" );
932         goto error;
933     }
934     vlc_object_attach( id->p_decoder, p_stream );
935     id->p_decoder->p_module = NULL;
936     id->p_decoder->fmt_in = *p_fmt;
937     id->p_decoder->b_pace_control = VLC_TRUE;
938
939     /* Create encoder object */
940     id->p_encoder = vlc_object_create( p_stream, VLC_OBJECT_ENCODER );
941     if( !id->p_encoder )
942     {
943         msg_Err( p_stream, "out of memory" );
944         goto error;
945     }
946     vlc_object_attach( id->p_encoder, p_stream );
947     id->p_encoder->p_module = NULL;
948
949     /* Create destination format */
950     es_format_Init( &id->p_encoder->fmt_out, p_fmt->i_cat, 0 );
951     id->p_encoder->fmt_out.i_id    = p_fmt->i_id;
952     id->p_encoder->fmt_out.i_group = p_fmt->i_group;
953     if( p_fmt->psz_language )
954         id->p_encoder->fmt_out.psz_language = strdup( p_fmt->psz_language );
955
956     if( p_fmt->i_cat == AUDIO_ES && (p_sys->i_acodec || p_sys->psz_aenc) )
957     {
958         msg_Dbg( p_stream,
959                  "creating audio transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
960                  (char*)&p_fmt->i_codec, (char*)&p_sys->i_acodec );
961
962         /* Complete destination format */
963         id->p_encoder->fmt_out.i_codec = p_sys->i_acodec;
964         id->p_encoder->fmt_out.audio.i_rate = p_sys->i_sample_rate > 0 ?
965             p_sys->i_sample_rate : (int)p_fmt->audio.i_rate;
966         id->p_encoder->fmt_out.i_bitrate = p_sys->i_abitrate;
967         id->p_encoder->fmt_out.audio.i_bitspersample =
968             p_fmt->audio.i_bitspersample;
969         id->p_encoder->fmt_out.audio.i_channels = p_sys->i_channels > 0 ?
970             p_sys->i_channels : p_fmt->audio.i_channels;
971         /* Sanity check for audio channels */
972         id->p_encoder->fmt_out.audio.i_channels =
973             __MIN( id->p_encoder->fmt_out.audio.i_channels,
974                    id->p_decoder->fmt_in.audio.i_channels );
975         id->p_encoder->fmt_out.audio.i_original_channels =
976             id->p_decoder->fmt_in.audio.i_physical_channels;
977         if( id->p_decoder->fmt_in.audio.i_channels ==
978             id->p_encoder->fmt_out.audio.i_channels )
979         {
980             id->p_encoder->fmt_out.audio.i_physical_channels =
981                 id->p_decoder->fmt_in.audio.i_physical_channels;
982         }
983         else
984         {
985             id->p_encoder->fmt_out.audio.i_physical_channels =
986                 pi_channels_maps[id->p_encoder->fmt_out.audio.i_channels];
987         }
988
989         /* Build decoder -> filter -> encoder chain */
990         if( transcode_audio_new( p_stream, id ) )
991         {
992             msg_Err( p_stream, "cannot create audio chain" );
993             goto error;
994         }
995
996         /* Open output stream */
997         id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
998         id->b_transcode = VLC_TRUE;
999
1000         if( !id->id )
1001         {
1002             transcode_audio_close( p_stream, id );
1003             goto error;
1004         }
1005
1006         date_Init( &id->interpolated_pts, p_fmt->audio.i_rate, 1 );
1007     }
1008     else if( p_fmt->i_cat == VIDEO_ES &&
1009              (p_sys->i_vcodec != 0 || p_sys->psz_venc) )
1010     {
1011         msg_Dbg( p_stream,
1012                  "creating video transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
1013                  (char*)&p_fmt->i_codec, (char*)&p_sys->i_vcodec );
1014
1015         /* Complete destination format */
1016         id->p_encoder->fmt_out.i_codec = p_sys->i_vcodec;
1017         id->p_encoder->fmt_out.video.i_width  = p_sys->i_width & ~1;
1018         id->p_encoder->fmt_out.video.i_height = p_sys->i_height & ~1;
1019         id->p_encoder->fmt_out.i_bitrate = p_sys->i_vbitrate;
1020
1021         /* Build decoder -> filter -> encoder chain */
1022         if( transcode_video_new( p_stream, id ) )
1023         {
1024             msg_Err( p_stream, "cannot create video chain" );
1025             goto error;
1026         }
1027
1028         /* Stream will be added later on because we don't know
1029          * all the characteristics of the decoded stream yet */
1030         id->b_transcode = VLC_TRUE;
1031
1032         if( p_sys->f_fps > 0 )
1033         {
1034             id->p_encoder->fmt_out.video.i_frame_rate =
1035                 (p_sys->f_fps * 1001) + 0.5;
1036             id->p_encoder->fmt_out.video.i_frame_rate_base = 1001;
1037         }
1038     }
1039     else if( ( p_fmt->i_cat == SPU_ES ) &&
1040              ( p_sys->i_scodec || p_sys->psz_senc ) )
1041     {
1042         msg_Dbg( p_stream, "creating subtitles transcoding from fcc=`%4.4s' "
1043                  "to fcc=`%4.4s'", (char*)&p_fmt->i_codec,
1044                  (char*)&p_sys->i_scodec );
1045
1046         /* Complete destination format */
1047         id->p_encoder->fmt_out.i_codec = p_sys->i_scodec;
1048
1049         /* build decoder -> filter -> encoder */
1050         if( transcode_spu_new( p_stream, id ) )
1051         {
1052             msg_Err( p_stream, "cannot create subtitles chain" );
1053             goto error;
1054         }
1055
1056         /* open output stream */
1057         id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
1058         id->b_transcode = VLC_TRUE;
1059
1060         if( !id->id )
1061         {
1062             transcode_spu_close( p_stream, id );
1063             goto error;
1064         }
1065     }
1066     else if( p_fmt->i_cat == SPU_ES && p_sys->b_soverlay )
1067     {
1068         msg_Dbg( p_stream, "subtitles (fcc=`%4.4s') overlaying",
1069                  (char*)&p_fmt->i_codec );
1070
1071         id->b_transcode = VLC_TRUE;
1072
1073         /* Build decoder -> filter -> overlaying chain */
1074         if( transcode_spu_new( p_stream, id ) )
1075         {
1076             msg_Err( p_stream, "cannot create subtitles chain" );
1077             goto error;
1078         }
1079     }
1080     else if( !p_sys->b_osd && (p_sys->i_osdcodec != 0 || p_sys->psz_osdenc) )
1081     {
1082         msg_Dbg( p_stream, "creating osd transcoding from fcc=`%4.4s' "
1083                  "to fcc=`%4.4s'", (char*)&p_fmt->i_codec,
1084                  (char*)&p_sys->i_scodec );
1085
1086         id->b_transcode = VLC_TRUE;
1087
1088         /* Create a fake OSD menu elementary stream */
1089         if( transcode_osd_new( p_stream, id ) )
1090         {
1091             msg_Err( p_stream, "cannot create osd chain" );
1092             goto error;
1093         }
1094         p_sys->b_osd = VLC_TRUE;
1095     }
1096     else
1097     {
1098         msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
1099                  (char*)&p_fmt->i_codec );
1100         id->id = p_sys->p_out->pf_add( p_sys->p_out, p_fmt );
1101         id->b_transcode = VLC_FALSE;
1102
1103         if( !id->id ) goto error;
1104     }
1105
1106     return id;
1107
1108  error:
1109     if( id->p_decoder )
1110     {
1111         vlc_object_detach( id->p_decoder );
1112         vlc_object_destroy( id->p_decoder );
1113         id->p_decoder = NULL;
1114     }
1115
1116     if( id->p_encoder )
1117     {
1118         vlc_object_detach( id->p_encoder );
1119         es_format_Clean( &id->p_encoder->fmt_out );
1120         vlc_object_destroy( id->p_encoder );
1121         id->p_encoder = NULL;
1122     }
1123
1124     free( id );
1125     return NULL;
1126 }
1127
1128 static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
1129 {
1130     sout_stream_sys_t *p_sys = p_stream->p_sys;
1131
1132     if( id->b_transcode )
1133     {
1134         switch( id->p_decoder->fmt_in.i_cat )
1135         {
1136         case AUDIO_ES:
1137             transcode_audio_close( p_stream, id );
1138             break;
1139         case VIDEO_ES:
1140             transcode_video_close( p_stream, id );
1141             break;
1142         case SPU_ES:
1143             if( p_sys->b_osd )
1144                 transcode_osd_close( p_stream, id );
1145             else
1146                 transcode_spu_close( p_stream, id );
1147             break;
1148         }
1149     }
1150
1151     if( id->id ) p_sys->p_out->pf_del( p_sys->p_out, id->id );
1152
1153     if( id->p_decoder )
1154     {
1155         vlc_object_detach( id->p_decoder );
1156         vlc_object_destroy( id->p_decoder );
1157         id->p_decoder = NULL;
1158     }
1159
1160     if( id->p_encoder )
1161     {
1162         vlc_object_detach( id->p_encoder );
1163         es_format_Clean( &id->p_encoder->fmt_out );
1164         vlc_object_destroy( id->p_encoder );
1165         id->p_encoder = NULL;
1166     }
1167     free( id );
1168
1169     return VLC_SUCCESS;
1170 }
1171
1172 static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
1173                  block_t *p_buffer )
1174 {
1175     sout_stream_sys_t *p_sys = p_stream->p_sys;
1176     block_t *p_out = NULL;
1177
1178     if( !id->b_transcode && id->id )
1179     {
1180         return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_buffer );
1181     }
1182     else if( !id->b_transcode )
1183     {
1184         block_Release( p_buffer );
1185         return VLC_EGENERIC;
1186     }
1187
1188     switch( id->p_decoder->fmt_in.i_cat )
1189     {
1190     case AUDIO_ES:
1191         transcode_audio_process( p_stream, id, p_buffer, &p_out );
1192         break;
1193
1194     case VIDEO_ES:
1195         if( transcode_video_process( p_stream, id, p_buffer, &p_out )
1196             != VLC_SUCCESS )
1197         {
1198             return VLC_EGENERIC;
1199         }
1200         break;
1201
1202     case SPU_ES:
1203         /* Transcode OSD menu pictures. */
1204         if( p_sys->b_osd )
1205         {
1206             if( transcode_osd_process( p_stream, id, p_buffer, &p_out ) !=
1207                 VLC_SUCCESS )
1208             {
1209                 return VLC_EGENERIC;
1210             }
1211         }
1212         else if ( transcode_spu_process( p_stream, id, p_buffer, &p_out ) !=
1213             VLC_SUCCESS )
1214         {
1215             return VLC_EGENERIC;
1216         }
1217         break;
1218
1219     default:
1220         p_out = NULL;
1221         block_Release( p_buffer );
1222         break;
1223     }
1224
1225     if( p_out ) return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_out );
1226     return VLC_SUCCESS;
1227 }
1228
1229 /****************************************************************************
1230  * decoder reencoder part
1231  ****************************************************************************/
1232 static int audio_BitsPerSample( vlc_fourcc_t i_format )
1233 {
1234     switch( i_format )
1235     {
1236     case VLC_FOURCC('u','8',' ',' '):
1237     case VLC_FOURCC('s','8',' ',' '):
1238         return 8;
1239
1240     case VLC_FOURCC('u','1','6','l'):
1241     case VLC_FOURCC('s','1','6','l'):
1242     case VLC_FOURCC('u','1','6','b'):
1243     case VLC_FOURCC('s','1','6','b'):
1244         return 16;
1245
1246     case VLC_FOURCC('u','2','4','l'):
1247     case VLC_FOURCC('s','2','4','l'):
1248     case VLC_FOURCC('u','2','4','b'):
1249     case VLC_FOURCC('s','2','4','b'):
1250         return 24;
1251
1252     case VLC_FOURCC('u','3','2','l'):
1253     case VLC_FOURCC('s','3','2','l'):
1254     case VLC_FOURCC('u','3','2','b'):
1255     case VLC_FOURCC('s','3','2','b'):
1256     case VLC_FOURCC('f','l','3','2'):
1257     case VLC_FOURCC('f','i','3','2'):
1258         return 32;
1259
1260     case VLC_FOURCC('f','l','6','4'):
1261         return 64;
1262     }
1263
1264     return 0;
1265 }
1266
1267 static block_t *transcode_audio_alloc (filter_t *filter, int size)
1268 {
1269     return block_New (filter, size);
1270 }
1271
1272 static filter_t *transcode_audio_filter_new( sout_stream_t *p_stream,
1273                                              sout_stream_id_t *id,
1274                                              es_format_t *p_fmt_in,
1275                                              es_format_t *p_fmt_out,
1276                                              char *psz_name )
1277 {
1278     sout_stream_sys_t *p_sys = p_stream->p_sys;
1279     filter_t *p_filter = vlc_object_create( p_stream, VLC_OBJECT_FILTER );
1280
1281     vlc_object_attach( p_filter, p_stream );
1282     p_filter->pf_audio_buffer_new = transcode_audio_alloc;
1283
1284     p_filter->fmt_in = *p_fmt_in;
1285     p_filter->fmt_out = *p_fmt_out;
1286     if( psz_name )
1287         p_filter->p_cfg = p_sys->p_afilters_cfg[id->i_ufilter];
1288
1289     p_filter->p_module = module_Need( p_filter, "audio filter2", psz_name,
1290                                       VLC_TRUE );
1291     if( p_filter->p_module )
1292     {
1293         p_filter->fmt_out.audio.i_bitspersample =
1294             audio_BitsPerSample( p_filter->fmt_out.i_codec );
1295         *p_fmt_in = p_filter->fmt_out;
1296     }
1297     else
1298     {
1299         vlc_object_detach( p_filter );
1300         vlc_object_destroy( p_filter );
1301         p_filter = 0;
1302     }
1303
1304     return p_filter;
1305 }
1306
1307 static int transcode_audio_new( sout_stream_t *p_stream,
1308                                 sout_stream_id_t *id )
1309 {
1310     sout_stream_sys_t *p_sys = p_stream->p_sys;
1311     es_format_t fmt_last;
1312     int i;
1313
1314     /*
1315      * Open decoder
1316      */
1317
1318     /* Initialization of decoder structures */
1319     id->p_decoder->fmt_out = id->p_decoder->fmt_in;
1320     id->p_decoder->fmt_out.i_extra = 0;
1321     id->p_decoder->fmt_out.p_extra = 0;
1322     id->p_decoder->pf_decode_audio = NULL;
1323     id->p_decoder->pf_aout_buffer_new = audio_new_buffer;
1324     id->p_decoder->pf_aout_buffer_del = audio_del_buffer;
1325     /* id->p_decoder->p_cfg = p_sys->p_audio_cfg; */
1326
1327     id->p_decoder->p_module =
1328         module_Need( id->p_decoder, "decoder", "$codec", 0 );
1329     if( !id->p_decoder->p_module )
1330     {
1331         msg_Err( p_stream, "cannot find decoder" );
1332         return VLC_EGENERIC;
1333     }
1334     id->p_decoder->fmt_out.audio.i_bitspersample =
1335         audio_BitsPerSample( id->p_decoder->fmt_out.i_codec );
1336     fmt_last = id->p_decoder->fmt_out;
1337     /* Fix AAC SBR changing number of channels and sampling rate */
1338     if( !(id->p_decoder->fmt_in.i_codec == VLC_FOURCC('m','p','4','a') &&
1339         fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate &&
1340         fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels) )
1341         fmt_last.audio.i_rate = id->p_decoder->fmt_in.audio.i_rate;
1342
1343     /*
1344      * Open encoder
1345      */
1346
1347     /* Initialization of encoder format structures */
1348     es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1349                     id->p_decoder->fmt_out.i_codec );
1350     id->p_encoder->fmt_in.audio.i_format = id->p_decoder->fmt_out.i_codec;
1351
1352     /* Initialization of encoder format structures */
1353     es_format_Init( &id->p_encoder->fmt_in, AUDIO_ES, VLC_FOURCC('f','l','3','2') );
1354     id->p_encoder->fmt_in.audio.i_format = VLC_FOURCC('f','l','3','2');
1355
1356     id->p_encoder->fmt_in.audio.i_rate = id->p_encoder->fmt_out.audio.i_rate;
1357     id->p_encoder->fmt_in.audio.i_physical_channels =
1358         id->p_encoder->fmt_out.audio.i_physical_channels;
1359     id->p_encoder->fmt_in.audio.i_original_channels =
1360         id->p_encoder->fmt_out.audio.i_original_channels;
1361     id->p_encoder->fmt_in.audio.i_channels =
1362         id->p_encoder->fmt_out.audio.i_channels;
1363     id->p_encoder->fmt_in.audio.i_bitspersample =
1364         audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1365
1366     id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
1367     id->p_encoder->p_module =
1368         module_Need( id->p_encoder, "encoder", p_sys->psz_aenc, VLC_TRUE );
1369     if( !id->p_encoder->p_module )
1370     {
1371         msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_aenc );
1372         module_Unneed( id->p_decoder, id->p_decoder->p_module );
1373         id->p_decoder->p_module = NULL;
1374         return VLC_EGENERIC;
1375     }
1376     id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
1377     id->p_encoder->fmt_in.audio.i_bitspersample =
1378         audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1379
1380     /* Fix AAC SBR changing number of channels and sampling rate */
1381     if( id->p_decoder->fmt_in.i_codec == VLC_FOURCC('m','p','4','a') &&
1382         fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate &&
1383         fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels )
1384     {
1385       id->p_encoder->fmt_in.audio.i_rate = fmt_last.audio.i_rate;
1386       id->p_encoder->fmt_out.audio.i_rate = fmt_last.audio.i_rate;
1387     }
1388
1389     /* Load conversion filters */
1390     if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels ||
1391         fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate )
1392     {
1393         /* We'll have to go through fl32 first */
1394         es_format_t fmt_out = id->p_encoder->fmt_in;
1395         fmt_out.i_codec = fmt_out.audio.i_format = VLC_FOURCC('f','l','3','2');
1396
1397         id->pp_filter[id->i_filter] =
1398             transcode_audio_filter_new( p_stream, id, &fmt_last, &fmt_out, NULL );
1399
1400         if( id->pp_filter[id->i_filter] ) id->i_filter++;
1401     }
1402
1403     for( i = 0; i < TRANSCODE_FILTERS; i++ )
1404     {
1405         if( (fmt_last.audio.i_channels !=
1406             id->p_encoder->fmt_in.audio.i_channels) ||
1407             (fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate) ||
1408             (fmt_last.i_codec != id->p_encoder->fmt_in.i_codec) )
1409         {
1410             id->pp_filter[id->i_filter] =
1411                 transcode_audio_filter_new( p_stream, id, &fmt_last,
1412                                             &id->p_encoder->fmt_in, NULL );
1413
1414             if( id->pp_filter[id->i_filter] )
1415                 id->i_filter++;
1416             else
1417                 break;
1418         }
1419     }
1420
1421     /* Final checks to see if conversions were successful */
1422     if( fmt_last.i_codec != id->p_encoder->fmt_in.i_codec )
1423     {
1424         msg_Err( p_stream, "no audio filter found (%4.4s->%4.4s)",
1425                  (char *)&fmt_last.i_codec,
1426                  (char *)&id->p_encoder->fmt_in.i_codec );
1427         transcode_audio_close( p_stream, id );
1428         return VLC_EGENERIC;
1429     }
1430
1431     /* Load user specified audio filters now */
1432     for( i = 0; (i < p_sys->i_afilters) &&
1433                 (id->i_ufilter < TRANSCODE_FILTERS); i++ )
1434     {
1435         id->pp_ufilter[id->i_ufilter] =
1436             transcode_audio_filter_new( p_stream, id, &fmt_last,
1437                                         &id->p_encoder->fmt_in,
1438                                         p_sys->psz_afilters[i] );
1439
1440         if( id->pp_ufilter[id->i_ufilter] )
1441             id->i_ufilter++;
1442         else
1443             break;
1444     }
1445
1446     if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels )
1447     {
1448 #if 1
1449         module_Unneed( id->p_encoder, id->p_encoder->p_module );
1450         id->p_encoder->p_module = NULL;
1451
1452         /* This might work, but only if the encoder is restarted */
1453         id->p_encoder->fmt_in.audio.i_channels = fmt_last.audio.i_channels;
1454         id->p_encoder->fmt_out.audio.i_channels = fmt_last.audio.i_channels;
1455
1456         id->p_encoder->fmt_in.audio.i_physical_channels =
1457             id->p_encoder->fmt_in.audio.i_original_channels =
1458                 fmt_last.audio.i_physical_channels;
1459         id->p_encoder->fmt_out.audio.i_physical_channels =
1460             id->p_encoder->fmt_out.audio.i_original_channels =
1461                 fmt_last.audio.i_physical_channels;
1462
1463         msg_Dbg( p_stream, "number of audio channels for mixing changed, "
1464                  "trying to reopen the encoder for mixing %i to %i channels",
1465                  fmt_last.audio.i_channels,
1466                  id->p_encoder->fmt_in.audio.i_channels );
1467
1468         /* reload encoder */
1469         id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
1470         id->p_encoder->p_module =
1471             module_Need( id->p_encoder, "encoder", p_sys->psz_aenc, VLC_TRUE );
1472         if( !id->p_encoder->p_module )
1473         {
1474             msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_aenc );
1475             transcode_audio_close( p_stream, id );
1476             return VLC_EGENERIC;
1477         }
1478         id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
1479         id->p_encoder->fmt_in.audio.i_bitspersample =
1480             audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1481 #else
1482         msg_Err( p_stream, "no audio filter found for mixing from"
1483                  " %i to %i channels", fmt_last.audio.i_channels,
1484                  id->p_encoder->fmt_in.audio.i_channels );
1485
1486         transcode_audio_close( p_stream, id );
1487         return VLC_EGENERIC;
1488 #endif
1489     }
1490
1491     if( fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate )
1492     {
1493         msg_Err( p_stream, "no audio filter found for resampling from"
1494                  " %iHz to %iHz", fmt_last.audio.i_rate,
1495                  id->p_encoder->fmt_in.audio.i_rate );
1496 #if 0
1497         /* FIXME : this might work, but only if the encoder is restarted */
1498         id->p_encoder->fmt_in.audio.i_rate = fmt_last.audio.i_rate;
1499         id->p_encoder->fmt_out.audio.i_rate = fmt_last.audio.i_rate;
1500 #else
1501         transcode_audio_close( p_stream, id );
1502         return VLC_EGENERIC;
1503 #endif
1504     }
1505
1506     /* FIXME: Hack for mp3 transcoding support */
1507     if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC( 'm','p','3',' ' ) )
1508         id->p_encoder->fmt_out.i_codec = VLC_FOURCC( 'm','p','g','a' );
1509
1510     return VLC_SUCCESS;
1511 }
1512
1513 static void transcode_audio_close( sout_stream_t *p_stream,
1514                                    sout_stream_id_t *id )
1515 {
1516     int i;
1517
1518     /* Close decoder */
1519     if( id->p_decoder->p_module )
1520         module_Unneed( id->p_decoder, id->p_decoder->p_module );
1521     id->p_decoder->p_module = NULL;
1522
1523     /* Close encoder */
1524     if( id->p_encoder->p_module )
1525         module_Unneed( id->p_encoder, id->p_encoder->p_module );
1526     id->p_encoder->p_module = NULL;
1527
1528     /* Close filters */
1529     for( i = 0; i < id->i_filter; i++ )
1530     {
1531         vlc_object_detach( id->pp_filter[i] );
1532         if( id->pp_filter[i]->p_module )
1533             module_Unneed( id->pp_filter[i], id->pp_filter[i]->p_module );
1534         vlc_object_destroy( id->pp_filter[i] );
1535     }
1536     for( i = 0; i < id->i_ufilter; i++ )
1537     {
1538         vlc_object_detach( id->pp_ufilter[i] );
1539         if( id->pp_ufilter[i]->p_module )
1540             module_Unneed( id->pp_ufilter[i], id->pp_ufilter[i]->p_module );
1541         vlc_object_destroy( id->pp_ufilter[i] );
1542     }
1543 }
1544
1545 static int transcode_audio_process( sout_stream_t *p_stream,
1546                                     sout_stream_id_t *id,
1547                                     block_t *in, block_t **out )
1548 {
1549     sout_stream_sys_t *p_sys = p_stream->p_sys;
1550     aout_buffer_t *p_audio_buf;
1551     block_t *p_block, *p_audio_block;
1552     int i;
1553     *out = NULL;
1554
1555     while( (p_audio_buf = id->p_decoder->pf_decode_audio( id->p_decoder,
1556                                                           &in )) )
1557     {
1558         sout_UpdateStatistic( p_stream->p_sout, SOUT_STATISTIC_DECODED_AUDIO, 1 );
1559         if( p_sys->b_master_sync )
1560         {
1561             mtime_t i_dts = date_Get( &id->interpolated_pts ) + 1;
1562             if ( p_audio_buf->start_date - i_dts > MASTER_SYNC_MAX_DRIFT
1563                   || p_audio_buf->start_date - i_dts < -MASTER_SYNC_MAX_DRIFT )
1564             {
1565                 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
1566                 date_Set( &id->interpolated_pts, p_audio_buf->start_date );
1567                 i_dts = p_audio_buf->start_date + 1;
1568             }
1569             p_sys->i_master_drift = p_audio_buf->start_date - i_dts;
1570             date_Increment( &id->interpolated_pts, p_audio_buf->i_nb_samples );
1571             p_audio_buf->start_date -= p_sys->i_master_drift;
1572             p_audio_buf->end_date -= p_sys->i_master_drift;
1573         }
1574
1575         p_audio_block = p_audio_buf->p_sys;
1576         p_audio_block->i_buffer = p_audio_buf->i_nb_bytes;
1577         p_audio_block->i_dts = p_audio_block->i_pts =
1578             p_audio_buf->start_date;
1579         p_audio_block->i_length = p_audio_buf->end_date -
1580             p_audio_buf->start_date;
1581         p_audio_block->i_samples = p_audio_buf->i_nb_samples;
1582
1583         /* Run filter chain */
1584         for( i = 0; i < id->i_filter; i++ )
1585         {
1586             p_audio_block =
1587                 id->pp_filter[i]->pf_audio_filter( id->pp_filter[i],
1588                                                    p_audio_block );
1589         }
1590
1591         /* Run user specified filter chain */
1592         for( i = 0; i < id->i_ufilter; i++ )
1593         {
1594             p_audio_block =
1595                 id->pp_ufilter[i]->pf_audio_filter( id->pp_ufilter[i],
1596                                                     p_audio_block );
1597         }
1598
1599         p_audio_buf->p_buffer = p_audio_block->p_buffer;
1600         p_audio_buf->i_nb_bytes = p_audio_block->i_buffer;
1601         p_audio_buf->i_nb_samples = p_audio_block->i_samples;
1602         p_audio_buf->start_date = p_audio_block->i_dts;
1603         p_audio_buf->end_date = p_audio_block->i_dts + p_audio_block->i_length;
1604
1605         p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf );
1606         block_ChainAppend( out, p_block );
1607         block_Release( p_audio_block );
1608         free( p_audio_buf );
1609     }
1610
1611     return VLC_SUCCESS;
1612 }
1613
1614 static void audio_release_buffer( aout_buffer_t *p_buffer )
1615 {
1616     if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
1617     if( p_buffer ) free( p_buffer );
1618 }
1619
1620 static aout_buffer_t *audio_new_buffer( decoder_t *p_dec, int i_samples )
1621 {
1622     aout_buffer_t *p_buffer;
1623     block_t *p_block;
1624     int i_size;
1625
1626     if( p_dec->fmt_out.audio.i_bitspersample )
1627     {
1628         i_size = i_samples * p_dec->fmt_out.audio.i_bitspersample / 8 *
1629             p_dec->fmt_out.audio.i_channels;
1630     }
1631     else if( p_dec->fmt_out.audio.i_bytes_per_frame &&
1632              p_dec->fmt_out.audio.i_frame_length )
1633     {
1634         i_size = i_samples * p_dec->fmt_out.audio.i_bytes_per_frame /
1635             p_dec->fmt_out.audio.i_frame_length;
1636     }
1637     else
1638     {
1639         i_size = i_samples * 4 * p_dec->fmt_out.audio.i_channels;
1640     }
1641
1642     p_buffer = malloc( sizeof(aout_buffer_t) );
1643     if( !p_buffer ) return NULL;
1644     p_buffer->b_discontinuity = VLC_FALSE;
1645     p_buffer->pf_release = audio_release_buffer;
1646     p_buffer->p_sys = p_block = block_New( p_dec, i_size );
1647
1648     p_buffer->p_buffer = p_block->p_buffer;
1649     p_buffer->i_size = p_buffer->i_nb_bytes = p_block->i_buffer;
1650     p_buffer->i_nb_samples = i_samples;
1651     p_block->i_samples = i_samples;
1652
1653     return p_buffer;
1654 }
1655
1656 static void audio_del_buffer( decoder_t *p_dec, aout_buffer_t *p_buffer )
1657 {
1658     if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
1659     if( p_buffer ) free( p_buffer );
1660 }
1661
1662 /*
1663  * video
1664  */
1665 static int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_t *id )
1666 {
1667     sout_stream_sys_t *p_sys = p_stream->p_sys;
1668     int i;
1669
1670     /* Open decoder
1671      * Initialization of decoder structures
1672      */
1673     id->p_decoder->fmt_out = id->p_decoder->fmt_in;
1674     id->p_decoder->fmt_out.i_extra = 0;
1675     id->p_decoder->fmt_out.p_extra = 0;
1676     id->p_decoder->pf_decode_video = NULL;
1677     id->p_decoder->pf_get_cc = NULL;
1678     id->p_decoder->pf_get_cc = 0;
1679     id->p_decoder->pf_vout_buffer_new = video_new_buffer_decoder;
1680     id->p_decoder->pf_vout_buffer_del = video_del_buffer_decoder;
1681     id->p_decoder->pf_picture_link    = video_link_picture_decoder;
1682     id->p_decoder->pf_picture_unlink  = video_unlink_picture_decoder;
1683     id->p_decoder->p_owner = malloc( sizeof(decoder_owner_sys_t) );
1684     for( i = 0; i < PICTURE_RING_SIZE; i++ )
1685         id->p_decoder->p_owner->pp_pics[i] = 0;
1686     id->p_decoder->p_owner->p_sys = p_sys;
1687     /* id->p_decoder->p_cfg = p_sys->p_video_cfg; */
1688
1689     id->p_decoder->p_module =
1690         module_Need( id->p_decoder, "decoder", "$codec", 0 );
1691
1692     if( !id->p_decoder->p_module )
1693     {
1694         msg_Err( p_stream, "cannot find decoder" );
1695         return VLC_EGENERIC;
1696     }
1697
1698     /*
1699      * Open encoder.
1700      * Because some info about the decoded input will only be available
1701      * once the first frame is decoded, we actually only test the availability
1702      * of the encoder here.
1703      */
1704
1705     /* Initialization of encoder format structures */
1706     es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1707                     id->p_decoder->fmt_out.i_codec );
1708     id->p_encoder->fmt_in.video.i_chroma = id->p_decoder->fmt_out.i_codec;
1709
1710     /* The dimensions will be set properly later on.
1711      * Just put sensible values so we can test an encoder is available. */
1712     id->p_encoder->fmt_in.video.i_width =
1713         id->p_encoder->fmt_out.video.i_width ?
1714         id->p_encoder->fmt_out.video.i_width :
1715         id->p_decoder->fmt_in.video.i_width ?
1716         id->p_decoder->fmt_in.video.i_width : 16;
1717     id->p_encoder->fmt_in.video.i_height =
1718         id->p_encoder->fmt_out.video.i_height ?
1719         id->p_encoder->fmt_out.video.i_height :
1720         id->p_decoder->fmt_in.video.i_height ?
1721         id->p_decoder->fmt_in.video.i_height : 16;
1722     id->p_encoder->fmt_in.video.i_frame_rate = 25;
1723     id->p_encoder->fmt_in.video.i_frame_rate_base = 1;
1724
1725     id->p_encoder->i_threads = p_sys->i_threads;
1726     id->p_encoder->p_cfg = p_sys->p_video_cfg;
1727
1728     id->p_encoder->p_module =
1729         module_Need( id->p_encoder, "encoder", p_sys->psz_venc, VLC_TRUE );
1730     if( !id->p_encoder->p_module )
1731     {
1732         msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_venc );
1733         module_Unneed( id->p_decoder, id->p_decoder->p_module );
1734         id->p_decoder->p_module = 0;
1735         return VLC_EGENERIC;
1736     }
1737
1738     /* Close the encoder.
1739      * We'll open it only when we have the first frame. */
1740     module_Unneed( id->p_encoder, id->p_encoder->p_module );
1741     if( id->p_encoder->fmt_out.p_extra )
1742     {
1743         free( id->p_encoder->fmt_out.p_extra );
1744         id->p_encoder->fmt_out.p_extra = NULL;
1745         id->p_encoder->fmt_out.i_extra = 0;
1746     }
1747     id->p_encoder->p_module = NULL;
1748
1749     if( p_sys->i_threads >= 1 )
1750     {
1751         int i_priority = p_sys->b_high_priority ? VLC_THREAD_PRIORITY_OUTPUT :
1752                            VLC_THREAD_PRIORITY_VIDEO;
1753         p_sys->id_video = id;
1754         vlc_mutex_init( p_stream, &p_sys->lock_out );
1755         vlc_cond_init( p_stream, &p_sys->cond );
1756         memset( p_sys->pp_pics, 0, sizeof(p_sys->pp_pics) );
1757         p_sys->i_first_pic = 0;
1758         p_sys->i_last_pic = 0;
1759         p_sys->p_buffers = NULL;
1760         p_sys->b_die = p_sys->b_error = 0;
1761         if( vlc_thread_create( p_sys, "encoder", EncoderThread, i_priority,
1762                                VLC_FALSE ) )
1763         {
1764             msg_Err( p_stream, "cannot spawn encoder thread" );
1765             module_Unneed( id->p_decoder, id->p_decoder->p_module );
1766             id->p_decoder->p_module = 0;
1767             return VLC_EGENERIC;
1768         }
1769     }
1770
1771     return VLC_SUCCESS;
1772 }
1773
1774 static int transcode_video_encoder_open( sout_stream_t *p_stream,
1775                                          sout_stream_id_t *id )
1776 {
1777     sout_stream_sys_t *p_sys = p_stream->p_sys;
1778
1779      /* Calculate scaling, padding, cropping etc. */
1780      /* width/height of source */
1781      int i_src_width = id->p_decoder->fmt_out.video.i_width;
1782      int i_src_height = id->p_decoder->fmt_out.video.i_height;
1783
1784      /* with/height scaling */
1785      float f_scale_width = 1;
1786      float f_scale_height = 1;
1787
1788      /* width/height of output stream */
1789      int i_dst_width;
1790      int i_dst_height;
1791
1792      /* aspect ratio */
1793      float f_aspect = (float)id->p_decoder->fmt_out.video.i_aspect /
1794                              VOUT_ASPECT_FACTOR;
1795
1796      msg_Dbg( p_stream, "decoder aspect is %i:%i",
1797                   id->p_decoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
1798
1799      /* Change f_aspect from source frame to source pixel */
1800      f_aspect = f_aspect * i_src_height / i_src_width;
1801      msg_Dbg( p_stream, "source pixel aspect is %f:1", f_aspect );
1802
1803      /* width/height after cropping */
1804      p_sys->i_src_x_offset = p_sys->i_crop_left & ~1;
1805      p_sys->i_src_y_offset = p_sys->i_crop_top & ~1;
1806      p_sys->i_crop_width = i_src_width - ( p_sys->i_crop_left & ~1 ) -
1807                             ( p_sys->i_crop_right & ~1 );
1808      p_sys->i_crop_height = i_src_height - ( p_sys->i_crop_top & ~1 ) -
1809                             ( p_sys->i_crop_bottom & ~1 );
1810
1811     /* Calculate scaling factor for specified parameters */
1812     if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1813         id->p_encoder->fmt_out.video.i_height <= 0 && p_sys->f_scale )
1814     {
1815         /* Global scaling. Make sure width will remain a factor of 16 */
1816         float f_real_scale;
1817         int  i_new_height;
1818         int i_new_width = i_src_width * p_sys->f_scale;
1819
1820         if( i_new_width % 16 <= 7 && i_new_width >= 16 )
1821             i_new_width -= i_new_width % 16;
1822         else
1823             i_new_width += 16 - i_new_width % 16;
1824
1825         f_real_scale = (float)( i_new_width ) / (float) i_src_width;
1826
1827         i_new_height = __MAX( 16, i_src_height * (float)f_real_scale );
1828
1829         f_scale_width = f_real_scale;
1830         f_scale_height = (float) i_new_height / (float) i_src_height;
1831     }
1832     else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1833              id->p_encoder->fmt_out.video.i_height <= 0 )
1834     {
1835         /* Only width specified */
1836         f_scale_width = (float)id->p_encoder->fmt_out.video.i_width /
1837                              p_sys->i_crop_width;
1838         f_scale_height = f_scale_width;
1839     }
1840     else if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1841              id->p_encoder->fmt_out.video.i_height > 0 )
1842     {
1843          /* Only height specified */
1844          f_scale_height = (float)id->p_encoder->fmt_out.video.i_height /
1845                               p_sys->i_crop_height;
1846          f_scale_width = f_scale_height;
1847      }
1848      else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1849               id->p_encoder->fmt_out.video.i_height > 0 )
1850      {
1851          /* Width and height specified */
1852          f_scale_width = (float)id->p_encoder->fmt_out.video.i_width
1853                                / p_sys->i_crop_width;
1854          f_scale_height = (float)id->p_encoder->fmt_out.video.i_height
1855                                / p_sys->i_crop_height;
1856      }
1857
1858      /* check maxwidth and maxheight
1859       * note: maxwidth and maxheight currently does not handle
1860       * canvas and padding, just scaling and cropping.
1861       */
1862      if( p_sys->i_maxwidth && f_scale_width > (float)p_sys->i_maxwidth /
1863                                                      p_sys->i_crop_width )
1864      {
1865          f_scale_width = (float)p_sys->i_maxwidth / p_sys->i_crop_width;
1866      }
1867      if( p_sys->i_maxheight && f_scale_height > (float)p_sys->i_maxheight /
1868                                                        p_sys->i_crop_height )
1869      {
1870          f_scale_height = (float)p_sys->i_maxheight / p_sys->i_crop_height;
1871      }
1872
1873      /* Change aspect ratio from source pixel to scaled pixel */
1874      f_aspect = f_aspect * f_scale_height / f_scale_width;
1875      msg_Dbg( p_stream, "scaled pixel aspect is %f:1", f_aspect );
1876
1877      /* Correct scaling for target aspect ratio
1878       * Shrink video if necessary
1879       */
1880      if ( p_sys->i_canvas_aspect > 0 )
1881      {
1882          float f_target_aspect = (float)p_sys->i_canvas_aspect /
1883                                         VOUT_ASPECT_FACTOR;
1884
1885          if( p_sys->i_canvas_width > 0 && p_sys->i_canvas_height > 0)
1886          {
1887              /* Calculate pixel aspect of canvas */
1888              f_target_aspect = f_target_aspect / p_sys->i_canvas_width *
1889                                p_sys->i_canvas_height;
1890          }
1891          if( f_target_aspect > f_aspect )
1892          {
1893              /* Reduce width scale to increase aspect */
1894              f_scale_width = f_scale_width * f_aspect / f_target_aspect;
1895          }
1896          else
1897          {
1898              /* Reduce height scale to decrease aspect */
1899              f_scale_height = f_scale_height * f_target_aspect / f_aspect;
1900          }
1901          f_aspect = f_target_aspect;
1902          msg_Dbg( p_stream, "canvas scaled pixel aspect is %f:1", f_aspect );
1903      }
1904
1905      /* f_scale_width and f_scale_height are now final */
1906      /* Calculate width, height from scaling
1907       * Make sure its multiple of 2
1908       */
1909      i_dst_width = 2 * (int)( p_sys->i_crop_width * f_scale_width / 2 + 0.5 );
1910      i_dst_height = 2 *
1911                     (int)( p_sys->i_crop_height * f_scale_height / 2 + 0.5 );
1912
1913      p_sys->i_nopadd_width = i_dst_width;
1914      p_sys->i_nopadd_height = i_dst_height;
1915      p_sys->i_dst_x_offset = 0;
1916      p_sys->i_dst_y_offset = 0;
1917
1918      /* Handle canvas and padding */
1919      if( p_sys->i_canvas_width <= 0 )
1920      {
1921          /* No canvas width set, add explicit padding border */
1922          i_dst_width = p_sys->i_nopadd_width + ( p_sys->i_padd_left & ~1 ) +
1923                       ( p_sys->i_padd_right & ~1 );
1924          p_sys->i_dst_x_offset = ( p_sys->i_padd_left & ~1 );
1925      }
1926      else
1927      {
1928          /* Canvas set, check if we have to padd or crop */
1929          if( p_sys->i_canvas_width < p_sys->i_nopadd_width )
1930          {
1931              /* need to crop more, but keep same scaling */
1932              int i_crop = 2 * (int)( ( p_sys->i_canvas_width & ~1 ) /
1933                                        f_scale_width / 2 + 0.5 );
1934
1935              p_sys->i_src_x_offset += ( ( p_sys->i_crop_width - i_crop ) / 2 )
1936                                            & ~1;
1937              p_sys->i_crop_width = i_crop;
1938              i_dst_width = p_sys->i_canvas_width & ~1;
1939              p_sys->i_nopadd_width = i_dst_width;
1940          }
1941          else if( p_sys->i_canvas_width > p_sys->i_nopadd_width )
1942          {
1943              /* need to padd */
1944              i_dst_width = p_sys->i_canvas_width & ~1;
1945              p_sys->i_dst_x_offset = ( i_dst_width - p_sys->i_nopadd_width )/2;
1946              p_sys->i_dst_x_offset = p_sys->i_dst_x_offset & ~1;
1947          }
1948      }
1949
1950      if( p_sys->i_canvas_height <= 0 )
1951      {
1952          /* No canvas set, add padding border */
1953          i_dst_height = p_sys->i_nopadd_height + ( p_sys->i_padd_top & ~1 ) +
1954                         ( p_sys->i_padd_bottom & ~1 );
1955          p_sys->i_dst_y_offset = ( p_sys->i_padd_top & ~1 );
1956      }
1957      else
1958      {
1959          /* Canvas set, check if we have to padd or crop */
1960          if( p_sys->i_canvas_height < p_sys->i_nopadd_height )
1961          {
1962              /* need to crop more, but keep same scaling */
1963              int i_crop = 2 * (int)( ( p_sys->i_canvas_height & ~1 ) /
1964                                         f_scale_height / 2 + 0.5 );
1965
1966              p_sys->i_src_y_offset += ( ( p_sys->i_crop_height - i_crop ) / 2 )
1967                                                 & ~1;
1968              p_sys->i_crop_height = i_crop;
1969              i_dst_height = p_sys->i_canvas_height & ~1;
1970              p_sys->i_nopadd_height = i_dst_height;
1971          }
1972          else if( p_sys->i_canvas_height > p_sys->i_nopadd_height )
1973          {
1974              /* need to padd */
1975              i_dst_height = p_sys->i_canvas_height & ~1;
1976              p_sys->i_dst_y_offset = ( i_dst_height - p_sys->i_nopadd_height )
1977                                         /2;
1978              p_sys->i_dst_y_offset = p_sys->i_dst_y_offset & ~1;
1979          }
1980      }
1981
1982      /* Change aspect ratio from scaled pixel to output frame */
1983      f_aspect = f_aspect * i_dst_width / i_dst_height;
1984
1985      /* Store calculated values */
1986      id->p_encoder->fmt_out.video.i_width = i_dst_width;
1987      id->p_encoder->fmt_out.video.i_height = i_dst_height;
1988
1989      id->p_encoder->fmt_in.video.i_width = i_dst_width;
1990      id->p_encoder->fmt_in.video.i_height = i_dst_height;
1991
1992      msg_Dbg( p_stream, "source %ix%i, crop %ix%i, "
1993                         "destination %ix%i, padding %ix%i",
1994          i_src_width, i_src_height,
1995          p_sys->i_crop_width, p_sys->i_crop_height,
1996          p_sys->i_nopadd_width, p_sys->i_nopadd_height,
1997          i_dst_width, i_dst_height
1998      );
1999
2000     /* Handle frame rate conversion */
2001     if( !id->p_encoder->fmt_out.video.i_frame_rate ||
2002         !id->p_encoder->fmt_out.video.i_frame_rate_base )
2003     {
2004         if( id->p_decoder->fmt_out.video.i_frame_rate &&
2005             id->p_decoder->fmt_out.video.i_frame_rate_base )
2006         {
2007             id->p_encoder->fmt_out.video.i_frame_rate =
2008                 id->p_decoder->fmt_out.video.i_frame_rate;
2009             id->p_encoder->fmt_out.video.i_frame_rate_base =
2010                 id->p_decoder->fmt_out.video.i_frame_rate_base;
2011         }
2012         else
2013         {
2014             /* Pick a sensible default value */
2015             id->p_encoder->fmt_out.video.i_frame_rate = 25;
2016             id->p_encoder->fmt_out.video.i_frame_rate_base = 1;
2017         }
2018     }
2019
2020     id->p_encoder->fmt_in.video.i_frame_rate =
2021         id->p_encoder->fmt_out.video.i_frame_rate;
2022     id->p_encoder->fmt_in.video.i_frame_rate_base =
2023         id->p_encoder->fmt_out.video.i_frame_rate_base;
2024
2025     date_Init( &id->interpolated_pts,
2026                id->p_encoder->fmt_out.video.i_frame_rate,
2027                id->p_encoder->fmt_out.video.i_frame_rate_base );
2028
2029     /* Check whether a particular aspect ratio was requested */
2030     if( !id->p_encoder->fmt_out.video.i_aspect )
2031     {
2032         id->p_encoder->fmt_out.video.i_aspect = (int)( f_aspect * VOUT_ASPECT_FACTOR + 0.5 );
2033     }
2034     id->p_encoder->fmt_in.video.i_aspect =
2035         id->p_encoder->fmt_out.video.i_aspect;
2036
2037     msg_Dbg( p_stream, "encoder aspect is %i:%i", id->p_encoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
2038
2039     id->p_encoder->p_module =
2040         module_Need( id->p_encoder, "encoder", p_sys->psz_venc, VLC_TRUE );
2041     if( !id->p_encoder->p_module )
2042     {
2043         msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_venc );
2044         return VLC_EGENERIC;
2045     }
2046
2047     id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
2048
2049     /* Hack for mp2v/mp1v transcoding support */
2050     if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','1','v') ||
2051         id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','2','v') )
2052     {
2053         id->p_encoder->fmt_out.i_codec = VLC_FOURCC('m','p','g','v');
2054     }
2055
2056     id->id = p_stream->p_sys->p_out->pf_add( p_stream->p_sys->p_out,
2057                                              &id->p_encoder->fmt_out );
2058     if( !id->id )
2059     {
2060         msg_Err( p_stream, "cannot add this stream" );
2061         return VLC_EGENERIC;
2062     }
2063
2064     return VLC_SUCCESS;
2065 }
2066
2067 static void transcode_video_close( sout_stream_t *p_stream,
2068                                    sout_stream_id_t *id )
2069 {
2070     int i, j;
2071
2072     if( p_stream->p_sys->i_threads >= 1 )
2073     {
2074         vlc_mutex_lock( &p_stream->p_sys->lock_out );
2075         vlc_object_kill( p_stream->p_sys );
2076         vlc_cond_signal( &p_stream->p_sys->cond );
2077         vlc_mutex_unlock( &p_stream->p_sys->lock_out );
2078         vlc_thread_join( p_stream->p_sys );
2079         vlc_mutex_destroy( &p_stream->p_sys->lock_out );
2080         vlc_cond_destroy( &p_stream->p_sys->cond );
2081     }
2082
2083     /* Close decoder */
2084     if( id->p_decoder->p_module )
2085         module_Unneed( id->p_decoder, id->p_decoder->p_module );
2086
2087     if( id->p_decoder->p_owner )
2088     {
2089         /* Clean-up pictures ring buffer */
2090         for( i = 0; i < PICTURE_RING_SIZE; i++ )
2091         {
2092             if( id->p_decoder->p_owner->pp_pics[i] )
2093                 video_del_buffer( VLC_OBJECT(id->p_decoder),
2094                                   id->p_decoder->p_owner->pp_pics[i] );
2095         }
2096         free( id->p_decoder->p_owner );
2097     }
2098
2099     /* Close encoder */
2100     if( id->p_encoder->p_module )
2101         module_Unneed( id->p_encoder, id->p_encoder->p_module );
2102
2103     /* Close filters */
2104     for( i = 0; i < id->i_filter; i++ )
2105     {
2106         vlc_object_detach( id->pp_filter[i] );
2107         if( id->pp_filter[i]->p_module )
2108             module_Unneed( id->pp_filter[i], id->pp_filter[i]->p_module );
2109
2110         /* Clean-up pictures ring buffer */
2111         for( j = 0; j < PICTURE_RING_SIZE; j++ )
2112         {
2113             if( id->pp_filter[i]->p_owner->pp_pics[j] )
2114                 video_del_buffer( VLC_OBJECT(id->pp_filter[i]),
2115                                   id->pp_filter[i]->p_owner->pp_pics[j] );
2116         }
2117         free( id->pp_filter[i]->p_owner );
2118         vlc_object_destroy( id->pp_filter[i] );
2119         id->pp_filter[i] = NULL;
2120     }
2121
2122     for( i = 0; i < id->i_ufilter; i++ )
2123     {
2124         vlc_object_detach( id->pp_ufilter[i] );
2125         if( id->pp_ufilter[i]->p_module )
2126             module_Unneed( id->pp_ufilter[i], id->pp_ufilter[i]->p_module );
2127
2128         /* Clean-up pictures ring buffer */
2129         for( j = 0; j < PICTURE_RING_SIZE; j++ )
2130         {
2131             if( id->pp_ufilter[i]->p_owner->pp_pics[j] )
2132                 video_del_buffer( VLC_OBJECT(id->pp_ufilter[i]),
2133                                   id->pp_ufilter[i]->p_owner->pp_pics[j] );
2134         }
2135         free( id->pp_ufilter[i]->p_owner );
2136         vlc_object_destroy( id->pp_ufilter[i] );
2137         id->pp_ufilter[i] = NULL;
2138     }
2139 }
2140
2141 static int transcode_video_process( sout_stream_t *p_stream,
2142                                     sout_stream_id_t *id,
2143                                     block_t *in, block_t **out )
2144 {
2145     sout_stream_sys_t *p_sys = p_stream->p_sys;
2146     int i_duplicate = 1, i;
2147     picture_t *p_pic, *p_pic2 = NULL;
2148     *out = NULL;
2149
2150     while( (p_pic = id->p_decoder->pf_decode_video( id->p_decoder, &in )) )
2151     {
2152         subpicture_t *p_subpic = NULL;
2153
2154         sout_UpdateStatistic( p_stream->p_sout, SOUT_STATISTIC_DECODED_VIDEO, 1 );
2155
2156         if( p_stream->p_sout->i_out_pace_nocontrol && p_sys->b_hurry_up )
2157         {
2158             mtime_t current_date = mdate();
2159             if( current_date + 50000 > p_pic->date )
2160             {
2161                 msg_Dbg( p_stream, "late picture skipped ("I64Fd")",
2162                          current_date + 50000 - p_pic->date );
2163                 p_pic->pf_release( p_pic );
2164                 continue;
2165             }
2166         }
2167
2168         if( p_sys->b_master_sync )
2169         {
2170             mtime_t i_video_drift;
2171             mtime_t i_master_drift = p_sys->i_master_drift;
2172             mtime_t i_pts;
2173
2174             i_pts = date_Get( &id->interpolated_pts ) + 1;
2175             if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2176                   || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2177             {
2178                 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2179                 date_Set( &id->interpolated_pts, p_pic->date );
2180                 i_pts = p_pic->date + 1;
2181             }
2182             i_video_drift = p_pic->date - i_pts;
2183             i_duplicate = 1;
2184
2185             /* Set the pts of the frame being encoded */
2186             p_pic->date = i_pts;
2187
2188             if( i_video_drift < (i_master_drift - 50000) )
2189             {
2190 #if 0
2191                 msg_Dbg( p_stream, "dropping frame (%i)",
2192                          (int)(i_video_drift - i_master_drift) );
2193 #endif
2194                 p_pic->pf_release( p_pic );
2195                 continue;
2196             }
2197             else if( i_video_drift > (i_master_drift + 50000) )
2198             {
2199 #if 0
2200                 msg_Dbg( p_stream, "adding frame (%i)",
2201                          (int)(i_video_drift - i_master_drift) );
2202 #endif
2203                 i_duplicate = 2;
2204             }
2205         }
2206
2207         if( !id->p_encoder->p_module )
2208         {
2209             if( transcode_video_encoder_open( p_stream, id ) != VLC_SUCCESS )
2210             {
2211                 p_pic->pf_release( p_pic );
2212                 transcode_video_close( p_stream, id );
2213                 id->b_transcode = VLC_FALSE;
2214                 return VLC_EGENERIC;
2215             }
2216
2217             /* Deinterlace */
2218             if( p_stream->p_sys->b_deinterlace )
2219             {
2220                 id->pp_filter[id->i_filter] =
2221                     vlc_object_create( p_stream, VLC_OBJECT_FILTER );
2222                 vlc_object_attach( id->pp_filter[id->i_filter], p_stream );
2223
2224                 id->pp_filter[id->i_filter]->pf_vout_buffer_new =
2225                     video_new_buffer_filter;
2226                 id->pp_filter[id->i_filter]->pf_vout_buffer_del =
2227                     video_del_buffer_filter;
2228
2229                 id->pp_filter[id->i_filter]->fmt_in = id->p_decoder->fmt_out;
2230                 id->pp_filter[id->i_filter]->fmt_out = id->p_decoder->fmt_out;
2231                 id->pp_filter[id->i_filter]->p_cfg = p_sys->p_deinterlace_cfg;
2232                 id->pp_filter[id->i_filter]->p_module =
2233                     module_Need( id->pp_filter[id->i_filter],
2234                                  "video filter2", p_sys->psz_deinterlace,
2235                                  VLC_TRUE );
2236                 if( id->pp_filter[id->i_filter]->p_module )
2237                 {
2238                     id->pp_filter[id->i_filter]->p_owner =
2239                         malloc( sizeof(filter_owner_sys_t) );
2240                     for( i = 0; i < PICTURE_RING_SIZE; i++ )
2241                         id->pp_filter[id->i_filter]->p_owner->pp_pics[i] = 0;
2242                     id->pp_filter[id->i_filter]->p_owner->p_sys = p_sys;
2243
2244                     id->i_filter++;
2245                 }
2246                 else
2247                 {
2248                     msg_Dbg( p_stream, "no video filter found" );
2249                     vlc_object_detach( id->pp_filter[id->i_filter] );
2250                     vlc_object_destroy( id->pp_filter[id->i_filter] );
2251                 }
2252             }
2253
2254             /* Check if we need a filter for chroma conversion or resizing */
2255             if( id->p_decoder->fmt_out.video.i_chroma !=
2256                 id->p_encoder->fmt_in.video.i_chroma ||
2257
2258                 (int)id->p_decoder->fmt_out.video.i_width != p_sys->i_crop_width ||
2259                 p_sys->i_crop_width != p_sys->i_nopadd_width ||
2260                 p_sys->i_nopadd_width != (int)id->p_encoder->fmt_out.video.i_width ||
2261
2262                 (int)id->p_decoder->fmt_out.video.i_height != p_sys->i_crop_height ||
2263                 p_sys->i_crop_height != p_sys->i_nopadd_height ||
2264                 p_sys->i_nopadd_height != (int)id->p_encoder->fmt_out.video.i_height)
2265             {
2266                 id->pp_filter[id->i_filter] =
2267                     vlc_object_create( p_stream, VLC_OBJECT_FILTER );
2268                 vlc_object_attach( id->pp_filter[id->i_filter], p_stream );
2269
2270                 id->pp_filter[id->i_filter]->pf_vout_buffer_new =
2271                     video_new_buffer_filter;
2272                 id->pp_filter[id->i_filter]->pf_vout_buffer_del =
2273                     video_del_buffer_filter;
2274
2275                 id->pp_filter[id->i_filter]->fmt_in = id->p_decoder->fmt_out;
2276                 id->pp_filter[id->i_filter]->fmt_out = id->p_encoder->fmt_in;
2277                 id->pp_filter[id->i_filter]->p_cfg = NULL;
2278
2279                 id->pp_filter[id->i_filter]->fmt_in.video.i_x_offset = p_sys->i_src_x_offset;
2280                 id->pp_filter[id->i_filter]->fmt_in.video.i_y_offset = p_sys->i_src_y_offset;
2281                 id->pp_filter[id->i_filter]->fmt_in.video.i_visible_width = p_sys->i_crop_width;
2282                 id->pp_filter[id->i_filter]->fmt_in.video.i_visible_height = p_sys->i_crop_height;
2283
2284                 id->pp_filter[id->i_filter]->fmt_out.video.i_x_offset = p_sys->i_dst_x_offset;
2285                 id->pp_filter[id->i_filter]->fmt_out.video.i_y_offset = p_sys->i_dst_y_offset;
2286                 id->pp_filter[id->i_filter]->fmt_out.video.i_visible_width = p_sys->i_nopadd_width;
2287                 id->pp_filter[id->i_filter]->fmt_out.video.i_visible_height = p_sys->i_nopadd_height;
2288
2289                 id->pp_filter[id->i_filter]->p_module =
2290                     module_Need( id->pp_filter[id->i_filter],
2291                                  "crop padd", 0, 0 );
2292                 if( id->pp_filter[id->i_filter]->p_module )
2293                 {
2294                     id->pp_filter[id->i_filter]->p_owner =
2295                         malloc( sizeof(filter_owner_sys_t) );
2296                     for( i = 0; i < PICTURE_RING_SIZE; i++ )
2297                         id->pp_filter[id->i_filter]->p_owner->pp_pics[i] = 0;
2298                     id->pp_filter[id->i_filter]->p_owner->p_sys = p_sys;
2299
2300                     id->i_filter++;
2301                 }
2302                 else
2303                 {
2304                     msg_Dbg( p_stream, "no video filter found" );
2305                     vlc_object_detach( id->pp_filter[id->i_filter] );
2306                     vlc_object_destroy( id->pp_filter[id->i_filter] );
2307
2308                     p_pic->pf_release( p_pic );
2309                     transcode_video_close( p_stream, id );
2310                     id->b_transcode = VLC_FALSE;
2311                     return VLC_EGENERIC;
2312                 }
2313             }
2314
2315             for( i = 0; (i < p_sys->i_vfilters) && (id->i_ufilter < TRANSCODE_FILTERS); i++ )
2316             {
2317                 id->pp_ufilter[id->i_ufilter] =
2318                     vlc_object_create( p_stream, VLC_OBJECT_FILTER );
2319                 vlc_object_attach( id->pp_ufilter[id->i_ufilter], p_stream );
2320
2321                 id->pp_ufilter[id->i_ufilter]->pf_vout_buffer_new =
2322                     video_new_buffer_filter;
2323                 id->pp_ufilter[id->i_ufilter]->pf_vout_buffer_del =
2324                     video_del_buffer_filter;
2325
2326                 id->pp_ufilter[id->i_ufilter]->fmt_in = id->p_encoder->fmt_in;
2327                 id->pp_ufilter[id->i_ufilter]->fmt_out = id->p_encoder->fmt_in;
2328                 id->pp_ufilter[id->i_ufilter]->p_cfg = p_sys->p_vfilters_cfg[i];
2329                 id->pp_ufilter[id->i_ufilter]->p_module =
2330                     module_Need( id->pp_ufilter[id->i_ufilter],
2331                           "video filter2", p_sys->psz_vfilters[i], VLC_TRUE );
2332                 if( id->pp_ufilter[id->i_ufilter]->p_module )
2333                 {
2334                     id->pp_ufilter[id->i_ufilter]->p_owner =
2335                         malloc( sizeof(filter_owner_sys_t) );
2336                     for( i = 0; i < PICTURE_RING_SIZE; i++ )
2337                         id->pp_ufilter[id->i_ufilter]->p_owner->pp_pics[i] = 0;
2338                     id->pp_ufilter[id->i_ufilter]->p_owner->p_sys = p_sys;
2339                     id->i_ufilter++;
2340                 }
2341                 else
2342                 {
2343                     msg_Dbg( p_stream, "no video filter found" );
2344                     vlc_object_detach( id->pp_ufilter[id->i_ufilter] );
2345                     vlc_object_destroy( id->pp_ufilter[id->i_ufilter] );
2346                     id->pp_ufilter[id->i_ufilter] = NULL;
2347                 }
2348             }
2349         }
2350
2351         /* Run filter chain */
2352         for( i = 0; i < id->i_filter; i++ )
2353         {
2354             p_pic = id->pp_filter[i]->pf_video_filter(id->pp_filter[i], p_pic);
2355         }
2356
2357         /*
2358          * Encoding
2359          */
2360
2361         /* Check if we have a subpicture to overlay */
2362         if( p_sys->p_spu )
2363         {
2364             p_subpic = spu_SortSubpictures( p_sys->p_spu, p_pic->date,
2365                        VLC_FALSE /* Fixme: check if stream is paused */ );
2366             /* TODO: get another pic */
2367         }
2368
2369         /* Overlay subpicture */
2370         if( p_subpic )
2371         {
2372             int i_scale_width, i_scale_height;
2373             video_format_t *p_fmt;
2374
2375             i_scale_width = id->p_encoder->fmt_in.video.i_width * 1000 /
2376                 id->p_decoder->fmt_out.video.i_width;
2377             i_scale_height = id->p_encoder->fmt_in.video.i_height * 1000 /
2378                 id->p_decoder->fmt_out.video.i_height;
2379
2380             if( p_pic->i_refcount && !id->i_filter )
2381             {
2382                 /* We can't modify the picture, we need to duplicate it */
2383                 picture_t *p_tmp = video_new_buffer_decoder( id->p_decoder );
2384                 if( p_tmp )
2385                 {
2386                     vout_CopyPicture( p_stream, p_tmp, p_pic );
2387                     p_pic->pf_release( p_pic );
2388                     p_pic = p_tmp;
2389                 }
2390             }
2391
2392             if( id->i_filter )
2393                 p_fmt = &id->pp_filter[id->i_filter -1]->fmt_out.video;
2394             else
2395                 p_fmt = &id->p_decoder->fmt_out.video;
2396
2397             /* FIXME (shouldn't have to be done here) */
2398             p_fmt->i_sar_num = p_fmt->i_aspect *
2399                 p_fmt->i_height / p_fmt->i_width;
2400             p_fmt->i_sar_den = VOUT_ASPECT_FACTOR;
2401
2402             spu_RenderSubpictures( p_sys->p_spu, p_fmt, p_pic, p_pic, p_subpic,
2403                                    i_scale_width, i_scale_height );
2404         }
2405
2406         /* Run user specified filter chain */
2407         for( i = 0; i < id->i_ufilter; i++ )
2408         {
2409             p_pic = id->pp_ufilter[i]->pf_video_filter( id->pp_ufilter[i],
2410                                                         p_pic );
2411         }
2412
2413         if( p_sys->i_threads == 0 )
2414         {
2415             block_t *p_block;
2416             p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
2417             block_ChainAppend( out, p_block );
2418         }
2419
2420         if( p_sys->b_master_sync )
2421         {
2422             mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
2423             if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2424                   || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2425             {
2426                 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2427                 date_Set( &id->interpolated_pts, p_pic->date );
2428                 i_pts = p_pic->date + 1;
2429             }
2430             date_Increment( &id->interpolated_pts, 1 );
2431         }
2432
2433         if( p_sys->b_master_sync && i_duplicate > 1 )
2434         {
2435             mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
2436             if( (p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT)
2437                  || ((p_pic->date - i_pts) < -MASTER_SYNC_MAX_DRIFT) )
2438             {
2439                 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2440                 date_Set( &id->interpolated_pts, p_pic->date );
2441                 i_pts = p_pic->date + 1;
2442             }
2443             date_Increment( &id->interpolated_pts, 1 );
2444
2445             if( p_sys->i_threads >= 1 )
2446             {
2447                 /* We can't modify the picture, we need to duplicate it */
2448                 p_pic2 = video_new_buffer_decoder( id->p_decoder );
2449                 if( p_pic2 != NULL )
2450                 {
2451                     vout_CopyPicture( p_stream, p_pic2, p_pic );
2452                     p_pic2->date = i_pts;
2453                 }
2454             }
2455             else
2456             {
2457                 block_t *p_block;
2458                 p_pic->date = i_pts;
2459                 p_block = id->p_encoder->pf_encode_video(id->p_encoder, p_pic);
2460                 block_ChainAppend( out, p_block );
2461             }
2462         }
2463
2464         if( p_sys->i_threads == 0 )
2465         {
2466             p_pic->pf_release( p_pic );
2467         }
2468         else
2469         {
2470             vlc_mutex_lock( &p_sys->lock_out );
2471             p_sys->pp_pics[p_sys->i_last_pic++] = p_pic;
2472             p_sys->i_last_pic %= PICTURE_RING_SIZE;
2473             *out = p_sys->p_buffers;
2474             p_sys->p_buffers = NULL;
2475             if( p_pic2 != NULL )
2476             {
2477                 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic2;
2478                 p_sys->i_last_pic %= PICTURE_RING_SIZE;
2479             }
2480             vlc_cond_signal( &p_sys->cond );
2481             vlc_mutex_unlock( &p_sys->lock_out );
2482         }
2483     }
2484
2485     return VLC_SUCCESS;
2486 }
2487
2488 static int EncoderThread( sout_stream_sys_t *p_sys )
2489 {
2490     sout_stream_id_t *id = p_sys->id_video;
2491     picture_t *p_pic;
2492
2493     while( !p_sys->b_die && !p_sys->b_error )
2494     {
2495         block_t *p_block;
2496
2497         vlc_mutex_lock( &p_sys->lock_out );
2498         while( p_sys->i_last_pic == p_sys->i_first_pic )
2499         {
2500             vlc_cond_wait( &p_sys->cond, &p_sys->lock_out );
2501             if( p_sys->b_die || p_sys->b_error ) break;
2502         }
2503         if( p_sys->b_die || p_sys->b_error )
2504         {
2505             vlc_mutex_unlock( &p_sys->lock_out );
2506             break;
2507         }
2508
2509         p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2510         p_sys->i_first_pic %= PICTURE_RING_SIZE;
2511         vlc_mutex_unlock( &p_sys->lock_out );
2512
2513         p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
2514         vlc_mutex_lock( &p_sys->lock_out );
2515         block_ChainAppend( &p_sys->p_buffers, p_block );
2516
2517         vlc_mutex_unlock( &p_sys->lock_out );
2518         p_pic->pf_release( p_pic );
2519     }
2520
2521     while( p_sys->i_last_pic != p_sys->i_first_pic )
2522     {
2523         p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2524         p_sys->i_first_pic %= PICTURE_RING_SIZE;
2525         p_pic->pf_release( p_pic );
2526     }
2527     block_ChainRelease( p_sys->p_buffers );
2528
2529     return 0;
2530 }
2531
2532 struct picture_sys_t
2533 {
2534     vlc_object_t *p_owner;
2535 };
2536
2537 static void video_release_buffer( picture_t *p_pic )
2538 {
2539     if( p_pic && !p_pic->i_refcount && p_pic->pf_release && p_pic->p_sys )
2540     {
2541         video_del_buffer_decoder( (decoder_t *)p_pic->p_sys->p_owner, p_pic );
2542     }
2543     else if( p_pic && p_pic->i_refcount > 0 ) p_pic->i_refcount--;
2544 }
2545
2546 static picture_t *video_new_buffer( vlc_object_t *p_this, picture_t **pp_ring,
2547                                     sout_stream_sys_t *p_sys )
2548 {
2549     decoder_t *p_dec = (decoder_t *)p_this;
2550     picture_t *p_pic;
2551     int i;
2552
2553     /* Find an empty space in the picture ring buffer */
2554     for( i = 0; i < PICTURE_RING_SIZE; i++ )
2555     {
2556         if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
2557         {
2558             pp_ring[i]->i_status = RESERVED_PICTURE;
2559             return pp_ring[i];
2560         }
2561     }
2562     for( i = 0; i < PICTURE_RING_SIZE; i++ )
2563     {
2564         if( pp_ring[i] == 0 ) break;
2565     }
2566
2567     if( i == PICTURE_RING_SIZE && p_sys->i_threads >= 1 )
2568     {
2569         int i_first_pic = p_sys->i_first_pic;
2570
2571         if( p_sys->i_first_pic != p_sys->i_last_pic )
2572         {
2573             /* Encoder still has stuff to encode, wait to clear-up the list */
2574             while( p_sys->i_first_pic == i_first_pic )
2575                 msleep( 100000 );
2576         }
2577
2578         /* Find an empty space in the picture ring buffer */
2579         for( i = 0; i < PICTURE_RING_SIZE; i++ )
2580         {
2581             if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
2582             {
2583                 pp_ring[i]->i_status = RESERVED_PICTURE;
2584                 return pp_ring[i];
2585             }
2586         }
2587         for( i = 0; i < PICTURE_RING_SIZE; i++ )
2588         {
2589             if( pp_ring[i] == 0 ) break;
2590         }
2591     }
2592
2593     if( i == PICTURE_RING_SIZE )
2594     {
2595         msg_Err( p_this, "decoder/filter is leaking pictures, "
2596                  "resetting its ring buffer" );
2597
2598         for( i = 0; i < PICTURE_RING_SIZE; i++ )
2599         {
2600             pp_ring[i]->pf_release( pp_ring[i] );
2601         }
2602
2603         i = 0;
2604     }
2605
2606     p_pic = malloc( sizeof(picture_t) );
2607     if( !p_pic ) return NULL;
2608     p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
2609     vout_AllocatePicture( VLC_OBJECT(p_dec), p_pic,
2610                           p_dec->fmt_out.video.i_chroma,
2611                           p_dec->fmt_out.video.i_width,
2612                           p_dec->fmt_out.video.i_height,
2613                           p_dec->fmt_out.video.i_aspect );
2614
2615     if( !p_pic->i_planes )
2616     {
2617         free( p_pic );
2618         return NULL;
2619     }
2620
2621     p_pic->pf_release = video_release_buffer;
2622     p_pic->p_sys = malloc( sizeof(picture_sys_t) );
2623     if( !p_pic->p_sys )
2624     {
2625         free( p_pic );
2626         return NULL;
2627     }
2628
2629     p_pic->p_sys->p_owner = p_this;
2630     p_pic->i_status = RESERVED_PICTURE;
2631
2632     pp_ring[i] = p_pic;
2633     return p_pic;
2634 }
2635
2636 static picture_t *video_new_buffer_decoder( decoder_t *p_dec )
2637 {
2638     return video_new_buffer( VLC_OBJECT(p_dec),
2639                              p_dec->p_owner->pp_pics, p_dec->p_owner->p_sys );
2640 }
2641
2642 static picture_t *video_new_buffer_filter( filter_t *p_filter )
2643 {
2644     return video_new_buffer( VLC_OBJECT(p_filter),
2645                              p_filter->p_owner->pp_pics,
2646                              p_filter->p_owner->p_sys );
2647 }
2648
2649 static void video_del_buffer( vlc_object_t *p_this, picture_t *p_pic )
2650 {
2651     if( p_pic && p_pic->p_data_orig ) free( p_pic->p_data_orig );
2652     if( p_pic && p_pic->p_sys ) free( p_pic->p_sys );
2653     if( p_pic ) free( p_pic );
2654 }
2655
2656 static void video_del_buffer_decoder( decoder_t *p_decoder, picture_t *p_pic )
2657 {
2658     p_pic->i_refcount = 0;
2659     p_pic->i_status = DESTROYED_PICTURE;
2660 }
2661
2662 static void video_del_buffer_filter( filter_t *p_filter, picture_t *p_pic )
2663 {
2664     p_pic->i_refcount = 0;
2665     p_pic->i_status = DESTROYED_PICTURE;
2666 }
2667
2668 static void video_link_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2669 {
2670     p_pic->i_refcount++;
2671 }
2672
2673 static void video_unlink_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2674 {
2675     video_release_buffer( p_pic );
2676 }
2677
2678 /*
2679  * SPU
2680  */
2681 static subpicture_t *spu_new_buffer( decoder_t * );
2682 static void spu_del_buffer( decoder_t *, subpicture_t * );
2683
2684 static int transcode_spu_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2685 {
2686     sout_stream_sys_t *p_sys = p_stream->p_sys;
2687
2688     /*
2689      * Open decoder
2690      */
2691
2692     /* Initialization of decoder structures */
2693     id->p_decoder->pf_decode_sub = NULL;
2694     id->p_decoder->pf_spu_buffer_new = spu_new_buffer;
2695     id->p_decoder->pf_spu_buffer_del = spu_del_buffer;
2696     id->p_decoder->p_owner = (decoder_owner_sys_t *)p_stream;
2697     /* id->p_decoder->p_cfg = p_sys->p_spu_cfg; */
2698
2699     id->p_decoder->p_module =
2700         module_Need( id->p_decoder, "decoder", "$codec", 0 );
2701
2702     if( !id->p_decoder->p_module )
2703     {
2704         msg_Err( p_stream, "cannot find decoder" );
2705         return VLC_EGENERIC;
2706     }
2707
2708     if( !p_sys->b_soverlay )
2709     {
2710         /* Open encoder */
2711         /* Initialization of encoder format structures */
2712         es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
2713                         id->p_decoder->fmt_in.i_codec );
2714
2715         id->p_encoder->p_cfg = p_sys->p_spu_cfg;
2716
2717         id->p_encoder->p_module =
2718             module_Need( id->p_encoder, "encoder", p_sys->psz_senc, VLC_TRUE );
2719
2720         if( !id->p_encoder->p_module )
2721         {
2722             module_Unneed( id->p_decoder, id->p_decoder->p_module );
2723             msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_senc );
2724             return VLC_EGENERIC;
2725         }
2726     }
2727
2728     if( !p_sys->p_spu )
2729     {
2730         p_sys->p_spu = spu_Create( p_stream );
2731         spu_Init( p_sys->p_spu );
2732     }
2733
2734     return VLC_SUCCESS;
2735 }
2736
2737 static void transcode_spu_close( sout_stream_t *p_stream, sout_stream_id_t *id)
2738 {
2739     /* Close decoder */
2740     if( id->p_decoder->p_module )
2741         module_Unneed( id->p_decoder, id->p_decoder->p_module );
2742
2743     /* Close encoder */
2744     if( id->p_encoder->p_module )
2745         module_Unneed( id->p_encoder, id->p_encoder->p_module );
2746 }
2747
2748 static int transcode_spu_process( sout_stream_t *p_stream,
2749                                   sout_stream_id_t *id,
2750                                   block_t *in, block_t **out )
2751 {
2752     sout_stream_sys_t *p_sys = p_stream->p_sys;
2753     subpicture_t *p_subpic;
2754     *out = NULL;
2755
2756     p_subpic = id->p_decoder->pf_decode_sub( id->p_decoder, &in );
2757     if( !p_subpic )
2758         return VLC_EGENERIC;
2759
2760     sout_UpdateStatistic( p_stream->p_sout, SOUT_STATISTIC_DECODED_SUBTITLE, 1 );
2761
2762     if( p_sys->b_master_sync && p_sys->i_master_drift )
2763     {
2764         p_subpic->i_start -= p_sys->i_master_drift;
2765         if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2766     }
2767
2768     if( p_sys->b_soverlay )
2769     {
2770         spu_DisplaySubpicture( p_sys->p_spu, p_subpic );
2771     }
2772     else
2773     {
2774         block_t *p_block;
2775
2776         p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
2777         spu_del_buffer( id->p_decoder, p_subpic );
2778         if( p_block )
2779         {
2780             block_ChainAppend( out, p_block );
2781             return VLC_SUCCESS;
2782         }
2783     }
2784
2785     return VLC_EGENERIC;
2786 }
2787
2788 static subpicture_t *spu_new_buffer( decoder_t *p_dec )
2789 {
2790     sout_stream_t *p_stream = (sout_stream_t *)p_dec->p_owner;
2791     return spu_CreateSubpicture( p_stream->p_sys->p_spu );
2792 }
2793
2794 static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_subpic )
2795 {
2796     sout_stream_t *p_stream = (sout_stream_t *)p_dec->p_owner;
2797     spu_DestroySubpicture( p_stream->p_sys->p_spu, p_subpic );
2798 }
2799
2800 /*
2801  * OSD menu
2802  */
2803 static int transcode_osd_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2804 {
2805     sout_stream_sys_t *p_sys = p_stream->p_sys;
2806
2807     id->p_decoder->fmt_in.i_cat = SPU_ES;
2808     id->p_encoder->fmt_out.psz_language = strdup( "osd" );
2809
2810     if( p_sys->i_osdcodec != 0 || p_sys->psz_osdenc )
2811     {
2812         msg_Dbg( p_stream, "creating osdmenu transcoding from fcc=`%4.4s' "
2813                  "to fcc=`%4.4s'", (char*)&id->p_encoder->fmt_out.i_codec,
2814                  (char*)&p_sys->i_osdcodec );
2815
2816         /* Complete destination format */
2817         id->p_encoder->fmt_out.i_codec = p_sys->i_osdcodec;
2818
2819         /* Open encoder */
2820         es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
2821                         VLC_FOURCC('Y','U','V','A') );
2822         id->p_encoder->fmt_in.psz_language = strdup( "osd" );
2823
2824         id->p_encoder->p_cfg = p_sys->p_osd_cfg;
2825
2826         id->p_encoder->p_module =
2827             module_Need( id->p_encoder, "encoder", p_sys->psz_osdenc, VLC_TRUE );
2828
2829         if( !id->p_encoder->p_module )
2830         {
2831             msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_osdenc );
2832             goto error;
2833         }
2834
2835         /* open output stream */
2836         id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
2837         id->b_transcode = VLC_TRUE;
2838
2839         if( !id->id ) goto error;
2840     }
2841     else
2842     {
2843         msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
2844                  (char*)&id->p_decoder->fmt_out.i_codec );
2845         id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_decoder->fmt_out );
2846         id->b_transcode = VLC_FALSE;
2847
2848         if( !id->id ) goto error;
2849     }
2850
2851     if( !p_sys->p_spu )
2852     {
2853         p_sys->p_spu = spu_Create( p_stream );
2854         spu_Init( p_sys->p_spu );
2855     }
2856
2857     return VLC_SUCCESS;
2858
2859  error:
2860     msg_Err( p_stream, "starting osd encoding thread failed" );
2861     if( id->p_encoder->p_module )
2862             module_Unneed( id->p_encoder, id->p_encoder->p_module );
2863     p_sys->b_osd = VLC_FALSE;
2864     return VLC_EGENERIC;
2865 }
2866
2867 static void transcode_osd_close( sout_stream_t *p_stream, sout_stream_id_t *id)
2868 {
2869     sout_stream_sys_t *p_sys = p_stream->p_sys;
2870
2871     /* Close encoder */
2872     if( p_sys->b_osd && id )
2873     {
2874         if( id->p_encoder->p_module )
2875             module_Unneed( id->p_encoder, id->p_encoder->p_module );
2876     }
2877     p_sys->b_osd = VLC_FALSE;
2878 }
2879
2880 static int transcode_osd_process( sout_stream_t *p_stream,
2881                                   sout_stream_id_t *id,
2882                                   block_t *in, block_t **out )
2883 {
2884     sout_stream_sys_t *p_sys = p_stream->p_sys;
2885     subpicture_t *p_subpic = NULL;
2886
2887     /* Check if we have a subpicture to send */
2888     if( p_sys->p_spu && in->i_dts > 0)
2889     {
2890         p_subpic = spu_SortSubpictures( p_sys->p_spu, in->i_dts, VLC_FALSE );
2891     }
2892     else
2893     {
2894         msg_Warn( p_stream, "spu channel not initialized, doing it now" );
2895         if( !p_sys->p_spu )
2896         {
2897             p_sys->p_spu = spu_Create( p_stream );
2898             spu_Init( p_sys->p_spu );
2899         }
2900     }
2901
2902     if( p_subpic )
2903     {
2904         block_t *p_block = NULL;
2905
2906         if( p_sys->b_master_sync && p_sys->i_master_drift )
2907         {
2908             p_subpic->i_start -= p_sys->i_master_drift;
2909             if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2910         }
2911
2912         p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
2913         spu_DestroySubpicture( p_sys->p_spu, p_subpic );
2914         if( p_block )
2915         {
2916             p_block->i_dts = p_block->i_pts = in->i_dts;
2917             block_ChainAppend( out, p_block );
2918             return VLC_SUCCESS;
2919         }
2920     }
2921     return VLC_EGENERIC;
2922 }