]> git.sesse.net Git - vlc/blob - modules/stream_out/transcode.c
Added sout_UpdateStatistic and fixed transcode module to use it.
[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_cat( SOUT_CFG_PREFIX "afilter", SUBCAT_AUDIO_MISC,
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_cat( SOUT_CFG_PREFIX "sfilter", SUBCAT_VIDEO_SUBPIC,
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 filter_t *transcode_audio_filter_new( sout_stream_t *p_stream,
1268                                              sout_stream_id_t *id,
1269                                              es_format_t *p_fmt_in,
1270                                              es_format_t *p_fmt_out,
1271                                              char *psz_name )
1272 {
1273     sout_stream_sys_t *p_sys = p_stream->p_sys;
1274     filter_t *p_filter = vlc_object_create( p_stream, VLC_OBJECT_FILTER );
1275
1276     vlc_object_attach( p_filter, p_stream );
1277     p_filter->pf_audio_buffer_new = (block_t* (*) (filter_t*, int))__block_New;
1278
1279     p_filter->fmt_in = *p_fmt_in;
1280     p_filter->fmt_out = *p_fmt_out;
1281     if( psz_name )
1282         p_filter->p_cfg = p_sys->p_afilters_cfg[id->i_ufilter];
1283
1284     p_filter->p_module = module_Need( p_filter, "audio filter2", psz_name,
1285                                       VLC_TRUE );
1286     if( p_filter->p_module )
1287     {
1288         p_filter->fmt_out.audio.i_bitspersample =
1289             audio_BitsPerSample( p_filter->fmt_out.i_codec );
1290         *p_fmt_in = p_filter->fmt_out;
1291     }
1292     else
1293     {
1294         vlc_object_detach( p_filter );
1295         vlc_object_destroy( p_filter );
1296         p_filter = 0;
1297     }
1298
1299     return p_filter;
1300 }
1301
1302 static int transcode_audio_new( sout_stream_t *p_stream,
1303                                 sout_stream_id_t *id )
1304 {
1305     sout_stream_sys_t *p_sys = p_stream->p_sys;
1306     es_format_t fmt_last;
1307     int i;
1308
1309     /*
1310      * Open decoder
1311      */
1312
1313     /* Initialization of decoder structures */
1314     id->p_decoder->fmt_out = id->p_decoder->fmt_in;
1315     id->p_decoder->fmt_out.i_extra = 0;
1316     id->p_decoder->fmt_out.p_extra = 0;
1317     id->p_decoder->pf_decode_audio = NULL;
1318     id->p_decoder->pf_aout_buffer_new = audio_new_buffer;
1319     id->p_decoder->pf_aout_buffer_del = audio_del_buffer;
1320     /* id->p_decoder->p_cfg = p_sys->p_audio_cfg; */
1321
1322     id->p_decoder->p_module =
1323         module_Need( id->p_decoder, "decoder", "$codec", 0 );
1324     if( !id->p_decoder->p_module )
1325     {
1326         msg_Err( p_stream, "cannot find decoder" );
1327         return VLC_EGENERIC;
1328     }
1329     id->p_decoder->fmt_out.audio.i_bitspersample =
1330         audio_BitsPerSample( id->p_decoder->fmt_out.i_codec );
1331     fmt_last = id->p_decoder->fmt_out;
1332     /* Fix AAC SBR changing number of channels and sampling rate */
1333     if( !(id->p_decoder->fmt_in.i_codec == VLC_FOURCC('m','p','4','a') &&
1334         fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate &&
1335         fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels) )
1336         fmt_last.audio.i_rate = id->p_decoder->fmt_in.audio.i_rate;
1337
1338     /*
1339      * Open encoder
1340      */
1341
1342     /* Initialization of encoder format structures */
1343     es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1344                     id->p_decoder->fmt_out.i_codec );
1345     id->p_encoder->fmt_in.audio.i_format = id->p_decoder->fmt_out.i_codec;
1346
1347     /* Initialization of encoder format structures */
1348     es_format_Init( &id->p_encoder->fmt_in, AUDIO_ES, VLC_FOURCC('f','l','3','2') );
1349     id->p_encoder->fmt_in.audio.i_format = VLC_FOURCC('f','l','3','2');
1350
1351     id->p_encoder->fmt_in.audio.i_rate = id->p_encoder->fmt_out.audio.i_rate;
1352     id->p_encoder->fmt_in.audio.i_physical_channels =
1353         id->p_encoder->fmt_out.audio.i_physical_channels;
1354     id->p_encoder->fmt_in.audio.i_original_channels =
1355         id->p_encoder->fmt_out.audio.i_original_channels;
1356     id->p_encoder->fmt_in.audio.i_channels =
1357         id->p_encoder->fmt_out.audio.i_channels;
1358     id->p_encoder->fmt_in.audio.i_bitspersample =
1359         audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1360
1361     id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
1362     id->p_encoder->p_module =
1363         module_Need( id->p_encoder, "encoder", p_sys->psz_aenc, VLC_TRUE );
1364     if( !id->p_encoder->p_module )
1365     {
1366         msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_aenc );
1367         module_Unneed( id->p_decoder, id->p_decoder->p_module );
1368         id->p_decoder->p_module = NULL;
1369         return VLC_EGENERIC;
1370     }
1371     id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
1372     id->p_encoder->fmt_in.audio.i_bitspersample =
1373         audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1374
1375     /* Fix AAC SBR changing number of channels and sampling rate */
1376     if( id->p_decoder->fmt_in.i_codec == VLC_FOURCC('m','p','4','a') &&
1377         fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate &&
1378         fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels )
1379     {
1380       id->p_encoder->fmt_in.audio.i_rate = fmt_last.audio.i_rate;
1381       id->p_encoder->fmt_out.audio.i_rate = fmt_last.audio.i_rate;
1382     }
1383
1384     /* Load conversion filters */
1385     if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels ||
1386         fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate )
1387     {
1388         /* We'll have to go through fl32 first */
1389         es_format_t fmt_out = id->p_encoder->fmt_in;
1390         fmt_out.i_codec = fmt_out.audio.i_format = VLC_FOURCC('f','l','3','2');
1391
1392         id->pp_filter[id->i_filter] =
1393             transcode_audio_filter_new( p_stream, id, &fmt_last, &fmt_out, NULL );
1394
1395         if( id->pp_filter[id->i_filter] ) id->i_filter++;
1396     }
1397
1398     for( i = 0; i < TRANSCODE_FILTERS; i++ )
1399     {
1400         if( (fmt_last.audio.i_channels !=
1401             id->p_encoder->fmt_in.audio.i_channels) ||
1402             (fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate) ||
1403             (fmt_last.i_codec != id->p_encoder->fmt_in.i_codec) )
1404         {
1405             id->pp_filter[id->i_filter] =
1406                 transcode_audio_filter_new( p_stream, id, &fmt_last,
1407                                             &id->p_encoder->fmt_in, NULL );
1408
1409             if( id->pp_filter[id->i_filter] )
1410                 id->i_filter++;
1411             else
1412                 break;
1413         }
1414     }
1415
1416     /* Final checks to see if conversions were successful */
1417     if( fmt_last.i_codec != id->p_encoder->fmt_in.i_codec )
1418     {
1419         msg_Err( p_stream, "no audio filter found (%4.4s->%4.4s)",
1420                  (char *)&fmt_last.i_codec,
1421                  (char *)&id->p_encoder->fmt_in.i_codec );
1422         transcode_audio_close( p_stream, id );
1423         return VLC_EGENERIC;
1424     }
1425
1426     /* Load user specified audio filters now */
1427     for( i = 0; (i < p_sys->i_afilters) &&
1428                 (id->i_ufilter < TRANSCODE_FILTERS); i++ )
1429     {
1430         id->pp_ufilter[id->i_ufilter] =
1431             transcode_audio_filter_new( p_stream, id, &fmt_last,
1432                                         &id->p_encoder->fmt_in,
1433                                         p_sys->psz_afilters[i] );
1434
1435         if( id->pp_ufilter[id->i_ufilter] )
1436             id->i_ufilter++;
1437         else
1438             break;
1439     }
1440
1441     if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels )
1442     {
1443 #if 1
1444         module_Unneed( id->p_encoder, id->p_encoder->p_module );
1445         id->p_encoder->p_module = NULL;
1446
1447         /* This might work, but only if the encoder is restarted */
1448         id->p_encoder->fmt_in.audio.i_channels = fmt_last.audio.i_channels;
1449         id->p_encoder->fmt_out.audio.i_channels = fmt_last.audio.i_channels;
1450
1451         id->p_encoder->fmt_in.audio.i_physical_channels =
1452             id->p_encoder->fmt_in.audio.i_original_channels =
1453                 fmt_last.audio.i_physical_channels;
1454         id->p_encoder->fmt_out.audio.i_physical_channels =
1455             id->p_encoder->fmt_out.audio.i_original_channels =
1456                 fmt_last.audio.i_physical_channels;
1457
1458         msg_Dbg( p_stream, "number of audio channels for mixing changed, "
1459                  "trying to reopen the encoder for mixing %i to %i channels",
1460                  fmt_last.audio.i_channels,
1461                  id->p_encoder->fmt_in.audio.i_channels );
1462
1463         /* reload encoder */
1464         id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
1465         id->p_encoder->p_module =
1466             module_Need( id->p_encoder, "encoder", p_sys->psz_aenc, VLC_TRUE );
1467         if( !id->p_encoder->p_module )
1468         {
1469             msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_aenc );
1470             transcode_audio_close( p_stream, id );
1471             return VLC_EGENERIC;
1472         }
1473         id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
1474         id->p_encoder->fmt_in.audio.i_bitspersample =
1475             audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1476 #else
1477         msg_Err( p_stream, "no audio filter found for mixing from"
1478                  " %i to %i channels", fmt_last.audio.i_channels,
1479                  id->p_encoder->fmt_in.audio.i_channels );
1480
1481         transcode_audio_close( p_stream, id );
1482         return VLC_EGENERIC;
1483 #endif
1484     }
1485
1486     if( fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate )
1487     {
1488         msg_Err( p_stream, "no audio filter found for resampling from"
1489                  " %iHz to %iHz", fmt_last.audio.i_rate,
1490                  id->p_encoder->fmt_in.audio.i_rate );
1491 #if 0
1492         /* FIXME : this might work, but only if the encoder is restarted */
1493         id->p_encoder->fmt_in.audio.i_rate = fmt_last.audio.i_rate;
1494         id->p_encoder->fmt_out.audio.i_rate = fmt_last.audio.i_rate;
1495 #else
1496         transcode_audio_close( p_stream, id );
1497         return VLC_EGENERIC;
1498 #endif
1499     }
1500
1501     /* FIXME: Hack for mp3 transcoding support */
1502     if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC( 'm','p','3',' ' ) )
1503         id->p_encoder->fmt_out.i_codec = VLC_FOURCC( 'm','p','g','a' );
1504
1505     return VLC_SUCCESS;
1506 }
1507
1508 static void transcode_audio_close( sout_stream_t *p_stream,
1509                                    sout_stream_id_t *id )
1510 {
1511     int i;
1512
1513     /* Close decoder */
1514     if( id->p_decoder->p_module )
1515         module_Unneed( id->p_decoder, id->p_decoder->p_module );
1516     id->p_decoder->p_module = NULL;
1517
1518     /* Close encoder */
1519     if( id->p_encoder->p_module )
1520         module_Unneed( id->p_encoder, id->p_encoder->p_module );
1521     id->p_encoder->p_module = NULL;
1522
1523     /* Close filters */
1524     for( i = 0; i < id->i_filter; i++ )
1525     {
1526         vlc_object_detach( id->pp_filter[i] );
1527         if( id->pp_filter[i]->p_module )
1528             module_Unneed( id->pp_filter[i], id->pp_filter[i]->p_module );
1529         vlc_object_destroy( id->pp_filter[i] );
1530     }
1531     for( i = 0; i < id->i_ufilter; i++ )
1532     {
1533         vlc_object_detach( id->pp_ufilter[i] );
1534         if( id->pp_ufilter[i]->p_module )
1535             module_Unneed( id->pp_ufilter[i], id->pp_ufilter[i]->p_module );
1536         vlc_object_destroy( id->pp_ufilter[i] );
1537     }
1538 }
1539
1540 static int transcode_audio_process( sout_stream_t *p_stream,
1541                                     sout_stream_id_t *id,
1542                                     block_t *in, block_t **out )
1543 {
1544     sout_stream_sys_t *p_sys = p_stream->p_sys;
1545     aout_buffer_t *p_audio_buf;
1546     block_t *p_block, *p_audio_block;
1547     int i;
1548     *out = NULL;
1549
1550     while( (p_audio_buf = id->p_decoder->pf_decode_audio( id->p_decoder,
1551                                                           &in )) )
1552     {
1553         sout_UpdateStatistic( p_stream->p_sout, SOUT_STATISTIC_DECODED_AUDIO, 1 );
1554         if( p_sys->b_master_sync )
1555         {
1556             mtime_t i_dts = date_Get( &id->interpolated_pts ) + 1;
1557             if ( p_audio_buf->start_date - i_dts > MASTER_SYNC_MAX_DRIFT
1558                   || p_audio_buf->start_date - i_dts < -MASTER_SYNC_MAX_DRIFT )
1559             {
1560                 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
1561                 date_Set( &id->interpolated_pts, p_audio_buf->start_date );
1562                 i_dts = p_audio_buf->start_date + 1;
1563             }
1564             p_sys->i_master_drift = p_audio_buf->start_date - i_dts;
1565             date_Increment( &id->interpolated_pts, p_audio_buf->i_nb_samples );
1566             p_audio_buf->start_date -= p_sys->i_master_drift;
1567             p_audio_buf->end_date -= p_sys->i_master_drift;
1568         }
1569
1570         p_audio_block = p_audio_buf->p_sys;
1571         p_audio_block->i_buffer = p_audio_buf->i_nb_bytes;
1572         p_audio_block->i_dts = p_audio_block->i_pts =
1573             p_audio_buf->start_date;
1574         p_audio_block->i_length = p_audio_buf->end_date -
1575             p_audio_buf->start_date;
1576         p_audio_block->i_samples = p_audio_buf->i_nb_samples;
1577
1578         /* Run filter chain */
1579         for( i = 0; i < id->i_filter; i++ )
1580         {
1581             p_audio_block =
1582                 id->pp_filter[i]->pf_audio_filter( id->pp_filter[i],
1583                                                    p_audio_block );
1584         }
1585
1586         /* Run user specified filter chain */
1587         for( i = 0; i < id->i_ufilter; i++ )
1588         {
1589             p_audio_block =
1590                 id->pp_ufilter[i]->pf_audio_filter( id->pp_ufilter[i],
1591                                                     p_audio_block );
1592         }
1593
1594         p_audio_buf->p_buffer = p_audio_block->p_buffer;
1595         p_audio_buf->i_nb_bytes = p_audio_block->i_buffer;
1596         p_audio_buf->i_nb_samples = p_audio_block->i_samples;
1597         p_audio_buf->start_date = p_audio_block->i_dts;
1598         p_audio_buf->end_date = p_audio_block->i_dts + p_audio_block->i_length;
1599
1600         p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf );
1601         block_ChainAppend( out, p_block );
1602         block_Release( p_audio_block );
1603         free( p_audio_buf );
1604     }
1605
1606     return VLC_SUCCESS;
1607 }
1608
1609 static void audio_release_buffer( aout_buffer_t *p_buffer )
1610 {
1611     if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
1612     if( p_buffer ) free( p_buffer );
1613 }
1614
1615 static aout_buffer_t *audio_new_buffer( decoder_t *p_dec, int i_samples )
1616 {
1617     aout_buffer_t *p_buffer;
1618     block_t *p_block;
1619     int i_size;
1620
1621     if( p_dec->fmt_out.audio.i_bitspersample )
1622     {
1623         i_size = i_samples * p_dec->fmt_out.audio.i_bitspersample / 8 *
1624             p_dec->fmt_out.audio.i_channels;
1625     }
1626     else if( p_dec->fmt_out.audio.i_bytes_per_frame &&
1627              p_dec->fmt_out.audio.i_frame_length )
1628     {
1629         i_size = i_samples * p_dec->fmt_out.audio.i_bytes_per_frame /
1630             p_dec->fmt_out.audio.i_frame_length;
1631     }
1632     else
1633     {
1634         i_size = i_samples * 4 * p_dec->fmt_out.audio.i_channels;
1635     }
1636
1637     p_buffer = malloc( sizeof(aout_buffer_t) );
1638     if( !p_buffer ) return NULL;
1639     p_buffer->b_discontinuity = VLC_FALSE;
1640     p_buffer->pf_release = audio_release_buffer;
1641     p_buffer->p_sys = p_block = block_New( p_dec, i_size );
1642
1643     p_buffer->p_buffer = p_block->p_buffer;
1644     p_buffer->i_size = p_buffer->i_nb_bytes = p_block->i_buffer;
1645     p_buffer->i_nb_samples = i_samples;
1646     p_block->i_samples = i_samples;
1647
1648     return p_buffer;
1649 }
1650
1651 static void audio_del_buffer( decoder_t *p_dec, aout_buffer_t *p_buffer )
1652 {
1653     if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
1654     if( p_buffer ) free( p_buffer );
1655 }
1656
1657 /*
1658  * video
1659  */
1660 static int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_t *id )
1661 {
1662     sout_stream_sys_t *p_sys = p_stream->p_sys;
1663     int i;
1664
1665     /* Open decoder
1666      * Initialization of decoder structures
1667      */
1668     id->p_decoder->fmt_out = id->p_decoder->fmt_in;
1669     id->p_decoder->fmt_out.i_extra = 0;
1670     id->p_decoder->fmt_out.p_extra = 0;
1671     id->p_decoder->pf_decode_video = NULL;
1672     id->p_decoder->pf_get_cc = NULL;
1673     id->p_decoder->pf_get_cc = 0;
1674     id->p_decoder->pf_vout_buffer_new = video_new_buffer_decoder;
1675     id->p_decoder->pf_vout_buffer_del = video_del_buffer_decoder;
1676     id->p_decoder->pf_picture_link    = video_link_picture_decoder;
1677     id->p_decoder->pf_picture_unlink  = video_unlink_picture_decoder;
1678     id->p_decoder->p_owner = malloc( sizeof(decoder_owner_sys_t) );
1679     for( i = 0; i < PICTURE_RING_SIZE; i++ )
1680         id->p_decoder->p_owner->pp_pics[i] = 0;
1681     id->p_decoder->p_owner->p_sys = p_sys;
1682     /* id->p_decoder->p_cfg = p_sys->p_video_cfg; */
1683
1684     id->p_decoder->p_module =
1685         module_Need( id->p_decoder, "decoder", "$codec", 0 );
1686
1687     if( !id->p_decoder->p_module )
1688     {
1689         msg_Err( p_stream, "cannot find decoder" );
1690         return VLC_EGENERIC;
1691     }
1692
1693     /*
1694      * Open encoder.
1695      * Because some info about the decoded input will only be available
1696      * once the first frame is decoded, we actually only test the availability
1697      * of the encoder here.
1698      */
1699
1700     /* Initialization of encoder format structures */
1701     es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1702                     id->p_decoder->fmt_out.i_codec );
1703     id->p_encoder->fmt_in.video.i_chroma = id->p_decoder->fmt_out.i_codec;
1704
1705     /* The dimensions will be set properly later on.
1706      * Just put sensible values so we can test an encoder is available. */
1707     id->p_encoder->fmt_in.video.i_width =
1708         id->p_encoder->fmt_out.video.i_width ?
1709         id->p_encoder->fmt_out.video.i_width :
1710         id->p_decoder->fmt_in.video.i_width ?
1711         id->p_decoder->fmt_in.video.i_width : 16;
1712     id->p_encoder->fmt_in.video.i_height =
1713         id->p_encoder->fmt_out.video.i_height ?
1714         id->p_encoder->fmt_out.video.i_height :
1715         id->p_decoder->fmt_in.video.i_height ?
1716         id->p_decoder->fmt_in.video.i_height : 16;
1717     id->p_encoder->fmt_in.video.i_frame_rate = 25;
1718     id->p_encoder->fmt_in.video.i_frame_rate_base = 1;
1719
1720     id->p_encoder->i_threads = p_sys->i_threads;
1721     id->p_encoder->p_cfg = p_sys->p_video_cfg;
1722
1723     id->p_encoder->p_module =
1724         module_Need( id->p_encoder, "encoder", p_sys->psz_venc, VLC_TRUE );
1725     if( !id->p_encoder->p_module )
1726     {
1727         msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_venc );
1728         module_Unneed( id->p_decoder, id->p_decoder->p_module );
1729         id->p_decoder->p_module = 0;
1730         return VLC_EGENERIC;
1731     }
1732
1733     /* Close the encoder.
1734      * We'll open it only when we have the first frame. */
1735     module_Unneed( id->p_encoder, id->p_encoder->p_module );
1736     if( id->p_encoder->fmt_out.p_extra )
1737     {
1738         free( id->p_encoder->fmt_out.p_extra );
1739         id->p_encoder->fmt_out.p_extra = NULL;
1740         id->p_encoder->fmt_out.i_extra = 0;
1741     }
1742     id->p_encoder->p_module = NULL;
1743
1744     if( p_sys->i_threads >= 1 )
1745     {
1746         int i_priority = p_sys->b_high_priority ? VLC_THREAD_PRIORITY_OUTPUT :
1747                            VLC_THREAD_PRIORITY_VIDEO;
1748         p_sys->id_video = id;
1749         vlc_mutex_init( p_stream, &p_sys->lock_out );
1750         vlc_cond_init( p_stream, &p_sys->cond );
1751         memset( p_sys->pp_pics, 0, sizeof(p_sys->pp_pics) );
1752         p_sys->i_first_pic = 0;
1753         p_sys->i_last_pic = 0;
1754         p_sys->p_buffers = NULL;
1755         p_sys->b_die = p_sys->b_error = 0;
1756         if( vlc_thread_create( p_sys, "encoder", EncoderThread, i_priority,
1757                                VLC_FALSE ) )
1758         {
1759             msg_Err( p_stream, "cannot spawn encoder thread" );
1760             module_Unneed( id->p_decoder, id->p_decoder->p_module );
1761             id->p_decoder->p_module = 0;
1762             return VLC_EGENERIC;
1763         }
1764     }
1765
1766     return VLC_SUCCESS;
1767 }
1768
1769 static int transcode_video_encoder_open( sout_stream_t *p_stream,
1770                                          sout_stream_id_t *id )
1771 {
1772     sout_stream_sys_t *p_sys = p_stream->p_sys;
1773
1774      /* Calculate scaling, padding, cropping etc. */
1775      /* width/height of source */
1776      int i_src_width = id->p_decoder->fmt_out.video.i_width;
1777      int i_src_height = id->p_decoder->fmt_out.video.i_height;
1778
1779      /* with/height scaling */
1780      float f_scale_width = 1;
1781      float f_scale_height = 1;
1782
1783      /* width/height of output stream */
1784      int i_dst_width;
1785      int i_dst_height;
1786
1787      /* aspect ratio */
1788      float f_aspect = (float)id->p_decoder->fmt_out.video.i_aspect /
1789                              VOUT_ASPECT_FACTOR;
1790
1791      msg_Dbg( p_stream, "decoder aspect is %i:%i",
1792                   id->p_decoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
1793
1794      /* Change f_aspect from source frame to source pixel */
1795      f_aspect = f_aspect * i_src_height / i_src_width;
1796      msg_Dbg( p_stream, "source pixel aspect is %f:1", f_aspect );
1797
1798      /* width/height after cropping */
1799      p_sys->i_src_x_offset = p_sys->i_crop_left & ~1;
1800      p_sys->i_src_y_offset = p_sys->i_crop_top & ~1;
1801      p_sys->i_crop_width = i_src_width - ( p_sys->i_crop_left & ~1 ) -
1802                             ( p_sys->i_crop_right & ~1 );
1803      p_sys->i_crop_height = i_src_height - ( p_sys->i_crop_top & ~1 ) -
1804                             ( p_sys->i_crop_bottom & ~1 );
1805
1806     /* Calculate scaling factor for specified parameters */
1807     if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1808         id->p_encoder->fmt_out.video.i_height <= 0 && p_sys->f_scale )
1809     {
1810         /* Global scaling. Make sure width will remain a factor of 16 */
1811         float f_real_scale;
1812         int  i_new_height;
1813         int i_new_width = i_src_width * p_sys->f_scale;
1814
1815         if( i_new_width % 16 <= 7 && i_new_width >= 16 )
1816             i_new_width -= i_new_width % 16;
1817         else
1818             i_new_width += 16 - i_new_width % 16;
1819
1820         f_real_scale = (float)( i_new_width ) / (float) i_src_width;
1821
1822         i_new_height = __MAX( 16, i_src_height * (float)f_real_scale );
1823
1824         f_scale_width = f_real_scale;
1825         f_scale_height = (float) i_new_height / (float) i_src_height;
1826     }
1827     else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1828              id->p_encoder->fmt_out.video.i_height <= 0 )
1829     {
1830         /* Only width specified */
1831         f_scale_width = (float)id->p_encoder->fmt_out.video.i_width /
1832                              p_sys->i_crop_width;
1833         f_scale_height = f_scale_width;
1834     }
1835     else if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1836              id->p_encoder->fmt_out.video.i_height > 0 )
1837     {
1838          /* Only height specified */
1839          f_scale_height = (float)id->p_encoder->fmt_out.video.i_height /
1840                               p_sys->i_crop_height;
1841          f_scale_width = f_scale_height;
1842      }
1843      else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1844               id->p_encoder->fmt_out.video.i_height > 0 )
1845      {
1846          /* Width and height specified */
1847          f_scale_width = (float)id->p_encoder->fmt_out.video.i_width
1848                                / p_sys->i_crop_width;
1849          f_scale_height = (float)id->p_encoder->fmt_out.video.i_height
1850                                / p_sys->i_crop_height;
1851      }
1852
1853      /* check maxwidth and maxheight
1854       * note: maxwidth and maxheight currently does not handle
1855       * canvas and padding, just scaling and cropping.
1856       */
1857      if( p_sys->i_maxwidth && f_scale_width > (float)p_sys->i_maxwidth /
1858                                                      p_sys->i_crop_width )
1859      {
1860          f_scale_width = (float)p_sys->i_maxwidth / p_sys->i_crop_width;
1861      }
1862      if( p_sys->i_maxheight && f_scale_height > (float)p_sys->i_maxheight /
1863                                                        p_sys->i_crop_height )
1864      {
1865          f_scale_height = (float)p_sys->i_maxheight / p_sys->i_crop_height;
1866      }
1867
1868      /* Change aspect ratio from source pixel to scaled pixel */
1869      f_aspect = f_aspect * f_scale_height / f_scale_width;
1870      msg_Dbg( p_stream, "scaled pixel aspect is %f:1", f_aspect );
1871
1872      /* Correct scaling for target aspect ratio
1873       * Shrink video if necessary
1874       */
1875      if ( p_sys->i_canvas_aspect > 0 )
1876      {
1877          float f_target_aspect = (float)p_sys->i_canvas_aspect /
1878                                         VOUT_ASPECT_FACTOR;
1879
1880          if( p_sys->i_canvas_width > 0 && p_sys->i_canvas_height > 0)
1881          {
1882              /* Calculate pixel aspect of canvas */
1883              f_target_aspect = f_target_aspect / p_sys->i_canvas_width *
1884                                p_sys->i_canvas_height;
1885          }
1886          if( f_target_aspect > f_aspect )
1887          {
1888              /* Reduce width scale to increase aspect */
1889              f_scale_width = f_scale_width * f_aspect / f_target_aspect;
1890          }
1891          else
1892          {
1893              /* Reduce height scale to decrease aspect */
1894              f_scale_height = f_scale_height * f_target_aspect / f_aspect;
1895          }
1896          f_aspect = f_target_aspect;
1897          msg_Dbg( p_stream, "canvas scaled pixel aspect is %f:1", f_aspect );
1898      }
1899
1900      /* f_scale_width and f_scale_height are now final */
1901      /* Calculate width, height from scaling
1902       * Make sure its multiple of 2
1903       */
1904      i_dst_width = 2 * (int)( p_sys->i_crop_width * f_scale_width / 2 + 0.5 );
1905      i_dst_height = 2 *
1906                     (int)( p_sys->i_crop_height * f_scale_height / 2 + 0.5 );
1907
1908      p_sys->i_nopadd_width = i_dst_width;
1909      p_sys->i_nopadd_height = i_dst_height;
1910      p_sys->i_dst_x_offset = 0;
1911      p_sys->i_dst_y_offset = 0;
1912
1913      /* Handle canvas and padding */
1914      if( p_sys->i_canvas_width <= 0 )
1915      {
1916          /* No canvas width set, add explicit padding border */
1917          i_dst_width = p_sys->i_nopadd_width + ( p_sys->i_padd_left & ~1 ) +
1918                       ( p_sys->i_padd_right & ~1 );
1919          p_sys->i_dst_x_offset = ( p_sys->i_padd_left & ~1 );
1920      }
1921      else
1922      {
1923          /* Canvas set, check if we have to padd or crop */
1924          if( p_sys->i_canvas_width < p_sys->i_nopadd_width )
1925          {
1926              /* need to crop more, but keep same scaling */
1927              int i_crop = 2 * (int)( ( p_sys->i_canvas_width & ~1 ) /
1928                                        f_scale_width / 2 + 0.5 );
1929
1930              p_sys->i_src_x_offset += ( ( p_sys->i_crop_width - i_crop ) / 2 )
1931                                            & ~1;
1932              p_sys->i_crop_width = i_crop;
1933              i_dst_width = p_sys->i_canvas_width & ~1;
1934              p_sys->i_nopadd_width = i_dst_width;
1935          }
1936          else if( p_sys->i_canvas_width > p_sys->i_nopadd_width )
1937          {
1938              /* need to padd */
1939              i_dst_width = p_sys->i_canvas_width & ~1;
1940              p_sys->i_dst_x_offset = ( i_dst_width - p_sys->i_nopadd_width )/2;
1941              p_sys->i_dst_x_offset = p_sys->i_dst_x_offset & ~1;
1942          }
1943      }
1944
1945      if( p_sys->i_canvas_height <= 0 )
1946      {
1947          /* No canvas set, add padding border */
1948          i_dst_height = p_sys->i_nopadd_height + ( p_sys->i_padd_top & ~1 ) +
1949                         ( p_sys->i_padd_bottom & ~1 );
1950          p_sys->i_dst_y_offset = ( p_sys->i_padd_top & ~1 );
1951      }
1952      else
1953      {
1954          /* Canvas set, check if we have to padd or crop */
1955          if( p_sys->i_canvas_height < p_sys->i_nopadd_height )
1956          {
1957              /* need to crop more, but keep same scaling */
1958              int i_crop = 2 * (int)( ( p_sys->i_canvas_height & ~1 ) /
1959                                         f_scale_height / 2 + 0.5 );
1960
1961              p_sys->i_src_y_offset += ( ( p_sys->i_crop_height - i_crop ) / 2 )
1962                                                 & ~1;
1963              p_sys->i_crop_height = i_crop;
1964              i_dst_height = p_sys->i_canvas_height & ~1;
1965              p_sys->i_nopadd_height = i_dst_height;
1966          }
1967          else if( p_sys->i_canvas_height > p_sys->i_nopadd_height )
1968          {
1969              /* need to padd */
1970              i_dst_height = p_sys->i_canvas_height & ~1;
1971              p_sys->i_dst_y_offset = ( i_dst_height - p_sys->i_nopadd_height )
1972                                         /2;
1973              p_sys->i_dst_y_offset = p_sys->i_dst_y_offset & ~1;
1974          }
1975      }
1976
1977      /* Change aspect ratio from scaled pixel to output frame */
1978      f_aspect = f_aspect * i_dst_width / i_dst_height;
1979
1980      /* Store calculated values */
1981      id->p_encoder->fmt_out.video.i_width = i_dst_width;
1982      id->p_encoder->fmt_out.video.i_height = i_dst_height;
1983
1984      id->p_encoder->fmt_in.video.i_width = i_dst_width;
1985      id->p_encoder->fmt_in.video.i_height = i_dst_height;
1986
1987      msg_Dbg( p_stream, "source %ix%i, crop %ix%i, "
1988                         "destination %ix%i, padding %ix%i",
1989          i_src_width, i_src_height,
1990          p_sys->i_crop_width, p_sys->i_crop_height,
1991          p_sys->i_nopadd_width, p_sys->i_nopadd_height,
1992          i_dst_width, i_dst_height
1993      );
1994
1995     /* Handle frame rate conversion */
1996     if( !id->p_encoder->fmt_out.video.i_frame_rate ||
1997         !id->p_encoder->fmt_out.video.i_frame_rate_base )
1998     {
1999         if( id->p_decoder->fmt_out.video.i_frame_rate &&
2000             id->p_decoder->fmt_out.video.i_frame_rate_base )
2001         {
2002             id->p_encoder->fmt_out.video.i_frame_rate =
2003                 id->p_decoder->fmt_out.video.i_frame_rate;
2004             id->p_encoder->fmt_out.video.i_frame_rate_base =
2005                 id->p_decoder->fmt_out.video.i_frame_rate_base;
2006         }
2007         else
2008         {
2009             /* Pick a sensible default value */
2010             id->p_encoder->fmt_out.video.i_frame_rate = 25;
2011             id->p_encoder->fmt_out.video.i_frame_rate_base = 1;
2012         }
2013     }
2014
2015     id->p_encoder->fmt_in.video.i_frame_rate =
2016         id->p_encoder->fmt_out.video.i_frame_rate;
2017     id->p_encoder->fmt_in.video.i_frame_rate_base =
2018         id->p_encoder->fmt_out.video.i_frame_rate_base;
2019
2020     date_Init( &id->interpolated_pts,
2021                id->p_encoder->fmt_out.video.i_frame_rate,
2022                id->p_encoder->fmt_out.video.i_frame_rate_base );
2023
2024     /* Check whether a particular aspect ratio was requested */
2025     if( !id->p_encoder->fmt_out.video.i_aspect )
2026     {
2027         id->p_encoder->fmt_out.video.i_aspect = (int)( f_aspect * VOUT_ASPECT_FACTOR + 0.5 );
2028     }
2029     id->p_encoder->fmt_in.video.i_aspect =
2030         id->p_encoder->fmt_out.video.i_aspect;
2031
2032     msg_Dbg( p_stream, "encoder aspect is %i:%i", id->p_encoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
2033
2034     id->p_encoder->p_module =
2035         module_Need( id->p_encoder, "encoder", p_sys->psz_venc, VLC_TRUE );
2036     if( !id->p_encoder->p_module )
2037     {
2038         msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_venc );
2039         return VLC_EGENERIC;
2040     }
2041
2042     id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
2043
2044     /* Hack for mp2v/mp1v transcoding support */
2045     if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','1','v') ||
2046         id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','2','v') )
2047     {
2048         id->p_encoder->fmt_out.i_codec = VLC_FOURCC('m','p','g','v');
2049     }
2050
2051     id->id = p_stream->p_sys->p_out->pf_add( p_stream->p_sys->p_out,
2052                                              &id->p_encoder->fmt_out );
2053     if( !id->id )
2054     {
2055         msg_Err( p_stream, "cannot add this stream" );
2056         return VLC_EGENERIC;
2057     }
2058
2059     return VLC_SUCCESS;
2060 }
2061
2062 static void transcode_video_close( sout_stream_t *p_stream,
2063                                    sout_stream_id_t *id )
2064 {
2065     int i, j;
2066
2067     if( p_stream->p_sys->i_threads >= 1 )
2068     {
2069         vlc_mutex_lock( &p_stream->p_sys->lock_out );
2070         vlc_object_kill( p_stream->p_sys );
2071         vlc_cond_signal( &p_stream->p_sys->cond );
2072         vlc_mutex_unlock( &p_stream->p_sys->lock_out );
2073         vlc_thread_join( p_stream->p_sys );
2074         vlc_mutex_destroy( &p_stream->p_sys->lock_out );
2075         vlc_cond_destroy( &p_stream->p_sys->cond );
2076     }
2077
2078     /* Close decoder */
2079     if( id->p_decoder->p_module )
2080         module_Unneed( id->p_decoder, id->p_decoder->p_module );
2081
2082     if( id->p_decoder->p_owner )
2083     {
2084         /* Clean-up pictures ring buffer */
2085         for( i = 0; i < PICTURE_RING_SIZE; i++ )
2086         {
2087             if( id->p_decoder->p_owner->pp_pics[i] )
2088                 video_del_buffer( VLC_OBJECT(id->p_decoder),
2089                                   id->p_decoder->p_owner->pp_pics[i] );
2090         }
2091         free( id->p_decoder->p_owner );
2092     }
2093
2094     /* Close encoder */
2095     if( id->p_encoder->p_module )
2096         module_Unneed( id->p_encoder, id->p_encoder->p_module );
2097
2098     /* Close filters */
2099     for( i = 0; i < id->i_filter; i++ )
2100     {
2101         vlc_object_detach( id->pp_filter[i] );
2102         if( id->pp_filter[i]->p_module )
2103             module_Unneed( id->pp_filter[i], id->pp_filter[i]->p_module );
2104
2105         /* Clean-up pictures ring buffer */
2106         for( j = 0; j < PICTURE_RING_SIZE; j++ )
2107         {
2108             if( id->pp_filter[i]->p_owner->pp_pics[j] )
2109                 video_del_buffer( VLC_OBJECT(id->pp_filter[i]),
2110                                   id->pp_filter[i]->p_owner->pp_pics[j] );
2111         }
2112         free( id->pp_filter[i]->p_owner );
2113         vlc_object_destroy( id->pp_filter[i] );
2114         id->pp_filter[i] = NULL;
2115     }
2116
2117     for( i = 0; i < id->i_ufilter; i++ )
2118     {
2119         vlc_object_detach( id->pp_ufilter[i] );
2120         if( id->pp_ufilter[i]->p_module )
2121             module_Unneed( id->pp_ufilter[i], id->pp_ufilter[i]->p_module );
2122
2123         /* Clean-up pictures ring buffer */
2124         for( j = 0; j < PICTURE_RING_SIZE; j++ )
2125         {
2126             if( id->pp_ufilter[i]->p_owner->pp_pics[j] )
2127                 video_del_buffer( VLC_OBJECT(id->pp_ufilter[i]),
2128                                   id->pp_ufilter[i]->p_owner->pp_pics[j] );
2129         }
2130         free( id->pp_ufilter[i]->p_owner );
2131         vlc_object_destroy( id->pp_ufilter[i] );
2132         id->pp_ufilter[i] = NULL;
2133     }
2134 }
2135
2136 static int transcode_video_process( sout_stream_t *p_stream,
2137                                     sout_stream_id_t *id,
2138                                     block_t *in, block_t **out )
2139 {
2140     sout_stream_sys_t *p_sys = p_stream->p_sys;
2141     int i_duplicate = 1, i;
2142     picture_t *p_pic, *p_pic2 = NULL;
2143     *out = NULL;
2144
2145     while( (p_pic = id->p_decoder->pf_decode_video( id->p_decoder, &in )) )
2146     {
2147         subpicture_t *p_subpic = NULL;
2148
2149         sout_UpdateStatistic( p_stream->p_sout, SOUT_STATISTIC_DECODED_VIDEO, 1 );
2150
2151         if( p_stream->p_sout->i_out_pace_nocontrol && p_sys->b_hurry_up )
2152         {
2153             mtime_t current_date = mdate();
2154             if( current_date + 50000 > p_pic->date )
2155             {
2156                 msg_Dbg( p_stream, "late picture skipped ("I64Fd")",
2157                          current_date + 50000 - p_pic->date );
2158                 p_pic->pf_release( p_pic );
2159                 continue;
2160             }
2161         }
2162
2163         if( p_sys->b_master_sync )
2164         {
2165             mtime_t i_video_drift;
2166             mtime_t i_master_drift = p_sys->i_master_drift;
2167             mtime_t i_pts;
2168
2169             i_pts = date_Get( &id->interpolated_pts ) + 1;
2170             if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2171                   || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2172             {
2173                 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2174                 date_Set( &id->interpolated_pts, p_pic->date );
2175                 i_pts = p_pic->date + 1;
2176             }
2177             i_video_drift = p_pic->date - i_pts;
2178             i_duplicate = 1;
2179
2180             /* Set the pts of the frame being encoded */
2181             p_pic->date = i_pts;
2182
2183             if( i_video_drift < (i_master_drift - 50000) )
2184             {
2185 #if 0
2186                 msg_Dbg( p_stream, "dropping frame (%i)",
2187                          (int)(i_video_drift - i_master_drift) );
2188 #endif
2189                 p_pic->pf_release( p_pic );
2190                 continue;
2191             }
2192             else if( i_video_drift > (i_master_drift + 50000) )
2193             {
2194 #if 0
2195                 msg_Dbg( p_stream, "adding frame (%i)",
2196                          (int)(i_video_drift - i_master_drift) );
2197 #endif
2198                 i_duplicate = 2;
2199             }
2200         }
2201
2202         if( !id->p_encoder->p_module )
2203         {
2204             if( transcode_video_encoder_open( p_stream, id ) != VLC_SUCCESS )
2205             {
2206                 p_pic->pf_release( p_pic );
2207                 transcode_video_close( p_stream, id );
2208                 id->b_transcode = VLC_FALSE;
2209                 return VLC_EGENERIC;
2210             }
2211
2212             /* Deinterlace */
2213             if( p_stream->p_sys->b_deinterlace )
2214             {
2215                 id->pp_filter[id->i_filter] =
2216                     vlc_object_create( p_stream, VLC_OBJECT_FILTER );
2217                 vlc_object_attach( id->pp_filter[id->i_filter], p_stream );
2218
2219                 id->pp_filter[id->i_filter]->pf_vout_buffer_new =
2220                     video_new_buffer_filter;
2221                 id->pp_filter[id->i_filter]->pf_vout_buffer_del =
2222                     video_del_buffer_filter;
2223
2224                 id->pp_filter[id->i_filter]->fmt_in = id->p_decoder->fmt_out;
2225                 id->pp_filter[id->i_filter]->fmt_out = id->p_decoder->fmt_out;
2226                 id->pp_filter[id->i_filter]->p_cfg = p_sys->p_deinterlace_cfg;
2227                 id->pp_filter[id->i_filter]->p_module =
2228                     module_Need( id->pp_filter[id->i_filter],
2229                                  "video filter2", p_sys->psz_deinterlace,
2230                                  VLC_TRUE );
2231                 if( id->pp_filter[id->i_filter]->p_module )
2232                 {
2233                     id->pp_filter[id->i_filter]->p_owner =
2234                         malloc( sizeof(filter_owner_sys_t) );
2235                     for( i = 0; i < PICTURE_RING_SIZE; i++ )
2236                         id->pp_filter[id->i_filter]->p_owner->pp_pics[i] = 0;
2237                     id->pp_filter[id->i_filter]->p_owner->p_sys = p_sys;
2238
2239                     id->i_filter++;
2240                 }
2241                 else
2242                 {
2243                     msg_Dbg( p_stream, "no video filter found" );
2244                     vlc_object_detach( id->pp_filter[id->i_filter] );
2245                     vlc_object_destroy( id->pp_filter[id->i_filter] );
2246                 }
2247             }
2248
2249             /* Check if we need a filter for chroma conversion or resizing */
2250             if( id->p_decoder->fmt_out.video.i_chroma !=
2251                 id->p_encoder->fmt_in.video.i_chroma ||
2252
2253                 (int)id->p_decoder->fmt_out.video.i_width != p_sys->i_crop_width ||
2254                 p_sys->i_crop_width != p_sys->i_nopadd_width ||
2255                 p_sys->i_nopadd_width != (int)id->p_encoder->fmt_out.video.i_width ||
2256
2257                 (int)id->p_decoder->fmt_out.video.i_height != p_sys->i_crop_height ||
2258                 p_sys->i_crop_height != p_sys->i_nopadd_height ||
2259                 p_sys->i_nopadd_height != (int)id->p_encoder->fmt_out.video.i_height)
2260             {
2261                 id->pp_filter[id->i_filter] =
2262                     vlc_object_create( p_stream, VLC_OBJECT_FILTER );
2263                 vlc_object_attach( id->pp_filter[id->i_filter], p_stream );
2264
2265                 id->pp_filter[id->i_filter]->pf_vout_buffer_new =
2266                     video_new_buffer_filter;
2267                 id->pp_filter[id->i_filter]->pf_vout_buffer_del =
2268                     video_del_buffer_filter;
2269
2270                 id->pp_filter[id->i_filter]->fmt_in = id->p_decoder->fmt_out;
2271                 id->pp_filter[id->i_filter]->fmt_out = id->p_encoder->fmt_in;
2272                 id->pp_filter[id->i_filter]->p_cfg = NULL;
2273
2274                 id->pp_filter[id->i_filter]->fmt_in.video.i_x_offset = p_sys->i_src_x_offset;
2275                 id->pp_filter[id->i_filter]->fmt_in.video.i_y_offset = p_sys->i_src_y_offset;
2276                 id->pp_filter[id->i_filter]->fmt_in.video.i_visible_width = p_sys->i_crop_width;
2277                 id->pp_filter[id->i_filter]->fmt_in.video.i_visible_height = p_sys->i_crop_height;
2278
2279                 id->pp_filter[id->i_filter]->fmt_out.video.i_x_offset = p_sys->i_dst_x_offset;
2280                 id->pp_filter[id->i_filter]->fmt_out.video.i_y_offset = p_sys->i_dst_y_offset;
2281                 id->pp_filter[id->i_filter]->fmt_out.video.i_visible_width = p_sys->i_nopadd_width;
2282                 id->pp_filter[id->i_filter]->fmt_out.video.i_visible_height = p_sys->i_nopadd_height;
2283
2284                 id->pp_filter[id->i_filter]->p_module =
2285                     module_Need( id->pp_filter[id->i_filter],
2286                                  "crop padd", 0, 0 );
2287                 if( id->pp_filter[id->i_filter]->p_module )
2288                 {
2289                     id->pp_filter[id->i_filter]->p_owner =
2290                         malloc( sizeof(filter_owner_sys_t) );
2291                     for( i = 0; i < PICTURE_RING_SIZE; i++ )
2292                         id->pp_filter[id->i_filter]->p_owner->pp_pics[i] = 0;
2293                     id->pp_filter[id->i_filter]->p_owner->p_sys = p_sys;
2294
2295                     id->i_filter++;
2296                 }
2297                 else
2298                 {
2299                     msg_Dbg( p_stream, "no video filter found" );
2300                     vlc_object_detach( id->pp_filter[id->i_filter] );
2301                     vlc_object_destroy( id->pp_filter[id->i_filter] );
2302
2303                     p_pic->pf_release( p_pic );
2304                     transcode_video_close( p_stream, id );
2305                     id->b_transcode = VLC_FALSE;
2306                     return VLC_EGENERIC;
2307                 }
2308             }
2309
2310             for( i = 0; (i < p_sys->i_vfilters) && (id->i_ufilter < TRANSCODE_FILTERS); i++ )
2311             {
2312                 id->pp_ufilter[id->i_ufilter] =
2313                     vlc_object_create( p_stream, VLC_OBJECT_FILTER );
2314                 vlc_object_attach( id->pp_ufilter[id->i_ufilter], p_stream );
2315
2316                 id->pp_ufilter[id->i_ufilter]->pf_vout_buffer_new =
2317                     video_new_buffer_filter;
2318                 id->pp_ufilter[id->i_ufilter]->pf_vout_buffer_del =
2319                     video_del_buffer_filter;
2320
2321                 id->pp_ufilter[id->i_ufilter]->fmt_in = id->p_encoder->fmt_in;
2322                 id->pp_ufilter[id->i_ufilter]->fmt_out = id->p_encoder->fmt_in;
2323                 id->pp_ufilter[id->i_ufilter]->p_cfg = p_sys->p_vfilters_cfg[i];
2324                 id->pp_ufilter[id->i_ufilter]->p_module =
2325                     module_Need( id->pp_ufilter[id->i_ufilter],
2326                           "video filter2", p_sys->psz_vfilters[i], VLC_TRUE );
2327                 if( id->pp_ufilter[id->i_ufilter]->p_module )
2328                 {
2329                     id->pp_ufilter[id->i_ufilter]->p_owner =
2330                         malloc( sizeof(filter_owner_sys_t) );
2331                     for( i = 0; i < PICTURE_RING_SIZE; i++ )
2332                         id->pp_ufilter[id->i_ufilter]->p_owner->pp_pics[i] = 0;
2333                     id->pp_ufilter[id->i_ufilter]->p_owner->p_sys = p_sys;
2334                     id->i_ufilter++;
2335                 }
2336                 else
2337                 {
2338                     msg_Dbg( p_stream, "no video filter found" );
2339                     vlc_object_detach( id->pp_ufilter[id->i_ufilter] );
2340                     vlc_object_destroy( id->pp_ufilter[id->i_ufilter] );
2341                     id->pp_ufilter[id->i_ufilter] = NULL;
2342                 }
2343             }
2344         }
2345
2346         /* Run filter chain */
2347         for( i = 0; i < id->i_filter; i++ )
2348         {
2349             p_pic = id->pp_filter[i]->pf_video_filter(id->pp_filter[i], p_pic);
2350         }
2351
2352         /*
2353          * Encoding
2354          */
2355
2356         /* Check if we have a subpicture to overlay */
2357         if( p_sys->p_spu )
2358         {
2359             p_subpic = spu_SortSubpictures( p_sys->p_spu, p_pic->date,
2360                        VLC_FALSE /* Fixme: check if stream is paused */ );
2361             /* TODO: get another pic */
2362         }
2363
2364         /* Overlay subpicture */
2365         if( p_subpic )
2366         {
2367             int i_scale_width, i_scale_height;
2368             video_format_t *p_fmt;
2369
2370             i_scale_width = id->p_encoder->fmt_in.video.i_width * 1000 /
2371                 id->p_decoder->fmt_out.video.i_width;
2372             i_scale_height = id->p_encoder->fmt_in.video.i_height * 1000 /
2373                 id->p_decoder->fmt_out.video.i_height;
2374
2375             if( p_pic->i_refcount && !id->i_filter )
2376             {
2377                 /* We can't modify the picture, we need to duplicate it */
2378                 picture_t *p_tmp = video_new_buffer_decoder( id->p_decoder );
2379                 if( p_tmp )
2380                 {
2381                     vout_CopyPicture( p_stream, p_tmp, p_pic );
2382                     p_pic->pf_release( p_pic );
2383                     p_pic = p_tmp;
2384                 }
2385             }
2386
2387             if( id->i_filter )
2388                 p_fmt = &id->pp_filter[id->i_filter -1]->fmt_out.video;
2389             else
2390                 p_fmt = &id->p_decoder->fmt_out.video;
2391
2392             /* FIXME (shouldn't have to be done here) */
2393             p_fmt->i_sar_num = p_fmt->i_aspect *
2394                 p_fmt->i_height / p_fmt->i_width;
2395             p_fmt->i_sar_den = VOUT_ASPECT_FACTOR;
2396
2397             spu_RenderSubpictures( p_sys->p_spu, p_fmt, p_pic, p_pic, p_subpic,
2398                                    i_scale_width, i_scale_height );
2399         }
2400
2401         /* Run user specified filter chain */
2402         for( i = 0; i < id->i_ufilter; i++ )
2403         {
2404             p_pic = id->pp_ufilter[i]->pf_video_filter( id->pp_ufilter[i],
2405                                                         p_pic );
2406         }
2407
2408         if( p_sys->i_threads == 0 )
2409         {
2410             block_t *p_block;
2411             p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
2412             block_ChainAppend( out, p_block );
2413         }
2414
2415         if( p_sys->b_master_sync )
2416         {
2417             mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
2418             if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2419                   || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2420             {
2421                 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2422                 date_Set( &id->interpolated_pts, p_pic->date );
2423                 i_pts = p_pic->date + 1;
2424             }
2425             date_Increment( &id->interpolated_pts, 1 );
2426         }
2427
2428         if( p_sys->b_master_sync && i_duplicate > 1 )
2429         {
2430             mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
2431             if( (p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT)
2432                  || ((p_pic->date - i_pts) < -MASTER_SYNC_MAX_DRIFT) )
2433             {
2434                 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2435                 date_Set( &id->interpolated_pts, p_pic->date );
2436                 i_pts = p_pic->date + 1;
2437             }
2438             date_Increment( &id->interpolated_pts, 1 );
2439
2440             if( p_sys->i_threads >= 1 )
2441             {
2442                 /* We can't modify the picture, we need to duplicate it */
2443                 p_pic2 = video_new_buffer_decoder( id->p_decoder );
2444                 if( p_pic2 != NULL )
2445                 {
2446                     vout_CopyPicture( p_stream, p_pic2, p_pic );
2447                     p_pic2->date = i_pts;
2448                 }
2449             }
2450             else
2451             {
2452                 block_t *p_block;
2453                 p_pic->date = i_pts;
2454                 p_block = id->p_encoder->pf_encode_video(id->p_encoder, p_pic);
2455                 block_ChainAppend( out, p_block );
2456             }
2457         }
2458
2459         if( p_sys->i_threads == 0 )
2460         {
2461             p_pic->pf_release( p_pic );
2462         }
2463         else
2464         {
2465             vlc_mutex_lock( &p_sys->lock_out );
2466             p_sys->pp_pics[p_sys->i_last_pic++] = p_pic;
2467             p_sys->i_last_pic %= PICTURE_RING_SIZE;
2468             *out = p_sys->p_buffers;
2469             p_sys->p_buffers = NULL;
2470             if( p_pic2 != NULL )
2471             {
2472                 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic2;
2473                 p_sys->i_last_pic %= PICTURE_RING_SIZE;
2474             }
2475             vlc_cond_signal( &p_sys->cond );
2476             vlc_mutex_unlock( &p_sys->lock_out );
2477         }
2478     }
2479
2480     return VLC_SUCCESS;
2481 }
2482
2483 static int EncoderThread( sout_stream_sys_t *p_sys )
2484 {
2485     sout_stream_id_t *id = p_sys->id_video;
2486     picture_t *p_pic;
2487
2488     while( !p_sys->b_die && !p_sys->b_error )
2489     {
2490         block_t *p_block;
2491
2492         vlc_mutex_lock( &p_sys->lock_out );
2493         while( p_sys->i_last_pic == p_sys->i_first_pic )
2494         {
2495             vlc_cond_wait( &p_sys->cond, &p_sys->lock_out );
2496             if( p_sys->b_die || p_sys->b_error ) break;
2497         }
2498         if( p_sys->b_die || p_sys->b_error )
2499         {
2500             vlc_mutex_unlock( &p_sys->lock_out );
2501             break;
2502         }
2503
2504         p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2505         p_sys->i_first_pic %= PICTURE_RING_SIZE;
2506         vlc_mutex_unlock( &p_sys->lock_out );
2507
2508         p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
2509         vlc_mutex_lock( &p_sys->lock_out );
2510         block_ChainAppend( &p_sys->p_buffers, p_block );
2511
2512         vlc_mutex_unlock( &p_sys->lock_out );
2513         p_pic->pf_release( p_pic );
2514     }
2515
2516     while( p_sys->i_last_pic != p_sys->i_first_pic )
2517     {
2518         p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2519         p_sys->i_first_pic %= PICTURE_RING_SIZE;
2520         p_pic->pf_release( p_pic );
2521     }
2522     block_ChainRelease( p_sys->p_buffers );
2523
2524     return 0;
2525 }
2526
2527 struct picture_sys_t
2528 {
2529     vlc_object_t *p_owner;
2530 };
2531
2532 static void video_release_buffer( picture_t *p_pic )
2533 {
2534     if( p_pic && !p_pic->i_refcount && p_pic->pf_release && p_pic->p_sys )
2535     {
2536         video_del_buffer_decoder( (decoder_t *)p_pic->p_sys->p_owner, p_pic );
2537     }
2538     else if( p_pic && p_pic->i_refcount > 0 ) p_pic->i_refcount--;
2539 }
2540
2541 static picture_t *video_new_buffer( vlc_object_t *p_this, picture_t **pp_ring,
2542                                     sout_stream_sys_t *p_sys )
2543 {
2544     decoder_t *p_dec = (decoder_t *)p_this;
2545     picture_t *p_pic;
2546     int i;
2547
2548     /* Find an empty space in the picture ring buffer */
2549     for( i = 0; i < PICTURE_RING_SIZE; i++ )
2550     {
2551         if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
2552         {
2553             pp_ring[i]->i_status = RESERVED_PICTURE;
2554             return pp_ring[i];
2555         }
2556     }
2557     for( i = 0; i < PICTURE_RING_SIZE; i++ )
2558     {
2559         if( pp_ring[i] == 0 ) break;
2560     }
2561
2562     if( i == PICTURE_RING_SIZE && p_sys->i_threads >= 1 )
2563     {
2564         int i_first_pic = p_sys->i_first_pic;
2565
2566         if( p_sys->i_first_pic != p_sys->i_last_pic )
2567         {
2568             /* Encoder still has stuff to encode, wait to clear-up the list */
2569             while( p_sys->i_first_pic == i_first_pic )
2570                 msleep( 100000 );
2571         }
2572
2573         /* Find an empty space in the picture ring buffer */
2574         for( i = 0; i < PICTURE_RING_SIZE; i++ )
2575         {
2576             if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
2577             {
2578                 pp_ring[i]->i_status = RESERVED_PICTURE;
2579                 return pp_ring[i];
2580             }
2581         }
2582         for( i = 0; i < PICTURE_RING_SIZE; i++ )
2583         {
2584             if( pp_ring[i] == 0 ) break;
2585         }
2586     }
2587
2588     if( i == PICTURE_RING_SIZE )
2589     {
2590         msg_Err( p_this, "decoder/filter is leaking pictures, "
2591                  "resetting its ring buffer" );
2592
2593         for( i = 0; i < PICTURE_RING_SIZE; i++ )
2594         {
2595             pp_ring[i]->pf_release( pp_ring[i] );
2596         }
2597
2598         i = 0;
2599     }
2600
2601     p_pic = malloc( sizeof(picture_t) );
2602     if( !p_pic ) return NULL;
2603     p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
2604     vout_AllocatePicture( VLC_OBJECT(p_dec), p_pic,
2605                           p_dec->fmt_out.video.i_chroma,
2606                           p_dec->fmt_out.video.i_width,
2607                           p_dec->fmt_out.video.i_height,
2608                           p_dec->fmt_out.video.i_aspect );
2609
2610     if( !p_pic->i_planes )
2611     {
2612         free( p_pic );
2613         return NULL;
2614     }
2615
2616     p_pic->pf_release = video_release_buffer;
2617     p_pic->p_sys = malloc( sizeof(picture_sys_t) );
2618     if( !p_pic->p_sys )
2619     {
2620         free( p_pic );
2621         return NULL;
2622     }
2623
2624     p_pic->p_sys->p_owner = p_this;
2625     p_pic->i_status = RESERVED_PICTURE;
2626
2627     pp_ring[i] = p_pic;
2628     return p_pic;
2629 }
2630
2631 static picture_t *video_new_buffer_decoder( decoder_t *p_dec )
2632 {
2633     return video_new_buffer( VLC_OBJECT(p_dec),
2634                              p_dec->p_owner->pp_pics, p_dec->p_owner->p_sys );
2635 }
2636
2637 static picture_t *video_new_buffer_filter( filter_t *p_filter )
2638 {
2639     return video_new_buffer( VLC_OBJECT(p_filter),
2640                              p_filter->p_owner->pp_pics,
2641                              p_filter->p_owner->p_sys );
2642 }
2643
2644 static void video_del_buffer( vlc_object_t *p_this, picture_t *p_pic )
2645 {
2646     if( p_pic && p_pic->p_data_orig ) free( p_pic->p_data_orig );
2647     if( p_pic && p_pic->p_sys ) free( p_pic->p_sys );
2648     if( p_pic ) free( p_pic );
2649 }
2650
2651 static void video_del_buffer_decoder( decoder_t *p_decoder, picture_t *p_pic )
2652 {
2653     p_pic->i_refcount = 0;
2654     p_pic->i_status = DESTROYED_PICTURE;
2655 }
2656
2657 static void video_del_buffer_filter( filter_t *p_filter, picture_t *p_pic )
2658 {
2659     p_pic->i_refcount = 0;
2660     p_pic->i_status = DESTROYED_PICTURE;
2661 }
2662
2663 static void video_link_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2664 {
2665     p_pic->i_refcount++;
2666 }
2667
2668 static void video_unlink_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2669 {
2670     video_release_buffer( p_pic );
2671 }
2672
2673 /*
2674  * SPU
2675  */
2676 static subpicture_t *spu_new_buffer( decoder_t * );
2677 static void spu_del_buffer( decoder_t *, subpicture_t * );
2678
2679 static int transcode_spu_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2680 {
2681     sout_stream_sys_t *p_sys = p_stream->p_sys;
2682
2683     /*
2684      * Open decoder
2685      */
2686
2687     /* Initialization of decoder structures */
2688     id->p_decoder->pf_decode_sub = NULL;
2689     id->p_decoder->pf_spu_buffer_new = spu_new_buffer;
2690     id->p_decoder->pf_spu_buffer_del = spu_del_buffer;
2691     id->p_decoder->p_owner = (decoder_owner_sys_t *)p_stream;
2692     /* id->p_decoder->p_cfg = p_sys->p_spu_cfg; */
2693
2694     id->p_decoder->p_module =
2695         module_Need( id->p_decoder, "decoder", "$codec", 0 );
2696
2697     if( !id->p_decoder->p_module )
2698     {
2699         msg_Err( p_stream, "cannot find decoder" );
2700         return VLC_EGENERIC;
2701     }
2702
2703     if( !p_sys->b_soverlay )
2704     {
2705         /* Open encoder */
2706         /* Initialization of encoder format structures */
2707         es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
2708                         id->p_decoder->fmt_in.i_codec );
2709
2710         id->p_encoder->p_cfg = p_sys->p_spu_cfg;
2711
2712         id->p_encoder->p_module =
2713             module_Need( id->p_encoder, "encoder", p_sys->psz_senc, VLC_TRUE );
2714
2715         if( !id->p_encoder->p_module )
2716         {
2717             module_Unneed( id->p_decoder, id->p_decoder->p_module );
2718             msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_senc );
2719             return VLC_EGENERIC;
2720         }
2721     }
2722
2723     if( !p_sys->p_spu )
2724     {
2725         p_sys->p_spu = spu_Create( p_stream );
2726         spu_Init( p_sys->p_spu );
2727     }
2728
2729     return VLC_SUCCESS;
2730 }
2731
2732 static void transcode_spu_close( sout_stream_t *p_stream, sout_stream_id_t *id)
2733 {
2734     /* Close decoder */
2735     if( id->p_decoder->p_module )
2736         module_Unneed( id->p_decoder, id->p_decoder->p_module );
2737
2738     /* Close encoder */
2739     if( id->p_encoder->p_module )
2740         module_Unneed( id->p_encoder, id->p_encoder->p_module );
2741 }
2742
2743 static int transcode_spu_process( sout_stream_t *p_stream,
2744                                   sout_stream_id_t *id,
2745                                   block_t *in, block_t **out )
2746 {
2747     sout_stream_sys_t *p_sys = p_stream->p_sys;
2748     subpicture_t *p_subpic;
2749     *out = NULL;
2750
2751     p_subpic = id->p_decoder->pf_decode_sub( id->p_decoder, &in );
2752     if( !p_subpic )
2753         return VLC_EGENERIC;
2754
2755     sout_UpdateStatistic( p_stream->p_sout, SOUT_STATISTIC_DECODED_SUBTITLE, 1 );
2756
2757     if( p_sys->b_master_sync && p_sys->i_master_drift )
2758     {
2759         p_subpic->i_start -= p_sys->i_master_drift;
2760         if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2761     }
2762
2763     if( p_sys->b_soverlay )
2764     {
2765         spu_DisplaySubpicture( p_sys->p_spu, p_subpic );
2766     }
2767     else
2768     {
2769         block_t *p_block;
2770
2771         p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
2772         spu_del_buffer( id->p_decoder, p_subpic );
2773         if( p_block )
2774         {
2775             block_ChainAppend( out, p_block );
2776             return VLC_SUCCESS;
2777         }
2778     }
2779
2780     return VLC_EGENERIC;
2781 }
2782
2783 static subpicture_t *spu_new_buffer( decoder_t *p_dec )
2784 {
2785     sout_stream_t *p_stream = (sout_stream_t *)p_dec->p_owner;
2786     return spu_CreateSubpicture( p_stream->p_sys->p_spu );
2787 }
2788
2789 static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_subpic )
2790 {
2791     sout_stream_t *p_stream = (sout_stream_t *)p_dec->p_owner;
2792     spu_DestroySubpicture( p_stream->p_sys->p_spu, p_subpic );
2793 }
2794
2795 /*
2796  * OSD menu
2797  */
2798 static int transcode_osd_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2799 {
2800     sout_stream_sys_t *p_sys = p_stream->p_sys;
2801
2802     id->p_decoder->fmt_in.i_cat = SPU_ES;
2803     id->p_encoder->fmt_out.psz_language = strdup( "osd" );
2804
2805     if( p_sys->i_osdcodec != 0 || p_sys->psz_osdenc )
2806     {
2807         msg_Dbg( p_stream, "creating osdmenu transcoding from fcc=`%4.4s' "
2808                  "to fcc=`%4.4s'", (char*)&id->p_encoder->fmt_out.i_codec,
2809                  (char*)&p_sys->i_osdcodec );
2810
2811         /* Complete destination format */
2812         id->p_encoder->fmt_out.i_codec = p_sys->i_osdcodec;
2813
2814         /* Open encoder */
2815         es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
2816                         VLC_FOURCC('Y','U','V','A') );
2817         id->p_encoder->fmt_in.psz_language = strdup( "osd" );
2818
2819         id->p_encoder->p_cfg = p_sys->p_osd_cfg;
2820
2821         id->p_encoder->p_module =
2822             module_Need( id->p_encoder, "encoder", p_sys->psz_osdenc, VLC_TRUE );
2823
2824         if( !id->p_encoder->p_module )
2825         {
2826             msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_osdenc );
2827             goto error;
2828         }
2829
2830         /* open output stream */
2831         id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
2832         id->b_transcode = VLC_TRUE;
2833
2834         if( !id->id ) goto error;
2835     }
2836     else
2837     {
2838         msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
2839                  (char*)&id->p_decoder->fmt_out.i_codec );
2840         id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_decoder->fmt_out );
2841         id->b_transcode = VLC_FALSE;
2842
2843         if( !id->id ) goto error;
2844     }
2845
2846     if( !p_sys->p_spu )
2847     {
2848         p_sys->p_spu = spu_Create( p_stream );
2849         spu_Init( p_sys->p_spu );
2850     }
2851
2852     return VLC_SUCCESS;
2853
2854  error:
2855     msg_Err( p_stream, "starting osd encoding thread failed" );
2856     if( id->p_encoder->p_module )
2857             module_Unneed( id->p_encoder, id->p_encoder->p_module );
2858     p_sys->b_osd = VLC_FALSE;
2859     return VLC_EGENERIC;
2860 }
2861
2862 static void transcode_osd_close( sout_stream_t *p_stream, sout_stream_id_t *id)
2863 {
2864     sout_stream_sys_t *p_sys = p_stream->p_sys;
2865
2866     /* Close encoder */
2867     if( p_sys->b_osd && id )
2868     {
2869         if( id->p_encoder->p_module )
2870             module_Unneed( id->p_encoder, id->p_encoder->p_module );
2871     }
2872     p_sys->b_osd = VLC_FALSE;
2873 }
2874
2875 static int transcode_osd_process( sout_stream_t *p_stream,
2876                                   sout_stream_id_t *id,
2877                                   block_t *in, block_t **out )
2878 {
2879     sout_stream_sys_t *p_sys = p_stream->p_sys;
2880     subpicture_t *p_subpic = NULL;
2881
2882     /* Check if we have a subpicture to send */
2883     if( p_sys->p_spu && in->i_dts > 0)
2884     {
2885         p_subpic = spu_SortSubpictures( p_sys->p_spu, in->i_dts, VLC_FALSE );
2886     }
2887     else
2888     {
2889         msg_Warn( p_stream, "spu channel not initialized, doing it now" );
2890         if( !p_sys->p_spu )
2891         {
2892             p_sys->p_spu = spu_Create( p_stream );
2893             spu_Init( p_sys->p_spu );
2894         }
2895     }
2896
2897     if( p_subpic )
2898     {
2899         block_t *p_block = NULL;
2900
2901         if( p_sys->b_master_sync && p_sys->i_master_drift )
2902         {
2903             p_subpic->i_start -= p_sys->i_master_drift;
2904             if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2905         }
2906
2907         p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
2908         spu_DestroySubpicture( p_sys->p_spu, p_subpic );
2909         if( p_block )
2910         {
2911             p_block->i_dts = p_block->i_pts = in->i_dts;
2912             block_ChainAppend( out, p_block );
2913             return VLC_SUCCESS;
2914         }
2915     }
2916     return VLC_EGENERIC;
2917 }