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