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