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