]> git.sesse.net Git - vlc/blob - modules/stream_out/transcode.c
Implement afilter transcode filters and renamed vfilter to ufilter (userfilter) so...
[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 0
518         if( (strncmp( (char *)&p_sys->i_acodec, "mp3", 3) == 0) &&
519                             (p_sys->i_channels > 2) )
520         {
521             msg_Warn( p_stream, "%d channels invalid for mp3, forcing to 2",
522                       p_sys->i_channels );
523             p_sys->i_channels = 2;
524         }
525 #endif
526         msg_Dbg( p_stream, "codec audio=%4.4s %dHz %d channels %dKb/s",
527                  (char *)&p_sys->i_acodec, p_sys->i_sample_rate,
528                  p_sys->i_channels, p_sys->i_abitrate / 1000 );
529     }
530
531     var_Get( p_stream, SOUT_CFG_PREFIX "afilter", &val );
532     p_sys->i_afilters = 0;
533     if( val.psz_string && *val.psz_string )
534     {
535         char *psz_parser = val.psz_string;
536
537         while( (psz_parser != NULL) && (*psz_parser != '\0')
538                 && (p_sys->i_afilters < TRANSCODE_FILTERS) )
539         {
540             psz_parser = sout_CfgCreate(
541                                    &p_sys->psz_afilters[p_sys->i_afilters],
542                                    &p_sys->p_afilters_cfg[p_sys->i_afilters],
543                                    psz_parser );
544             p_sys->i_afilters++;
545             if( (psz_parser != NULL) && (*psz_parser != '\0') ) psz_parser++;
546         }
547     }
548     if( val.psz_string ) free( val.psz_string );
549     if( p_sys->i_afilters < TRANSCODE_FILTERS-1 )
550     {
551         p_sys->psz_afilters[p_sys->i_afilters] = NULL;
552         p_sys->p_afilters_cfg[p_sys->i_afilters] = NULL;
553     }
554
555     /* Video transcoding parameters */
556     var_Get( p_stream, SOUT_CFG_PREFIX "venc", &val );
557     p_sys->psz_venc = NULL;
558     p_sys->p_video_cfg = NULL;
559     if( val.psz_string && *val.psz_string )
560     {
561         char *psz_next;
562         psz_next = sout_CfgCreate( &p_sys->psz_venc, &p_sys->p_video_cfg,
563                                    val.psz_string );
564         if( psz_next ) free( psz_next );
565     }
566     if( val.psz_string ) free( val.psz_string );
567
568     var_Get( p_stream, SOUT_CFG_PREFIX "vcodec", &val );
569     p_sys->i_vcodec = 0;
570     if( val.psz_string && *val.psz_string )
571     {
572         char fcc[4] = "    ";
573         memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
574         p_sys->i_vcodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
575     }
576     if( val.psz_string ) free( val.psz_string );
577
578     var_Get( p_stream, SOUT_CFG_PREFIX "vb", &val );
579     p_sys->i_vbitrate = val.i_int;
580     if( p_sys->i_vbitrate < 16000 ) p_sys->i_vbitrate *= 1000;
581
582     var_Get( p_stream, SOUT_CFG_PREFIX "scale", &val );
583     p_sys->f_scale = val.f_float;
584
585     var_Get( p_stream, SOUT_CFG_PREFIX "fps", &val );
586     p_sys->f_fps = val.f_float;
587
588     var_Get( p_stream, SOUT_CFG_PREFIX "hurry-up", &val );
589     p_sys->b_hurry_up = val.b_bool;
590
591     var_Get( p_stream, SOUT_CFG_PREFIX "width", &val );
592     p_sys->i_width = val.i_int;
593
594     var_Get( p_stream, SOUT_CFG_PREFIX "height", &val );
595     p_sys->i_height = val.i_int;
596
597     var_Get( p_stream, SOUT_CFG_PREFIX "maxwidth", &val );
598     p_sys->i_maxwidth = val.i_int;
599
600     var_Get( p_stream, SOUT_CFG_PREFIX "maxheight", &val );
601     p_sys->i_maxheight = val.i_int;
602
603     var_Get( p_stream, SOUT_CFG_PREFIX "vfilter", &val );
604     p_sys->i_vfilters = 0;
605     if( val.psz_string && *val.psz_string )
606     {
607         char *psz_parser = val.psz_string;
608
609         while( (psz_parser != NULL) && (*psz_parser != '\0')
610                 && (p_sys->i_vfilters < TRANSCODE_FILTERS) )
611         {
612             psz_parser = sout_CfgCreate(
613                                    &p_sys->psz_vfilters[p_sys->i_vfilters],
614                                    &p_sys->p_vfilters_cfg[p_sys->i_vfilters],
615                                    psz_parser );
616             p_sys->i_vfilters++;
617             if( psz_parser != NULL && *psz_parser != '\0' ) psz_parser++;
618         }
619     }
620     if( val.psz_string ) free( val.psz_string );
621     if( p_sys->i_vfilters < TRANSCODE_FILTERS-1 )
622     {
623         p_sys->psz_vfilters[p_sys->i_vfilters] = NULL;
624         p_sys->p_vfilters_cfg[p_sys->i_vfilters] = NULL;
625     }
626
627     var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace", &val );
628     p_sys->b_deinterlace = val.b_bool;
629
630     var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace-module", &val );
631     p_sys->psz_deinterlace = NULL;
632     p_sys->p_deinterlace_cfg = NULL;
633     if( val.psz_string && *val.psz_string )
634     {
635         char *psz_next;
636         psz_next = sout_CfgCreate( &p_sys->psz_deinterlace,
637                                    &p_sys->p_deinterlace_cfg,
638                                    val.psz_string );
639         if( psz_next ) free( psz_next );
640     }
641     if( val.psz_string ) free( val.psz_string );
642
643     var_Get( p_stream, SOUT_CFG_PREFIX "croptop", &val );
644     p_sys->i_crop_top = val.i_int;
645     var_Get( p_stream, SOUT_CFG_PREFIX "cropbottom", &val );
646     p_sys->i_crop_bottom = val.i_int;
647     var_Get( p_stream, SOUT_CFG_PREFIX "cropleft", &val );
648     p_sys->i_crop_left = val.i_int;
649     var_Get( p_stream, SOUT_CFG_PREFIX "cropright", &val );
650     p_sys->i_crop_right = val.i_int;
651
652     var_Get( p_stream, SOUT_CFG_PREFIX "paddtop", &val );
653     p_sys->i_padd_top = val.i_int;
654     var_Get( p_stream, SOUT_CFG_PREFIX "paddbottom", &val );
655     p_sys->i_padd_bottom = val.i_int;
656     var_Get( p_stream, SOUT_CFG_PREFIX "paddleft", &val );
657     p_sys->i_padd_left = val.i_int;
658     var_Get( p_stream, SOUT_CFG_PREFIX "paddright", &val );
659     p_sys->i_padd_right = val.i_int;
660
661     var_Get( p_stream, SOUT_CFG_PREFIX "canvas-width", &val );
662     p_sys->i_canvas_width = val.i_int;
663     var_Get( p_stream, SOUT_CFG_PREFIX "canvas-height", &val );
664     p_sys->i_canvas_height = val.i_int;
665
666     var_Get( p_stream, SOUT_CFG_PREFIX "canvas-aspect", &val );
667     if ( val.psz_string )
668     {
669         char *psz_parser = strchr( val.psz_string, ':' );
670
671         if( psz_parser )
672         {
673             *psz_parser++ = '\0';
674             p_sys->i_canvas_aspect = atoi( val.psz_string ) * VOUT_ASPECT_FACTOR
675                 / atoi( psz_parser );
676         }
677         else
678         {
679             msg_Warn( p_stream, "bad aspect ratio %s", val.psz_string );
680             p_sys->i_canvas_aspect = 0;
681         }
682
683         free( val.psz_string );
684     }
685     else
686     {
687         p_sys->i_canvas_aspect = 0;
688     }
689
690     var_Get( p_stream, SOUT_CFG_PREFIX "threads", &val );
691     p_sys->i_threads = val.i_int;
692     var_Get( p_stream, SOUT_CFG_PREFIX "high-priority", &val );
693     p_sys->b_high_priority = val.b_bool;
694
695     if( p_sys->i_vcodec )
696     {
697         msg_Dbg( p_stream, "codec video=%4.4s %dx%d scaling: %f %dkb/s",
698                  (char *)&p_sys->i_vcodec, p_sys->i_width, p_sys->i_height,
699                  p_sys->f_scale, p_sys->i_vbitrate / 1000 );
700     }
701
702     /* Subpictures transcoding parameters */
703     p_sys->p_spu = NULL;
704     p_sys->psz_senc = NULL;
705     p_sys->p_spu_cfg = NULL;
706     p_sys->i_scodec = 0;
707
708     var_Get( p_stream, SOUT_CFG_PREFIX "senc", &val );
709     if( val.psz_string && *val.psz_string )
710     {
711         char *psz_next;
712         psz_next = sout_CfgCreate( &p_sys->psz_senc, &p_sys->p_spu_cfg,
713                                    val.psz_string );
714         if( psz_next ) free( psz_next );
715     }
716     if( val.psz_string ) free( val.psz_string );
717
718     var_Get( p_stream, SOUT_CFG_PREFIX "scodec", &val );
719     if( val.psz_string && *val.psz_string )
720     {
721         char fcc[4] = "    ";
722         memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
723         p_sys->i_scodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
724     }
725     if( val.psz_string ) free( val.psz_string );
726
727     if( p_sys->i_scodec )
728     {
729         msg_Dbg( p_stream, "codec spu=%4.4s", (char *)&p_sys->i_scodec );
730     }
731
732     var_Get( p_stream, SOUT_CFG_PREFIX "soverlay", &val );
733     p_sys->b_soverlay = val.b_bool;
734
735     var_Get( p_stream, SOUT_CFG_PREFIX "sfilter", &val );
736     if( val.psz_string && *val.psz_string )
737     {
738         p_sys->p_spu = spu_Create( p_stream );
739         var_Create( p_sys->p_spu, "sub-filter", VLC_VAR_STRING );
740         var_Set( p_sys->p_spu, "sub-filter", val );
741         spu_Init( p_sys->p_spu );
742     }
743     if( val.psz_string ) free( val.psz_string );
744
745     /* OSD menu transcoding parameters */
746     p_sys->psz_osdenc = NULL;
747     p_sys->p_osd_cfg  = NULL;
748     p_sys->i_osdcodec = 0;
749     p_sys->b_es_osd   = VLC_FALSE;
750
751     var_Get( p_stream, SOUT_CFG_PREFIX "osd", &val );
752     p_sys->b_sout_osd = val.b_bool;
753     if( p_sys->b_sout_osd )
754     {
755         vlc_value_t osd_val;
756         char *psz_next;
757
758         psz_next = sout_CfgCreate( &p_sys->psz_osdenc,
759                                    &p_sys->p_osd_cfg, strdup( "dvbsub") );
760         if( psz_next ) free( psz_next );
761
762         p_sys->i_osdcodec = VLC_FOURCC('Y','U','V','P' );
763
764         msg_Dbg( p_stream, "codec osd=%4.4s", (char *)&p_sys->i_osdcodec );
765
766         if( !p_sys->p_spu )
767         {
768             osd_val.psz_string = strdup("osdmenu");
769             p_sys->p_spu = spu_Create( p_stream );
770             var_Create( p_sys->p_spu, "sub-filter", VLC_VAR_STRING );
771             var_Set( p_sys->p_spu, "sub-filter", osd_val );
772             spu_Init( p_sys->p_spu );
773             if( osd_val.psz_string ) free( osd_val.psz_string );
774         }
775         else
776         {
777             osd_val.psz_string = strdup("osdmenu");
778             var_Set( p_sys->p_spu, "sub-filter", osd_val );
779             if( osd_val.psz_string ) free( osd_val.psz_string );
780         }
781     }
782
783     /* Audio settings */
784     var_Get( p_stream, SOUT_CFG_PREFIX "audio-sync", &val );
785     p_sys->b_master_sync = val.b_bool;
786     if( p_sys->f_fps > 0 ) p_sys->b_master_sync = VLC_TRUE;
787
788     p_stream->pf_add    = Add;
789     p_stream->pf_del    = Del;
790     p_stream->pf_send   = Send;
791     p_stream->p_sys     = p_sys;
792
793     return VLC_SUCCESS;
794 }
795
796 /*****************************************************************************
797  * Close:
798  *****************************************************************************/
799 static void Close( vlc_object_t * p_this )
800 {
801     sout_stream_t       *p_stream = (sout_stream_t*)p_this;
802     sout_stream_sys_t   *p_sys = p_stream->p_sys;
803
804     sout_StreamDelete( p_sys->p_out );
805
806     while( p_sys->p_audio_cfg != NULL )
807     {
808         sout_cfg_t *p_next = p_sys->p_audio_cfg->p_next;
809
810         if( p_sys->p_audio_cfg->psz_name )
811             free( p_sys->p_audio_cfg->psz_name );
812         if( p_sys->p_audio_cfg->psz_value )
813             free( p_sys->p_audio_cfg->psz_value );
814         free( p_sys->p_audio_cfg );
815
816         p_sys->p_audio_cfg = p_next;
817     }
818     if( p_sys->psz_aenc ) free( p_sys->psz_aenc );
819
820     while( p_sys->p_video_cfg != NULL )
821     {
822         sout_cfg_t *p_next = p_sys->p_video_cfg->p_next;
823
824         if( p_sys->p_video_cfg->psz_name )
825             free( p_sys->p_video_cfg->psz_name );
826         if( p_sys->p_video_cfg->psz_value )
827             free( p_sys->p_video_cfg->psz_value );
828         free( p_sys->p_video_cfg );
829
830         p_sys->p_video_cfg = p_next;
831     }
832     if( p_sys->psz_venc ) free( p_sys->psz_venc );
833
834     while( p_sys->p_deinterlace_cfg != NULL )
835     {
836         sout_cfg_t *p_next = p_sys->p_deinterlace_cfg->p_next;
837
838         if( p_sys->p_deinterlace_cfg->psz_name )
839             free( p_sys->p_deinterlace_cfg->psz_name );
840         if( p_sys->p_deinterlace_cfg->psz_value )
841             free( p_sys->p_deinterlace_cfg->psz_value );
842         free( p_sys->p_deinterlace_cfg );
843
844         p_sys->p_deinterlace_cfg = p_next;
845     }
846     if( p_sys->psz_deinterlace ) free( p_sys->psz_deinterlace );
847
848     while( p_sys->p_spu_cfg != NULL )
849     {
850         sout_cfg_t *p_next = p_sys->p_spu_cfg->p_next;
851
852         if( p_sys->p_spu_cfg->psz_name )
853             free( p_sys->p_spu_cfg->psz_name );
854         if( p_sys->p_spu_cfg->psz_value )
855             free( p_sys->p_spu_cfg->psz_value );
856         free( p_sys->p_spu_cfg );
857
858         p_sys->p_spu_cfg = p_next;
859     }
860     if( p_sys->psz_senc ) free( p_sys->psz_senc );
861
862     if( p_sys->p_spu ) spu_Destroy( p_sys->p_spu );
863
864     while( p_sys->p_osd_cfg != NULL )
865     {
866         sout_cfg_t *p_next = p_sys->p_osd_cfg->p_next;
867
868         if( p_sys->p_osd_cfg->psz_name )
869             free( p_sys->p_osd_cfg->psz_name );
870         if( p_sys->p_osd_cfg->psz_value )
871             free( p_sys->p_osd_cfg->psz_value );
872         free( p_sys->p_osd_cfg );
873
874         p_sys->p_osd_cfg = p_next;
875     }
876     if( p_sys->psz_osdenc ) free( p_sys->psz_osdenc );
877
878     vlc_object_destroy( p_sys );
879 }
880
881 struct sout_stream_id_t
882 {
883     vlc_fourcc_t  b_transcode;
884
885     /* id of the out stream */
886     void *id;
887
888     /* Decoder */
889     decoder_t       *p_decoder;
890
891     /* Filters */
892     filter_t        *pp_filter[TRANSCODE_FILTERS];
893     int             i_filter;
894     /* User specified filters */
895     filter_t        *pp_ufilter[TRANSCODE_FILTERS];
896     int             i_ufilter;
897
898     /* Encoder */
899     encoder_t       *p_encoder;
900
901     /* Sync */
902     date_t          interpolated_pts;
903 };
904
905 static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
906 {
907     sout_stream_sys_t *p_sys = p_stream->p_sys;
908     sout_stream_id_t *id;
909
910     id = malloc( sizeof( sout_stream_id_t ) );
911     memset( id, 0, sizeof(sout_stream_id_t) );
912
913     id->id = NULL;
914     id->p_decoder = NULL;
915     id->p_encoder = NULL;
916
917     /* Create decoder object */
918     id->p_decoder = vlc_object_create( p_stream, VLC_OBJECT_DECODER );
919     if( !id->p_decoder )
920     {
921         msg_Err( p_stream, "out of memory" );
922         goto error;
923     }
924     vlc_object_attach( id->p_decoder, p_stream );
925     id->p_decoder->p_module = NULL;
926     id->p_decoder->fmt_in = *p_fmt;
927     id->p_decoder->b_pace_control = VLC_TRUE;
928
929     /* Create encoder object */
930     id->p_encoder = vlc_object_create( p_stream, VLC_OBJECT_ENCODER );
931     if( !id->p_encoder )
932     {
933         msg_Err( p_stream, "out of memory" );
934         goto error;
935     }
936     vlc_object_attach( id->p_encoder, p_stream );
937     id->p_encoder->p_module = NULL;
938
939     /* Create destination format */
940     es_format_Init( &id->p_encoder->fmt_out, p_fmt->i_cat, 0 );
941     id->p_encoder->fmt_out.i_id    = p_fmt->i_id;
942     id->p_encoder->fmt_out.i_group = p_fmt->i_group;
943     if( p_fmt->psz_language )
944         id->p_encoder->fmt_out.psz_language = strdup( p_fmt->psz_language );
945
946     if( p_fmt->i_cat == AUDIO_ES && (p_sys->i_acodec || p_sys->psz_aenc) )
947     {
948         msg_Dbg( p_stream,
949                  "creating audio transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
950                  (char*)&p_fmt->i_codec, (char*)&p_sys->i_acodec );
951
952         /* Complete destination format */
953         id->p_encoder->fmt_out.i_codec = p_sys->i_acodec;
954         id->p_encoder->fmt_out.audio.i_rate = p_sys->i_sample_rate > 0 ?
955             p_sys->i_sample_rate : (int)p_fmt->audio.i_rate;
956         id->p_encoder->fmt_out.i_bitrate = p_sys->i_abitrate;
957         id->p_encoder->fmt_out.audio.i_bitspersample =
958             p_fmt->audio.i_bitspersample;
959         id->p_encoder->fmt_out.audio.i_channels = p_sys->i_channels > 0 ?
960             p_sys->i_channels : p_fmt->audio.i_channels;
961         /* Sanity check for audio channels */
962         id->p_encoder->fmt_out.audio.i_channels =
963             __MIN( id->p_encoder->fmt_out.audio.i_channels,
964                    id->p_decoder->fmt_in.audio.i_channels );
965         id->p_encoder->fmt_out.audio.i_original_channels =
966             id->p_decoder->fmt_in.audio.i_physical_channels;
967         if( id->p_decoder->fmt_in.audio.i_channels ==
968             id->p_encoder->fmt_out.audio.i_channels )
969         {
970             id->p_encoder->fmt_out.audio.i_physical_channels =
971                 id->p_decoder->fmt_in.audio.i_physical_channels;
972         }
973         else
974         {
975             id->p_encoder->fmt_out.audio.i_physical_channels =
976                 pi_channels_maps[id->p_encoder->fmt_out.audio.i_channels];
977         }
978
979         /* Build decoder -> filter -> encoder chain */
980         if( transcode_audio_new( p_stream, id ) )
981         {
982             msg_Err( p_stream, "cannot create audio chain" );
983             goto error;
984         }
985
986         /* Open output stream */
987         id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
988         id->b_transcode = VLC_TRUE;
989
990         if( !id->id )
991         {
992             transcode_audio_close( p_stream, id );
993             goto error;
994         }
995
996         date_Init( &id->interpolated_pts, p_fmt->audio.i_rate, 1 );
997     }
998     else if( p_fmt->i_cat == VIDEO_ES &&
999              (p_sys->i_vcodec != 0 || p_sys->psz_venc) )
1000     {
1001         msg_Dbg( p_stream,
1002                  "creating video transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
1003                  (char*)&p_fmt->i_codec, (char*)&p_sys->i_vcodec );
1004
1005         /* Complete destination format */
1006         id->p_encoder->fmt_out.i_codec = p_sys->i_vcodec;
1007         id->p_encoder->fmt_out.video.i_width  = p_sys->i_width & ~1;
1008         id->p_encoder->fmt_out.video.i_height = p_sys->i_height & ~1;
1009         id->p_encoder->fmt_out.i_bitrate = p_sys->i_vbitrate;
1010
1011         /* Build decoder -> filter -> encoder chain */
1012         if( transcode_video_new( p_stream, id ) )
1013         {
1014             msg_Err( p_stream, "cannot create video chain" );
1015             goto error;
1016         }
1017
1018         /* Stream will be added later on because we don't know
1019          * all the characteristics of the decoded stream yet */
1020         id->b_transcode = VLC_TRUE;
1021
1022         if( p_sys->f_fps > 0 )
1023         {
1024             id->p_encoder->fmt_out.video.i_frame_rate =
1025                 (p_sys->f_fps * 1001) + 0.5;
1026             id->p_encoder->fmt_out.video.i_frame_rate_base = 1001;
1027         }
1028     }
1029     else if( p_fmt->i_cat == SPU_ES && (p_sys->i_scodec || p_sys->psz_senc) )
1030     {
1031         msg_Dbg( p_stream, "creating subtitles transcoding from fcc=`%4.4s' "
1032                  "to fcc=`%4.4s'", (char*)&p_fmt->i_codec,
1033                  (char*)&p_sys->i_scodec );
1034
1035         /* Complete destination format */
1036         id->p_encoder->fmt_out.i_codec = p_sys->i_scodec;
1037
1038         /* build decoder -> filter -> encoder */
1039         if( transcode_spu_new( p_stream, id ) )
1040         {
1041             msg_Err( p_stream, "cannot create subtitles chain" );
1042             goto error;
1043         }
1044
1045         /* open output stream */
1046         id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
1047         id->b_transcode = VLC_TRUE;
1048
1049         if( !id->id )
1050         {
1051             transcode_spu_close( p_stream, id );
1052             goto error;
1053         }
1054     }
1055     else if( p_fmt->i_cat == SPU_ES && p_sys->b_soverlay )
1056     {
1057         msg_Dbg( p_stream, "subtitles (fcc=`%4.4s') overlaying",
1058                  (char*)&p_fmt->i_codec );
1059
1060         id->b_transcode = VLC_TRUE;
1061
1062         /* Build decoder -> filter -> overlaying chain */
1063         if( transcode_spu_new( p_stream, id ) )
1064         {
1065             msg_Err( p_stream, "cannot create subtitles chain" );
1066             goto error;
1067         }
1068     }
1069     else
1070     {
1071         msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
1072                  (char*)&p_fmt->i_codec );
1073         id->id = p_sys->p_out->pf_add( p_sys->p_out, p_fmt );
1074         id->b_transcode = VLC_FALSE;
1075
1076         if( !id->id ) goto error;
1077     }
1078
1079     if( p_sys->b_sout_osd )
1080     {
1081         /* Create a fake OSD menu elementary stream */
1082         if( !p_sys->b_es_osd && (p_sys->i_osdcodec != 0 || p_sys->psz_osdenc) )
1083         {
1084             if( transcode_osd_new( p_stream, p_sys->id_osd ) )
1085             {
1086                 msg_Err( p_stream, "cannot create osd chain" );
1087                 goto error;
1088             }
1089             p_sys->b_es_osd = VLC_TRUE;
1090         }
1091     }
1092     return id;
1093
1094  error:
1095     if( id->p_decoder )
1096     {
1097         vlc_object_detach( id->p_decoder );
1098         vlc_object_destroy( id->p_decoder );
1099     }
1100
1101     if( id->p_encoder )
1102     {
1103         vlc_object_detach( id->p_encoder );
1104         es_format_Clean( &id->p_encoder->fmt_out );
1105         vlc_object_destroy( id->p_encoder );
1106     }
1107
1108     free( id );
1109     return NULL;
1110 }
1111
1112 static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
1113 {
1114     sout_stream_sys_t *p_sys = p_stream->p_sys;
1115
1116     if( p_sys->b_es_osd )
1117         transcode_osd_close( p_stream, p_sys->id_osd );
1118
1119     if( id->b_transcode )
1120     {
1121         switch( id->p_decoder->fmt_in.i_cat )
1122         {
1123         case AUDIO_ES:
1124             transcode_audio_close( p_stream, id );
1125             break;
1126         case VIDEO_ES:
1127             transcode_video_close( p_stream, id );
1128             break;
1129         case SPU_ES:
1130             transcode_spu_close( p_stream, id );
1131             break;
1132         }
1133     }
1134
1135     if( id->id ) p_sys->p_out->pf_del( p_sys->p_out, id->id );
1136
1137     if( id->p_decoder )
1138     {
1139         vlc_object_detach( id->p_decoder );
1140         vlc_object_destroy( id->p_decoder );
1141     }
1142
1143     if( id->p_encoder )
1144     {
1145         vlc_object_detach( id->p_encoder );
1146         es_format_Clean( &id->p_encoder->fmt_out );
1147         vlc_object_destroy( id->p_encoder );
1148     }
1149
1150     free( id );
1151
1152     return VLC_SUCCESS;
1153 }
1154
1155 static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
1156                  block_t *p_buffer )
1157 {
1158     sout_stream_sys_t *p_sys = p_stream->p_sys;
1159     block_t *p_out = NULL;
1160
1161     if( !id->b_transcode && id->id )
1162     {
1163         /* Transcode OSD menu pictures. */
1164         if( p_sys->b_es_osd )
1165         {
1166             transcode_osd_process( p_stream, id, p_buffer, &p_out );
1167         }
1168         return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_buffer );
1169     }
1170     else if( !id->b_transcode )
1171     {
1172         block_Release( p_buffer );
1173         return VLC_EGENERIC;
1174     }
1175
1176     switch( id->p_decoder->fmt_in.i_cat )
1177     {
1178     case AUDIO_ES:
1179         transcode_audio_process( p_stream, id, p_buffer, &p_out );
1180         break;
1181
1182     case VIDEO_ES:
1183         if( transcode_video_process( p_stream, id, p_buffer, &p_out )
1184             != VLC_SUCCESS )
1185         {
1186             return VLC_EGENERIC;
1187         }
1188         break;
1189
1190     case SPU_ES:
1191         if( transcode_spu_process( p_stream, id, p_buffer, &p_out ) !=
1192             VLC_SUCCESS )
1193         {
1194             return VLC_EGENERIC;
1195         }
1196         break;
1197
1198     default:
1199         p_out = NULL;
1200         block_Release( p_buffer );
1201         break;
1202     }
1203
1204     if( p_out ) return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_out );
1205     return VLC_SUCCESS;
1206 }
1207
1208 /****************************************************************************
1209  * decoder reencoder part
1210  ****************************************************************************/
1211 int audio_BitsPerSample( vlc_fourcc_t i_format )
1212 {
1213     switch( i_format )
1214     {
1215     case VLC_FOURCC('u','8',' ',' '):
1216     case VLC_FOURCC('s','8',' ',' '):
1217         return 8;
1218
1219     case VLC_FOURCC('u','1','6','l'):
1220     case VLC_FOURCC('s','1','6','l'):
1221     case VLC_FOURCC('u','1','6','b'):
1222     case VLC_FOURCC('s','1','6','b'):
1223         return 16;
1224
1225     case VLC_FOURCC('u','2','4','l'):
1226     case VLC_FOURCC('s','2','4','l'):
1227     case VLC_FOURCC('u','2','4','b'):
1228     case VLC_FOURCC('s','2','4','b'):
1229         return 24;
1230
1231     case VLC_FOURCC('u','3','2','l'):
1232     case VLC_FOURCC('s','3','2','l'):
1233     case VLC_FOURCC('u','3','2','b'):
1234     case VLC_FOURCC('s','3','2','b'):
1235     case VLC_FOURCC('f','l','3','2'):
1236     case VLC_FOURCC('f','i','3','2'):
1237         return 32;
1238
1239     case VLC_FOURCC('f','l','6','4'):
1240         return 64;
1241     }
1242
1243     return 0;
1244 }
1245
1246 static filter_t *transcode_audio_filter_new( sout_stream_t *p_stream,
1247                                              sout_stream_id_t *id,
1248                                              es_format_t *p_fmt_in,
1249                                              es_format_t *p_fmt_out,
1250                                              char *psz_name )
1251 {
1252     sout_stream_sys_t *p_sys = p_stream->p_sys;
1253     filter_t *p_filter = vlc_object_create( p_stream, VLC_OBJECT_FILTER );
1254
1255     vlc_object_attach( p_filter, p_stream );
1256     p_filter->pf_audio_buffer_new = (block_t* (*) (filter_t*, int))__block_New;
1257
1258     p_filter->fmt_in = *p_fmt_in;
1259     p_filter->fmt_out = *p_fmt_out;
1260     if( psz_name )
1261         p_filter->p_cfg = p_sys->p_afilters_cfg[id->i_ufilter];
1262
1263     p_filter->p_module = module_Need( p_filter, "audio filter2", psz_name, 0 );
1264     if( p_filter->p_module )
1265     {
1266         p_filter->fmt_out.audio.i_bitspersample =
1267             audio_BitsPerSample( p_filter->fmt_out.i_codec );
1268         *p_fmt_in = p_filter->fmt_out;
1269     }
1270     else
1271     {
1272         vlc_object_detach( p_filter );
1273         vlc_object_destroy( p_filter );
1274         p_filter = 0;
1275     }
1276
1277     return p_filter;
1278 }
1279
1280 static int transcode_audio_new( sout_stream_t *p_stream,
1281                                 sout_stream_id_t *id )
1282 {
1283     sout_stream_sys_t *p_sys = p_stream->p_sys;
1284     es_format_t fmt_last;
1285     int i;
1286
1287     /*
1288      * Open decoder
1289      */
1290
1291     /* Initialization of decoder structures */
1292     id->p_decoder->fmt_out = id->p_decoder->fmt_in;
1293     id->p_decoder->fmt_out.i_extra = 0;
1294     id->p_decoder->fmt_out.p_extra = 0;
1295     id->p_decoder->pf_decode_audio = 0;
1296     id->p_decoder->pf_aout_buffer_new = audio_new_buffer;
1297     id->p_decoder->pf_aout_buffer_del = audio_del_buffer;
1298     /* id->p_decoder->p_cfg = p_sys->p_audio_cfg; */
1299
1300     id->p_decoder->p_module =
1301         module_Need( id->p_decoder, "decoder", "$codec", 0 );
1302
1303     if( !id->p_decoder->p_module )
1304     {
1305         msg_Err( p_stream, "cannot find decoder" );
1306         return VLC_EGENERIC;
1307     }
1308     id->p_decoder->fmt_out.audio.i_bitspersample = 
1309         audio_BitsPerSample( id->p_decoder->fmt_out.i_codec );
1310     fmt_last = id->p_decoder->fmt_out;
1311     /* FIX decoders so we don't have to do this */
1312     fmt_last.audio.i_rate = id->p_decoder->fmt_in.audio.i_rate;
1313
1314     /*
1315      * Open encoder
1316      */
1317
1318     /* Initialization of encoder format structures */
1319     es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1320                     id->p_decoder->fmt_out.i_codec );
1321     id->p_encoder->fmt_in.audio.i_format = id->p_decoder->fmt_out.i_codec;
1322
1323     /* Initialization of encoder format structures */
1324     es_format_Init( &id->p_encoder->fmt_in, AUDIO_ES, AOUT_FMT_S16_NE );
1325     id->p_encoder->fmt_in.audio.i_format = AOUT_FMT_S16_NE;
1326     id->p_encoder->fmt_in.audio.i_rate = id->p_encoder->fmt_out.audio.i_rate;
1327     id->p_encoder->fmt_in.audio.i_physical_channels =
1328         id->p_encoder->fmt_out.audio.i_physical_channels;
1329     id->p_encoder->fmt_in.audio.i_original_channels =
1330         id->p_encoder->fmt_out.audio.i_original_channels;
1331     id->p_encoder->fmt_in.audio.i_channels =
1332         id->p_encoder->fmt_out.audio.i_channels;
1333     id->p_encoder->fmt_in.audio.i_bitspersample =
1334         audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1335
1336     id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
1337
1338     id->p_encoder->p_module =
1339         module_Need( id->p_encoder, "encoder", p_sys->psz_aenc, VLC_TRUE );
1340     if( !id->p_encoder->p_module )
1341     {
1342         msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_aenc );
1343         module_Unneed( id->p_decoder, id->p_decoder->p_module );
1344         id->p_decoder->p_module = 0;
1345         return VLC_EGENERIC;
1346     }
1347     id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
1348     id->p_encoder->fmt_in.audio.i_bitspersample =
1349         audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
1350
1351     /* Load conversion filters */
1352     if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels ||
1353         fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate )
1354     {
1355         /* We'll have to go through fl32 first */
1356         es_format_t fmt_out = id->p_encoder->fmt_in;
1357         fmt_out.i_codec = fmt_out.audio.i_format = VLC_FOURCC('f','l','3','2');
1358
1359         id->pp_filter[id->i_filter] =
1360             transcode_audio_filter_new( p_stream, id, &fmt_last, &fmt_out, NULL );
1361
1362         if( id->pp_filter[id->i_filter] ) id->i_filter++;
1363     }
1364
1365     for( i = 0; i < TRANSCODE_FILTERS; i++ )
1366     {
1367         if( (fmt_last.audio.i_channels !=
1368             id->p_encoder->fmt_in.audio.i_channels) ||
1369             (fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate) ||
1370             (fmt_last.i_codec != id->p_encoder->fmt_in.i_codec) )
1371         {
1372             id->pp_filter[id->i_filter] =
1373                 transcode_audio_filter_new( p_stream, id, &fmt_last,
1374                                             &id->p_encoder->fmt_in, NULL );
1375
1376             if( id->pp_filter[id->i_filter] )
1377                 id->i_filter++;
1378             else
1379                 break;
1380         }
1381     }
1382
1383     /* Final checks to see if conversions were successful */
1384     if( fmt_last.i_codec != id->p_encoder->fmt_in.i_codec )
1385     {
1386         msg_Err( p_stream, "no audio filter found (%4.4s->%4.4s)",
1387                  (char *)&fmt_last.i_codec,
1388                  (char *)&id->p_encoder->fmt_in.i_codec );
1389         transcode_audio_close( p_stream, id );
1390         return VLC_EGENERIC;
1391     }
1392
1393     /* Load user specified audio filters now */
1394     for( i = 0; (i < p_sys->i_afilters) &&
1395                 (id->i_ufilter < TRANSCODE_FILTERS); i++ )
1396     {
1397         id->pp_ufilter[id->i_ufilter] =
1398             transcode_audio_filter_new( p_stream, id, &fmt_last,
1399                                         &id->p_encoder->fmt_in,
1400                                         p_sys->psz_afilters[i] );
1401
1402         if( id->pp_ufilter[id->i_ufilter] )
1403             id->i_ufilter++;
1404         else
1405             break;
1406     }
1407
1408     if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels )
1409     {
1410         msg_Err( p_stream, "no audio filter found for mixing from"
1411                  " %i to %i channels", fmt_last.audio.i_channels,
1412                  id->p_encoder->fmt_in.audio.i_channels );
1413 #if 0
1414         /* FIXME : this might work, but only if the encoder is restarted */
1415         id->p_encoder->fmt_in.audio.i_channels = fmt_last.audio.i_channels;
1416         id->p_encoder->fmt_out.audio.i_channels = fmt_last.audio.i_channels;
1417
1418         id->p_encoder->fmt_in.audio.i_physical_channels =
1419             id->p_encoder->fmt_in.audio.i_original_channels =
1420                 fmt_last.audio.i_physical_channels;
1421         id->p_encoder->fmt_out.audio.i_physical_channels =
1422             id->p_encoder->fmt_out.audio.i_original_channels =
1423                 fmt_last.audio.i_physical_channels;
1424 #else
1425         transcode_audio_close( p_stream, id );
1426         return VLC_EGENERIC;
1427 #endif
1428     }
1429
1430     if( fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate )
1431     {
1432         msg_Err( p_stream, "no audio filter found for resampling from"
1433                  " %iHz to %iHz", fmt_last.audio.i_rate,
1434                  id->p_encoder->fmt_in.audio.i_rate );
1435 #if 0
1436         /* FIXME : this might work, but only if the encoder is restarted */
1437         id->p_encoder->fmt_in.audio.i_rate = fmt_last.audio.i_rate;
1438         id->p_encoder->fmt_out.audio.i_rate = fmt_last.audio.i_rate;
1439 #else
1440         transcode_audio_close( p_stream, id );
1441         return VLC_EGENERIC;
1442 #endif
1443     }
1444
1445     /* FIXME: Hack for mp3 transcoding support */
1446     if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC( 'm','p','3',' ' ) )
1447         id->p_encoder->fmt_out.i_codec = VLC_FOURCC( 'm','p','g','a' );
1448
1449     return VLC_SUCCESS;
1450 }
1451
1452 static void transcode_audio_close( sout_stream_t *p_stream,
1453                                    sout_stream_id_t *id )
1454 {
1455     int i;
1456
1457     /* Close decoder */
1458     if( id->p_decoder->p_module )
1459         module_Unneed( id->p_decoder, id->p_decoder->p_module );
1460     id->p_decoder->p_module = 0;
1461
1462     /* Close encoder */
1463     if( id->p_encoder->p_module )
1464         module_Unneed( id->p_encoder, id->p_encoder->p_module );
1465     id->p_encoder->p_module = 0;
1466
1467     /* Close filters */
1468     for( i = 0; i < id->i_filter; i++ )
1469     {
1470         vlc_object_detach( id->pp_filter[i] );
1471         if( id->pp_filter[i]->p_module )
1472             module_Unneed( id->pp_filter[i], id->pp_filter[i]->p_module );
1473         vlc_object_destroy( id->pp_filter[i] );
1474     }
1475     for( i = 0; i < id->i_ufilter; i++ )
1476     {
1477         vlc_object_detach( id->pp_ufilter[i] );
1478         if( id->pp_ufilter[i]->p_module )
1479             module_Unneed( id->pp_ufilter[i], id->pp_ufilter[i]->p_module );
1480         vlc_object_destroy( id->pp_ufilter[i] );
1481     }
1482 }
1483
1484 static int transcode_audio_process( sout_stream_t *p_stream,
1485                                     sout_stream_id_t *id,
1486                                     block_t *in, block_t **out )
1487 {
1488     sout_stream_sys_t *p_sys = p_stream->p_sys;
1489     aout_buffer_t *p_audio_buf;
1490     block_t *p_block, *p_audio_block;
1491     int i;
1492     *out = NULL;
1493     input_thread_t *p_input = NULL;
1494
1495     if( p_stream->p_parent->p_parent && p_stream->p_parent->p_parent->
1496                                 i_object_type == VLC_OBJECT_INPUT )
1497         p_input = (input_thread_t *)p_stream->p_parent->p_parent;
1498
1499     while( (p_audio_buf = id->p_decoder->pf_decode_audio( id->p_decoder,
1500                                                           &in )) )
1501     {
1502         if( p_input )
1503             stats_UpdateInteger( p_input, p_input->counters.p_decoded_audio,
1504                                  1, NULL );
1505         if( p_sys->b_master_sync )
1506         {
1507             mtime_t i_dts = date_Get( &id->interpolated_pts ) + 1;
1508             if ( p_audio_buf->start_date - i_dts > MASTER_SYNC_MAX_DRIFT
1509                   || p_audio_buf->start_date - i_dts < -MASTER_SYNC_MAX_DRIFT )
1510             {
1511                 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
1512                 date_Set( &id->interpolated_pts, p_audio_buf->start_date );
1513                 i_dts = p_audio_buf->start_date + 1;
1514             }
1515             p_sys->i_master_drift = p_audio_buf->start_date - i_dts;
1516             date_Increment( &id->interpolated_pts, p_audio_buf->i_nb_samples );
1517             p_audio_buf->start_date -= p_sys->i_master_drift;
1518             p_audio_buf->end_date -= p_sys->i_master_drift;
1519         }
1520
1521         p_audio_block = p_audio_buf->p_sys;
1522         p_audio_block->i_buffer = p_audio_buf->i_nb_bytes;
1523         p_audio_block->i_dts = p_audio_block->i_pts =
1524             p_audio_buf->start_date;
1525         p_audio_block->i_length = p_audio_buf->end_date -
1526             p_audio_buf->start_date;
1527         p_audio_block->i_samples = p_audio_buf->i_nb_samples;
1528
1529         /* Run filter chain */
1530         for( i = 0; i < id->i_filter; i++ )
1531         {
1532             p_audio_block =
1533                 id->pp_filter[i]->pf_audio_filter( id->pp_filter[i],
1534                                                    p_audio_block );
1535         }
1536
1537         /* Run user specified filter chain */
1538         for( i = 0; i < id->i_ufilter; i++ )
1539         {
1540             p_audio_block =
1541                 id->pp_ufilter[i]->pf_audio_filter( id->pp_ufilter[i],
1542                                                     p_audio_block );
1543         }
1544
1545         p_audio_buf->p_buffer = p_audio_block->p_buffer;
1546         p_audio_buf->i_nb_bytes = p_audio_block->i_buffer;
1547         p_audio_buf->i_nb_samples = p_audio_block->i_samples;
1548         p_audio_buf->start_date = p_audio_block->i_dts;
1549         p_audio_buf->end_date = p_audio_block->i_dts + p_audio_block->i_length;
1550
1551         p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf );
1552         block_ChainAppend( out, p_block );
1553         block_Release( p_audio_block );
1554         free( p_audio_buf );
1555     }
1556
1557     return VLC_SUCCESS;
1558 }
1559
1560 static void audio_release_buffer( aout_buffer_t *p_buffer )
1561 {
1562     if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
1563     if( p_buffer ) free( p_buffer );
1564 }
1565
1566 static aout_buffer_t *audio_new_buffer( decoder_t *p_dec, int i_samples )
1567 {
1568     aout_buffer_t *p_buffer;
1569     block_t *p_block;
1570     int i_size;
1571
1572     if( p_dec->fmt_out.audio.i_bitspersample )
1573     {
1574         i_size = i_samples * p_dec->fmt_out.audio.i_bitspersample / 8 *
1575             p_dec->fmt_out.audio.i_channels;
1576     }
1577     else if( p_dec->fmt_out.audio.i_bytes_per_frame &&
1578              p_dec->fmt_out.audio.i_frame_length )
1579     {
1580         i_size = i_samples * p_dec->fmt_out.audio.i_bytes_per_frame /
1581             p_dec->fmt_out.audio.i_frame_length;
1582     }
1583     else
1584     {
1585         i_size = i_samples * 4 * p_dec->fmt_out.audio.i_channels;
1586     }
1587
1588     p_buffer = malloc( sizeof(aout_buffer_t) );
1589     p_buffer->pf_release = audio_release_buffer;
1590     p_buffer->p_sys = p_block = block_New( p_dec, i_size );
1591
1592     p_buffer->p_buffer = p_block->p_buffer;
1593     p_buffer->i_size = p_buffer->i_nb_bytes = p_block->i_buffer;
1594     p_buffer->i_nb_samples = i_samples;
1595     p_block->i_samples = i_samples;
1596
1597     return p_buffer;
1598 }
1599
1600 static void audio_del_buffer( decoder_t *p_dec, aout_buffer_t *p_buffer )
1601 {
1602     if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
1603     if( p_buffer ) free( p_buffer );
1604 }
1605
1606 /*
1607  * video
1608  */
1609 static int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_t *id )
1610 {
1611     sout_stream_sys_t *p_sys = p_stream->p_sys;
1612     int i;
1613
1614     /* Open decoder
1615      * Initialization of decoder structures
1616      */
1617     id->p_decoder->fmt_out = id->p_decoder->fmt_in;
1618     id->p_decoder->fmt_out.i_extra = 0;
1619     id->p_decoder->fmt_out.p_extra = 0;
1620     id->p_decoder->pf_decode_video = 0;
1621     id->p_decoder->pf_vout_buffer_new = video_new_buffer_decoder;
1622     id->p_decoder->pf_vout_buffer_del = video_del_buffer_decoder;
1623     id->p_decoder->pf_picture_link    = video_link_picture_decoder;
1624     id->p_decoder->pf_picture_unlink  = video_unlink_picture_decoder;
1625     id->p_decoder->p_owner = malloc( sizeof(decoder_owner_sys_t) );
1626     for( i = 0; i < PICTURE_RING_SIZE; i++ )
1627         id->p_decoder->p_owner->pp_pics[i] = 0;
1628     id->p_decoder->p_owner->p_sys = p_sys;
1629     /* id->p_decoder->p_cfg = p_sys->p_video_cfg; */
1630
1631     id->p_decoder->p_module =
1632         module_Need( id->p_decoder, "decoder", "$codec", 0 );
1633
1634     if( !id->p_decoder->p_module )
1635     {
1636         msg_Err( p_stream, "cannot find decoder" );
1637         return VLC_EGENERIC;
1638     }
1639
1640     /*
1641      * Open encoder.
1642      * Because some info about the decoded input will only be available
1643      * once the first frame is decoded, we actually only test the availability
1644      * of the encoder here.
1645      */
1646
1647     /* Initialization of encoder format structures */
1648     es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1649                     id->p_decoder->fmt_out.i_codec );
1650     id->p_encoder->fmt_in.video.i_chroma = id->p_decoder->fmt_out.i_codec;
1651
1652     /* The dimensions will be set properly later on.
1653      * Just put sensible values so we can test an encoder is available. */
1654     id->p_encoder->fmt_in.video.i_width =
1655         id->p_encoder->fmt_out.video.i_width ?
1656         id->p_encoder->fmt_out.video.i_width :
1657         id->p_decoder->fmt_in.video.i_width ?
1658         id->p_decoder->fmt_in.video.i_width : 16;
1659     id->p_encoder->fmt_in.video.i_height =
1660         id->p_encoder->fmt_out.video.i_height ?
1661         id->p_encoder->fmt_out.video.i_height :
1662         id->p_decoder->fmt_in.video.i_height ?
1663         id->p_decoder->fmt_in.video.i_height : 16;
1664     id->p_encoder->fmt_in.video.i_frame_rate = 25;
1665     id->p_encoder->fmt_in.video.i_frame_rate_base = 1;
1666
1667     id->p_encoder->i_threads = p_sys->i_threads;
1668     id->p_encoder->p_cfg = p_sys->p_video_cfg;
1669
1670     id->p_encoder->p_module =
1671         module_Need( id->p_encoder, "encoder", p_sys->psz_venc, VLC_TRUE );
1672     if( !id->p_encoder->p_module )
1673     {
1674         msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_venc );
1675         module_Unneed( id->p_decoder, id->p_decoder->p_module );
1676         id->p_decoder->p_module = 0;
1677         return VLC_EGENERIC;
1678     }
1679
1680     /* Close the encoder.
1681      * We'll open it only when we have the first frame. */
1682     module_Unneed( id->p_encoder, id->p_encoder->p_module );
1683     if( id->p_encoder->fmt_out.p_extra )
1684         free( id->p_encoder->fmt_out.p_extra );
1685     id->p_encoder->p_module = NULL;
1686
1687     if( p_sys->i_threads >= 1 )
1688     {
1689         int i_priority = p_sys->b_high_priority ? VLC_THREAD_PRIORITY_OUTPUT :
1690                            VLC_THREAD_PRIORITY_VIDEO;
1691         p_sys->id_video = id;
1692         vlc_mutex_init( p_stream, &p_sys->lock_out );
1693         vlc_cond_init( p_stream, &p_sys->cond );
1694         memset( p_sys->pp_pics, 0, sizeof(p_sys->pp_pics) );
1695         p_sys->i_first_pic = 0;
1696         p_sys->i_last_pic = 0;
1697         p_sys->p_buffers = NULL;
1698         p_sys->b_die = p_sys->b_error = 0;
1699         if( vlc_thread_create( p_sys, "encoder", EncoderThread, i_priority,
1700                                VLC_FALSE ) )
1701         {
1702             msg_Err( p_stream, "cannot spawn encoder thread" );
1703             module_Unneed( id->p_decoder, id->p_decoder->p_module );
1704             id->p_decoder->p_module = 0;
1705             return VLC_EGENERIC;
1706         }
1707     }
1708
1709     return VLC_SUCCESS;
1710 }
1711
1712 static int transcode_video_encoder_open( sout_stream_t *p_stream,
1713                                          sout_stream_id_t *id )
1714 {
1715     sout_stream_sys_t *p_sys = p_stream->p_sys;
1716
1717      /* Calculate scaling, padding, cropping etc. */
1718      /* width/height of source */
1719      int i_src_width = id->p_decoder->fmt_out.video.i_width;
1720      int i_src_height = id->p_decoder->fmt_out.video.i_height;
1721
1722      /* with/height scaling */
1723      float f_scale_width = 1;
1724      float f_scale_height = 1;
1725
1726      /* width/height of output stream */
1727      int i_dst_width;
1728      int i_dst_height;
1729
1730      /* aspect ratio */
1731      float f_aspect = (float)id->p_decoder->fmt_out.video.i_aspect /
1732                              VOUT_ASPECT_FACTOR;
1733
1734      msg_Dbg( p_stream, "decoder aspect is %i:%i",
1735                   id->p_decoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
1736
1737      /* Change f_aspect from source frame to source pixel */
1738      f_aspect = f_aspect * i_src_height / i_src_width;
1739      msg_Dbg( p_stream, "source pixel aspect is %f:1", f_aspect );
1740
1741      /* width/height after cropping */
1742      p_sys->i_src_x_offset = p_sys->i_crop_left & ~1;
1743      p_sys->i_src_y_offset = p_sys->i_crop_top & ~1;
1744      p_sys->i_crop_width = i_src_width - ( p_sys->i_crop_left & ~1 ) -
1745                             ( p_sys->i_crop_right & ~1 );
1746      p_sys->i_crop_height = i_src_height - ( p_sys->i_crop_top & ~1 ) -
1747                             ( p_sys->i_crop_bottom & ~1 );
1748
1749     /* Calculate scaling factor for specified parameters */
1750     if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1751         id->p_encoder->fmt_out.video.i_height <= 0 && p_sys->f_scale )
1752     {
1753         /* Global scaling. Make sure width will remain a factor of 16 */
1754         float f_real_scale;
1755         int  i_new_height;
1756         int i_new_width = i_src_width * p_sys->f_scale;
1757
1758         if( i_new_width % 16 <= 7 && i_new_width >= 16 )
1759             i_new_width -= i_new_width % 16;
1760         else
1761             i_new_width += 16 - i_new_width % 16;
1762
1763         f_real_scale = (float)( i_new_width ) / (float) i_src_width;
1764
1765         i_new_height = __MAX( 16, i_src_height * (float)f_real_scale );
1766
1767         f_scale_width = f_real_scale;
1768         f_scale_height = (float) i_new_height / (float) i_src_height;
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 width specified */
1774         f_scale_width = (float)id->p_encoder->fmt_out.video.i_width /
1775                              p_sys->i_crop_width;
1776         f_scale_height = f_scale_width;
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          /* Only height specified */
1782          f_scale_height = (float)id->p_encoder->fmt_out.video.i_height /
1783                               p_sys->i_crop_height;
1784          f_scale_width = f_scale_height;
1785      }
1786      else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1787               id->p_encoder->fmt_out.video.i_height > 0 )
1788      {
1789          /* Width and height specified */
1790          f_scale_width = (float)id->p_encoder->fmt_out.video.i_width
1791                                / p_sys->i_crop_width;
1792          f_scale_height = (float)id->p_encoder->fmt_out.video.i_height
1793                                / p_sys->i_crop_height;
1794      }
1795
1796      /* check maxwidth and maxheight
1797       * note: maxwidth and maxheight currently does not handle
1798       * canvas and padding, just scaling and cropping.
1799       */
1800      if( p_sys->i_maxwidth && f_scale_width > (float)p_sys->i_maxwidth /
1801                                                      p_sys->i_crop_width )
1802      {
1803          f_scale_width = (float)p_sys->i_maxwidth / p_sys->i_crop_width;
1804      }
1805      if( p_sys->i_maxheight && f_scale_height > (float)p_sys->i_maxheight /
1806                                                        p_sys->i_crop_height )
1807      {
1808          f_scale_height = (float)p_sys->i_maxheight / p_sys->i_crop_height;
1809      }
1810
1811      /* Change aspect ratio from source pixel to scaled pixel */
1812      f_aspect = f_aspect * f_scale_height / f_scale_width;
1813      msg_Dbg( p_stream, "scaled pixel aspect is %f:1", f_aspect );
1814
1815      /* Correct scaling for target aspect ratio
1816       * Shrink video if necessary
1817       */
1818      if ( p_sys->i_canvas_aspect > 0 )
1819      {
1820          float f_target_aspect = (float)p_sys->i_canvas_aspect /
1821                                         VOUT_ASPECT_FACTOR;
1822
1823          if( p_sys->i_canvas_width > 0 && p_sys->i_canvas_height > 0)
1824          {
1825              /* Calculate pixel aspect of canvas */
1826              f_target_aspect = f_target_aspect / p_sys->i_canvas_width *
1827                                p_sys->i_canvas_height;
1828          }
1829          if( f_target_aspect > f_aspect )
1830          {
1831              /* Reduce width scale to increase aspect */
1832              f_scale_width = f_scale_width * f_aspect / f_target_aspect;
1833          }
1834          else
1835          {
1836              /* Reduce height scale to decrease aspect */
1837              f_scale_height = f_scale_height * f_target_aspect / f_aspect;
1838          }
1839          f_aspect = f_target_aspect;
1840          msg_Dbg( p_stream, "canvas scaled pixel aspect is %f:1", f_aspect );
1841      }
1842
1843      /* f_scale_width and f_scale_height are now final */
1844      /* Calculate width, height from scaling
1845       * Make sure its multiple of 2
1846       */
1847      i_dst_width = 2 * (int)( p_sys->i_crop_width * f_scale_width / 2 + 0.5 );
1848      i_dst_height = 2 *
1849                     (int)( p_sys->i_crop_height * f_scale_height / 2 + 0.5 );
1850
1851      p_sys->i_nopadd_width = i_dst_width;
1852      p_sys->i_nopadd_height = i_dst_height;
1853      p_sys->i_dst_x_offset = 0;
1854      p_sys->i_dst_y_offset = 0;
1855
1856      /* Handle canvas and padding */
1857      if( p_sys->i_canvas_width <= 0 )
1858      {
1859          /* No canvas width set, add explicit padding border */
1860          i_dst_width = p_sys->i_nopadd_width + ( p_sys->i_padd_left & ~1 ) +
1861                       ( p_sys->i_padd_right & ~1 );
1862          p_sys->i_dst_x_offset = ( p_sys->i_padd_left & ~1 );
1863      }
1864      else
1865      {
1866          /* Canvas set, check if we have to padd or crop */
1867          if( p_sys->i_canvas_width < p_sys->i_nopadd_width )
1868          {
1869              /* need to crop more, but keep same scaling */
1870              int i_crop = 2 * (int)( ( p_sys->i_canvas_width & ~1 ) /
1871                                        f_scale_width / 2 + 0.5 );
1872
1873              p_sys->i_src_x_offset += ( ( p_sys->i_crop_width - i_crop ) / 2 )
1874                                            & ~1;
1875              p_sys->i_crop_width = i_crop;
1876              i_dst_width = p_sys->i_canvas_width & ~1;
1877              p_sys->i_nopadd_width = i_dst_width;
1878          }
1879          else if( p_sys->i_canvas_width > p_sys->i_nopadd_width )
1880          {
1881              /* need to padd */
1882              i_dst_width = p_sys->i_canvas_width & ~1;
1883              p_sys->i_dst_x_offset = ( i_dst_width - p_sys->i_nopadd_width )/2;
1884              p_sys->i_dst_x_offset = p_sys->i_dst_x_offset & ~1;
1885          }
1886      }
1887
1888      if( p_sys->i_canvas_height <= 0 )
1889      {
1890          /* No canvas set, add padding border */
1891          i_dst_height = p_sys->i_nopadd_height + ( p_sys->i_padd_top & ~1 ) +
1892                         ( p_sys->i_padd_bottom & ~1 );
1893          p_sys->i_dst_y_offset = ( p_sys->i_padd_top & ~1 );
1894      }
1895      else
1896      {
1897          /* Canvas set, check if we have to padd or crop */
1898          if( p_sys->i_canvas_height < p_sys->i_nopadd_height )
1899          {
1900              /* need to crop more, but keep same scaling */
1901              int i_crop = 2 * (int)( ( p_sys->i_canvas_height & ~1 ) /
1902                                         f_scale_height / 2 + 0.5 );
1903
1904              p_sys->i_src_y_offset += ( ( p_sys->i_crop_height - i_crop ) / 2 )
1905                                                 & ~1;
1906              p_sys->i_crop_height = i_crop;
1907              i_dst_height = p_sys->i_canvas_height & ~1;
1908              p_sys->i_nopadd_height = i_dst_height;
1909          }
1910          else if( p_sys->i_canvas_height > p_sys->i_nopadd_height )
1911          {
1912              /* need to padd */
1913              i_dst_height = p_sys->i_canvas_height & ~1;
1914              p_sys->i_dst_y_offset = ( i_dst_height - p_sys->i_nopadd_height )
1915                                         /2;
1916              p_sys->i_dst_y_offset = p_sys->i_dst_y_offset & ~1;
1917          }
1918      }
1919
1920      /* Change aspect ratio from scaled pixel to output frame */
1921      f_aspect = f_aspect * i_dst_width / i_dst_height;
1922
1923      /* Store calculated values */
1924      id->p_encoder->fmt_out.video.i_width = i_dst_width;
1925      id->p_encoder->fmt_out.video.i_height = i_dst_height;
1926
1927      id->p_encoder->fmt_in.video.i_width = i_dst_width;
1928      id->p_encoder->fmt_in.video.i_height = i_dst_height;
1929
1930      msg_Dbg( p_stream, "source %ix%i, crop %ix%i, "
1931                         "destination %ix%i, padding %ix%i",
1932          i_src_width, i_src_height,
1933          p_sys->i_crop_width, p_sys->i_crop_height,
1934          p_sys->i_nopadd_width, p_sys->i_nopadd_height,
1935          i_dst_width, i_dst_height
1936      );
1937
1938     /* Handle frame rate conversion */
1939     if( !id->p_encoder->fmt_out.video.i_frame_rate ||
1940         !id->p_encoder->fmt_out.video.i_frame_rate_base )
1941     {
1942         if( id->p_decoder->fmt_out.video.i_frame_rate &&
1943             id->p_decoder->fmt_out.video.i_frame_rate_base )
1944         {
1945             id->p_encoder->fmt_out.video.i_frame_rate =
1946                 id->p_decoder->fmt_out.video.i_frame_rate;
1947             id->p_encoder->fmt_out.video.i_frame_rate_base =
1948                 id->p_decoder->fmt_out.video.i_frame_rate_base;
1949         }
1950         else
1951         {
1952             /* Pick a sensible default value */
1953             id->p_encoder->fmt_out.video.i_frame_rate = 25;
1954             id->p_encoder->fmt_out.video.i_frame_rate_base = 1;
1955         }
1956     }
1957
1958     id->p_encoder->fmt_in.video.i_frame_rate =
1959         id->p_encoder->fmt_out.video.i_frame_rate;
1960     id->p_encoder->fmt_in.video.i_frame_rate_base =
1961         id->p_encoder->fmt_out.video.i_frame_rate_base;
1962
1963     date_Init( &id->interpolated_pts,
1964                id->p_encoder->fmt_out.video.i_frame_rate,
1965                id->p_encoder->fmt_out.video.i_frame_rate_base );
1966
1967     /* Check whether a particular aspect ratio was requested */
1968     if( !id->p_encoder->fmt_out.video.i_aspect )
1969     {
1970         id->p_encoder->fmt_out.video.i_aspect = (int)( f_aspect * VOUT_ASPECT_FACTOR + 0.5 );
1971     }
1972     id->p_encoder->fmt_in.video.i_aspect =
1973         id->p_encoder->fmt_out.video.i_aspect;
1974
1975     msg_Dbg( p_stream, "encoder aspect is %i:%i", id->p_encoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
1976
1977     id->p_encoder->p_module =
1978         module_Need( id->p_encoder, "encoder", p_sys->psz_venc, VLC_TRUE );
1979     if( !id->p_encoder->p_module )
1980     {
1981         msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_venc );
1982         return VLC_EGENERIC;
1983     }
1984
1985     id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
1986
1987     /* Hack for mp2v/mp1v transcoding support */
1988     if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','1','v') ||
1989         id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','2','v') )
1990     {
1991         id->p_encoder->fmt_out.i_codec = VLC_FOURCC('m','p','g','v');
1992     }
1993
1994     id->id = p_stream->p_sys->p_out->pf_add( p_stream->p_sys->p_out,
1995                                              &id->p_encoder->fmt_out );
1996     if( !id->id )
1997     {
1998         msg_Err( p_stream, "cannot add this stream" );
1999         return VLC_EGENERIC;
2000     }
2001
2002     return VLC_SUCCESS;
2003 }
2004
2005 static void transcode_video_close( sout_stream_t *p_stream,
2006                                    sout_stream_id_t *id )
2007 {
2008     int i, j;
2009
2010     if( p_stream->p_sys->i_threads >= 1 )
2011     {
2012         vlc_mutex_lock( &p_stream->p_sys->lock_out );
2013         p_stream->p_sys->b_die = 1;
2014         vlc_cond_signal( &p_stream->p_sys->cond );
2015         vlc_mutex_unlock( &p_stream->p_sys->lock_out );
2016         vlc_thread_join( p_stream->p_sys );
2017         vlc_mutex_destroy( &p_stream->p_sys->lock_out );
2018         vlc_cond_destroy( &p_stream->p_sys->cond );
2019     }
2020
2021     /* Close decoder */
2022     if( id->p_decoder->p_module )
2023         module_Unneed( id->p_decoder, id->p_decoder->p_module );
2024
2025     if( id->p_decoder->p_owner )
2026     {
2027         /* Clean-up pictures ring buffer */
2028         for( i = 0; i < PICTURE_RING_SIZE; i++ )
2029         {
2030             if( id->p_decoder->p_owner->pp_pics[i] )
2031                 video_del_buffer( VLC_OBJECT(id->p_decoder),
2032                                   id->p_decoder->p_owner->pp_pics[i] );
2033         }
2034         free( id->p_decoder->p_owner );
2035     }
2036
2037     /* Close encoder */
2038     if( id->p_encoder->p_module )
2039         module_Unneed( id->p_encoder, id->p_encoder->p_module );
2040
2041     /* Close filters */
2042     for( i = 0; i < id->i_filter; i++ )
2043     {
2044         vlc_object_detach( id->pp_filter[i] );
2045         if( id->pp_filter[i]->p_module )
2046             module_Unneed( id->pp_filter[i], id->pp_filter[i]->p_module );
2047
2048         /* Clean-up pictures ring buffer */
2049         for( j = 0; j < PICTURE_RING_SIZE; j++ )
2050         {
2051             if( id->pp_filter[i]->p_owner->pp_pics[j] )
2052                 video_del_buffer( VLC_OBJECT(id->pp_filter[i]),
2053                                   id->pp_filter[i]->p_owner->pp_pics[j] );
2054         }
2055         free( id->pp_filter[i]->p_owner );
2056         vlc_object_destroy( id->pp_filter[i] );
2057         id->pp_filter[i] = NULL;
2058     }
2059
2060     for( i = 0; i < id->i_ufilter; i++ )
2061     {
2062         vlc_object_detach( id->pp_ufilter[i] );
2063         if( id->pp_ufilter[i]->p_module )
2064             module_Unneed( id->pp_ufilter[i], id->pp_ufilter[i]->p_module );
2065
2066         /* Clean-up pictures ring buffer */
2067         for( j = 0; j < PICTURE_RING_SIZE; j++ )
2068         {
2069             if( id->pp_ufilter[i]->p_owner->pp_pics[j] )
2070                 video_del_buffer( VLC_OBJECT(id->pp_ufilter[i]),
2071                                   id->pp_ufilter[i]->p_owner->pp_pics[j] );
2072         }
2073         free( id->pp_ufilter[i]->p_owner );
2074         vlc_object_destroy( id->pp_ufilter[i] );
2075         id->pp_ufilter[i] = NULL;
2076     }
2077 }
2078
2079 static int transcode_video_process( sout_stream_t *p_stream,
2080                                     sout_stream_id_t *id,
2081                                     block_t *in, block_t **out )
2082 {
2083     sout_stream_sys_t *p_sys = p_stream->p_sys;
2084     int i_duplicate = 1, i;
2085     picture_t *p_pic, *p_pic2 = NULL;
2086     *out = NULL;
2087     input_thread_t *p_input = NULL;
2088
2089     if( p_stream->p_parent->p_parent && p_stream->p_parent->p_parent->
2090                                 i_object_type == VLC_OBJECT_INPUT )
2091         p_input = (input_thread_t *)p_stream->p_parent->p_parent;
2092
2093     while( (p_pic = id->p_decoder->pf_decode_video( id->p_decoder, &in )) )
2094     {
2095         subpicture_t *p_subpic = 0;
2096         if( p_input )
2097             stats_UpdateInteger( p_input, p_input->counters.p_decoded_video,
2098                                  1, NULL );
2099
2100         if( p_stream->p_sout->i_out_pace_nocontrol && p_sys->b_hurry_up )
2101         {
2102             mtime_t current_date = mdate();
2103             if( current_date + 50000 > p_pic->date )
2104             {
2105                 msg_Dbg( p_stream, "late picture skipped ("I64Fd")",
2106                          current_date + 50000 - p_pic->date );
2107                 p_pic->pf_release( p_pic );
2108                 continue;
2109             }
2110         }
2111
2112         if( p_sys->b_master_sync )
2113         {
2114             mtime_t i_video_drift;
2115             mtime_t i_master_drift = p_sys->i_master_drift;
2116             mtime_t i_pts;
2117
2118             i_pts = date_Get( &id->interpolated_pts ) + 1;
2119             if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2120                   || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2121             {
2122                 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2123                 date_Set( &id->interpolated_pts, p_pic->date );
2124                 i_pts = p_pic->date + 1;
2125             }
2126             i_video_drift = p_pic->date - i_pts;
2127             i_duplicate = 1;
2128
2129             /* Set the pts of the frame being encoded */
2130             p_pic->date = i_pts;
2131
2132             if( i_video_drift < i_master_drift - 50000 )
2133             {
2134 #if 0
2135                 msg_Dbg( p_stream, "dropping frame (%i)",
2136                          (int)(i_video_drift - i_master_drift) );
2137 #endif
2138                 p_pic->pf_release( p_pic );
2139                 continue;
2140             }
2141             else if( i_video_drift > i_master_drift + 50000 )
2142             {
2143 #if 0
2144                 msg_Dbg( p_stream, "adding frame (%i)",
2145                          (int)(i_video_drift - i_master_drift) );
2146 #endif
2147                 i_duplicate = 2;
2148             }
2149         }
2150
2151         if( !id->p_encoder->p_module )
2152         {
2153             if( transcode_video_encoder_open( p_stream, id ) != VLC_SUCCESS )
2154             {
2155                 p_pic->pf_release( p_pic );
2156                 transcode_video_close( p_stream, id );
2157                 id->b_transcode = VLC_FALSE;
2158                 return VLC_EGENERIC;
2159             }
2160
2161             /* Deinterlace */
2162             if( p_stream->p_sys->b_deinterlace )
2163             {
2164                 id->pp_filter[id->i_filter] =
2165                     vlc_object_create( p_stream, VLC_OBJECT_FILTER );
2166                 vlc_object_attach( id->pp_filter[id->i_filter], p_stream );
2167
2168                 id->pp_filter[id->i_filter]->pf_vout_buffer_new =
2169                     video_new_buffer_filter;
2170                 id->pp_filter[id->i_filter]->pf_vout_buffer_del =
2171                     video_del_buffer_filter;
2172
2173                 id->pp_filter[id->i_filter]->fmt_in = id->p_decoder->fmt_out;
2174                 id->pp_filter[id->i_filter]->fmt_out = id->p_decoder->fmt_out;
2175                 id->pp_filter[id->i_filter]->p_cfg = p_sys->p_deinterlace_cfg;
2176                 id->pp_filter[id->i_filter]->p_module =
2177                     module_Need( id->pp_filter[id->i_filter],
2178                                  "video filter2", p_sys->psz_deinterlace, 0 );
2179                 if( id->pp_filter[id->i_filter]->p_module )
2180                 {
2181                     id->pp_filter[id->i_filter]->p_owner =
2182                         malloc( sizeof(filter_owner_sys_t) );
2183                     for( i = 0; i < PICTURE_RING_SIZE; i++ )
2184                         id->pp_filter[id->i_filter]->p_owner->pp_pics[i] = 0;
2185                     id->pp_filter[id->i_filter]->p_owner->p_sys = p_sys;
2186
2187                     id->i_filter++;
2188                 }
2189                 else
2190                 {
2191                     msg_Dbg( p_stream, "no video filter found" );
2192                     vlc_object_detach( id->pp_filter[id->i_filter] );
2193                     vlc_object_destroy( id->pp_filter[id->i_filter] );
2194                 }
2195             }
2196
2197             /* Check if we need a filter for chroma conversion or resizing */
2198             if( id->p_decoder->fmt_out.video.i_chroma !=
2199                 id->p_encoder->fmt_in.video.i_chroma ||
2200
2201                 (int)id->p_decoder->fmt_out.video.i_width != p_sys->i_crop_width ||
2202                 p_sys->i_crop_width != p_sys->i_nopadd_width ||
2203                 p_sys->i_nopadd_width != (int)id->p_encoder->fmt_out.video.i_width ||
2204
2205                 (int)id->p_decoder->fmt_out.video.i_height != p_sys->i_crop_height ||
2206                 p_sys->i_crop_height != p_sys->i_nopadd_height ||
2207                 p_sys->i_nopadd_height != (int)id->p_encoder->fmt_out.video.i_height)
2208             {
2209                 id->pp_filter[id->i_filter] =
2210                     vlc_object_create( p_stream, VLC_OBJECT_FILTER );
2211                 vlc_object_attach( id->pp_filter[id->i_filter], p_stream );
2212
2213                 id->pp_filter[id->i_filter]->pf_vout_buffer_new =
2214                     video_new_buffer_filter;
2215                 id->pp_filter[id->i_filter]->pf_vout_buffer_del =
2216                     video_del_buffer_filter;
2217
2218                 id->pp_filter[id->i_filter]->fmt_in = id->p_decoder->fmt_out;
2219                 id->pp_filter[id->i_filter]->fmt_out = id->p_encoder->fmt_in;
2220                 id->pp_filter[id->i_filter]->p_cfg = NULL;
2221
2222                 id->pp_filter[id->i_filter]->fmt_in.video.i_x_offset = p_sys->i_src_x_offset;
2223                 id->pp_filter[id->i_filter]->fmt_in.video.i_y_offset = p_sys->i_src_y_offset;
2224                 id->pp_filter[id->i_filter]->fmt_in.video.i_visible_width = p_sys->i_crop_width;
2225                 id->pp_filter[id->i_filter]->fmt_in.video.i_visible_height = p_sys->i_crop_height;
2226
2227                 id->pp_filter[id->i_filter]->fmt_out.video.i_x_offset = p_sys->i_dst_x_offset;
2228                 id->pp_filter[id->i_filter]->fmt_out.video.i_y_offset = p_sys->i_dst_y_offset;
2229                 id->pp_filter[id->i_filter]->fmt_out.video.i_visible_width = p_sys->i_nopadd_width;
2230                 id->pp_filter[id->i_filter]->fmt_out.video.i_visible_height = p_sys->i_nopadd_height;
2231
2232                 id->pp_filter[id->i_filter]->p_module =
2233                     module_Need( id->pp_filter[id->i_filter],
2234                                  "crop padd", 0, 0 );
2235                 if( id->pp_filter[id->i_filter]->p_module )
2236                 {
2237                     id->pp_filter[id->i_filter]->p_owner =
2238                         malloc( sizeof(filter_owner_sys_t) );
2239                     for( i = 0; i < PICTURE_RING_SIZE; i++ )
2240                         id->pp_filter[id->i_filter]->p_owner->pp_pics[i] = 0;
2241                     id->pp_filter[id->i_filter]->p_owner->p_sys = p_sys;
2242
2243                     id->i_filter++;
2244                 }
2245                 else
2246                 {
2247                     msg_Dbg( p_stream, "no video filter found" );
2248                     vlc_object_detach( id->pp_filter[id->i_filter] );
2249                     vlc_object_destroy( id->pp_filter[id->i_filter] );
2250
2251                     p_pic->pf_release( p_pic );
2252                     transcode_video_close( p_stream, id );
2253                     id->b_transcode = VLC_FALSE;
2254                     return VLC_EGENERIC;
2255                 }
2256             }
2257
2258             for( i = 0; (i < p_sys->i_vfilters) && (id->i_ufilter < TRANSCODE_FILTERS); i++ )
2259             {
2260                 id->pp_ufilter[id->i_ufilter] =
2261                     vlc_object_create( p_stream, VLC_OBJECT_FILTER );
2262                 vlc_object_attach( id->pp_ufilter[id->i_ufilter], p_stream );
2263
2264                 id->pp_ufilter[id->i_ufilter]->pf_vout_buffer_new =
2265                     video_new_buffer_filter;
2266                 id->pp_ufilter[id->i_ufilter]->pf_vout_buffer_del =
2267                     video_del_buffer_filter;
2268
2269                 id->pp_ufilter[id->i_ufilter]->fmt_in = id->p_encoder->fmt_in;
2270                 id->pp_ufilter[id->i_ufilter]->fmt_out = id->p_encoder->fmt_in;
2271                 id->pp_ufilter[id->i_ufilter]->p_cfg = p_sys->p_vfilters_cfg[i];
2272                 id->pp_ufilter[id->i_ufilter]->p_module =
2273                     module_Need( id->pp_ufilter[id->i_ufilter],
2274                           "video filter2", p_sys->psz_vfilters[i], 0 );
2275                 if( id->pp_ufilter[id->i_ufilter]->p_module )
2276                 {
2277                     id->pp_ufilter[id->i_ufilter]->p_owner =
2278                         malloc( sizeof(filter_owner_sys_t) );
2279                     for( i = 0; i < PICTURE_RING_SIZE; i++ )
2280                         id->pp_ufilter[id->i_ufilter]->p_owner->pp_pics[i] = 0;
2281                     id->pp_ufilter[id->i_ufilter]->p_owner->p_sys = p_sys;
2282                     id->i_ufilter++;
2283                 }
2284                 else
2285                 {
2286                     msg_Dbg( p_stream, "no video filter found" );
2287                     vlc_object_detach( id->pp_ufilter[id->i_ufilter] );
2288                     vlc_object_destroy( id->pp_ufilter[id->i_ufilter] );
2289                 }
2290             }
2291         }
2292
2293         /* Run filter chain */
2294         for( i = 0; i < id->i_filter; i++ )
2295         {
2296             p_pic = id->pp_filter[i]->pf_video_filter(id->pp_filter[i], p_pic);
2297         }
2298
2299         /*
2300          * Encoding
2301          */
2302
2303         /* Check if we have a subpicture to overlay */
2304         if( p_sys->p_spu )
2305         {
2306             p_subpic = spu_SortSubpictures( p_sys->p_spu, p_pic->date );
2307             /* TODO: get another pic */
2308         }
2309
2310         /* Overlay subpicture */
2311         if( p_subpic )
2312         {
2313             int i_scale_width, i_scale_height;
2314             video_format_t *p_fmt;
2315
2316             i_scale_width = id->p_encoder->fmt_in.video.i_width * 1000 /
2317                 id->p_decoder->fmt_out.video.i_width;
2318             i_scale_height = id->p_encoder->fmt_in.video.i_height * 1000 /
2319                 id->p_decoder->fmt_out.video.i_height;
2320
2321             if( p_pic->i_refcount && !id->i_filter )
2322             {
2323                 /* We can't modify the picture, we need to duplicate it */
2324                 picture_t *p_tmp = video_new_buffer_decoder( id->p_decoder );
2325                 if( p_tmp )
2326                 {
2327                     vout_CopyPicture( p_stream, p_tmp, p_pic );
2328                     p_pic->pf_release( p_pic );
2329                     p_pic = p_tmp;
2330                 }
2331             }
2332
2333             if( id->i_filter )
2334                 p_fmt = &id->pp_filter[id->i_filter -1]->fmt_out.video;
2335             else
2336                 p_fmt = &id->p_decoder->fmt_out.video;
2337
2338             /* FIXME (shouldn't have to be done here) */
2339             p_fmt->i_sar_num = p_fmt->i_aspect *
2340                 p_fmt->i_height / p_fmt->i_width;
2341             p_fmt->i_sar_den = VOUT_ASPECT_FACTOR;
2342
2343             spu_RenderSubpictures( p_sys->p_spu, p_fmt, p_pic, p_pic, p_subpic,
2344                                    i_scale_width, i_scale_height );
2345         }
2346
2347         /* Run user specified filter chain */
2348         for( i = 0; i < id->i_ufilter; i++ )
2349         {
2350             p_pic = id->pp_ufilter[i]->pf_video_filter(id->pp_ufilter[i], p_pic);
2351         }
2352
2353         if( p_sys->i_threads == 0 )
2354         {
2355             block_t *p_block;
2356             p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
2357             block_ChainAppend( out, p_block );
2358         }
2359
2360         if( p_sys->b_master_sync )
2361         {
2362             mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
2363             if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2364                   || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2365             {
2366                 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2367                 date_Set( &id->interpolated_pts, p_pic->date );
2368                 i_pts = p_pic->date + 1;
2369             }
2370             date_Increment( &id->interpolated_pts, 1 );
2371         }
2372
2373         if( p_sys->b_master_sync && i_duplicate > 1 )
2374         {
2375             mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
2376             if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2377                   || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2378             {
2379                 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2380                 date_Set( &id->interpolated_pts, p_pic->date );
2381                 i_pts = p_pic->date + 1;
2382             }
2383             date_Increment( &id->interpolated_pts, 1 );
2384
2385             if( p_sys->i_threads >= 1 )
2386             {
2387                 /* We can't modify the picture, we need to duplicate it */
2388                 p_pic2 = video_new_buffer_decoder( id->p_decoder );
2389                 if( p_pic2 != NULL )
2390                 {
2391                     vout_CopyPicture( p_stream, p_pic2, p_pic );
2392                     p_pic2->date = i_pts;
2393                 }
2394             }
2395             else
2396             {
2397                 block_t *p_block;
2398                 p_pic->date = i_pts;
2399                 p_block = id->p_encoder->pf_encode_video(id->p_encoder, p_pic);
2400                 block_ChainAppend( out, p_block );
2401             }
2402         }
2403
2404         if( p_sys->i_threads == 0 )
2405         {
2406             p_pic->pf_release( p_pic );
2407         }
2408         else
2409         {
2410             vlc_mutex_lock( &p_sys->lock_out );
2411             p_sys->pp_pics[p_sys->i_last_pic++] = p_pic;
2412             p_sys->i_last_pic %= PICTURE_RING_SIZE;
2413             *out = p_sys->p_buffers;
2414             p_sys->p_buffers = NULL;
2415             if( p_pic2 != NULL )
2416             {
2417                 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic2;
2418                 p_sys->i_last_pic %= PICTURE_RING_SIZE;
2419             }
2420             vlc_cond_signal( &p_sys->cond );
2421             vlc_mutex_unlock( &p_sys->lock_out );
2422         }
2423     }
2424
2425     return VLC_SUCCESS;
2426 }
2427
2428 static int EncoderThread( sout_stream_sys_t *p_sys )
2429 {
2430     sout_stream_id_t *id = p_sys->id_video;
2431     picture_t *p_pic;
2432
2433     while( !p_sys->b_die && !p_sys->b_error )
2434     {
2435         block_t *p_block;
2436
2437         vlc_mutex_lock( &p_sys->lock_out );
2438         while( p_sys->i_last_pic == p_sys->i_first_pic )
2439         {
2440             vlc_cond_wait( &p_sys->cond, &p_sys->lock_out );
2441             if( p_sys->b_die || p_sys->b_error ) break;
2442         }
2443         if( p_sys->b_die || p_sys->b_error )
2444         {
2445             vlc_mutex_unlock( &p_sys->lock_out );
2446             break;
2447         }
2448
2449         p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2450         p_sys->i_first_pic %= PICTURE_RING_SIZE;
2451         vlc_mutex_unlock( &p_sys->lock_out );
2452
2453         p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
2454         vlc_mutex_lock( &p_sys->lock_out );
2455         block_ChainAppend( &p_sys->p_buffers, p_block );
2456
2457         vlc_mutex_unlock( &p_sys->lock_out );
2458         p_pic->pf_release( p_pic );
2459     }
2460
2461     while( p_sys->i_last_pic != p_sys->i_first_pic )
2462     {
2463         p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2464         p_sys->i_first_pic %= PICTURE_RING_SIZE;
2465         p_pic->pf_release( p_pic );
2466     }
2467     block_ChainRelease( p_sys->p_buffers );
2468
2469     return 0;
2470 }
2471
2472 struct picture_sys_t
2473 {
2474     vlc_object_t *p_owner;
2475 };
2476
2477 static void video_release_buffer( picture_t *p_pic )
2478 {
2479     if( p_pic && !p_pic->i_refcount && p_pic->pf_release && p_pic->p_sys )
2480     {
2481         video_del_buffer_decoder( (decoder_t *)p_pic->p_sys->p_owner, p_pic );
2482     }
2483     else if( p_pic && p_pic->i_refcount > 0 ) p_pic->i_refcount--;
2484 }
2485
2486 static picture_t *video_new_buffer( vlc_object_t *p_this, picture_t **pp_ring,
2487                                     sout_stream_sys_t *p_sys )
2488 {
2489     decoder_t *p_dec = (decoder_t *)p_this;
2490     picture_t *p_pic;
2491     int i;
2492
2493     /* Find an empty space in the picture ring buffer */
2494     for( i = 0; i < PICTURE_RING_SIZE; i++ )
2495     {
2496         if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
2497         {
2498             pp_ring[i]->i_status = RESERVED_PICTURE;
2499             return pp_ring[i];
2500         }
2501     }
2502     for( i = 0; i < PICTURE_RING_SIZE; i++ )
2503     {
2504         if( pp_ring[i] == 0 ) break;
2505     }
2506
2507     if( i == PICTURE_RING_SIZE && p_sys->i_threads >= 1 )
2508     {
2509         int i_first_pic = p_sys->i_first_pic;
2510
2511         if( p_sys->i_first_pic != p_sys->i_last_pic )
2512         {
2513             /* Encoder still has stuff to encode, wait to clear-up the list */
2514             while( p_sys->i_first_pic == i_first_pic )
2515                 msleep( 100000 );
2516         }
2517
2518         /* Find an empty space in the picture ring buffer */
2519         for( i = 0; i < PICTURE_RING_SIZE; i++ )
2520         {
2521             if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
2522             {
2523                 pp_ring[i]->i_status = RESERVED_PICTURE;
2524                 return pp_ring[i];
2525             }
2526         }
2527         for( i = 0; i < PICTURE_RING_SIZE; i++ )
2528         {
2529             if( pp_ring[i] == 0 ) break;
2530         }
2531     }
2532
2533     if( i == PICTURE_RING_SIZE )
2534     {
2535         msg_Err( p_this, "decoder/filter is leaking pictures, "
2536                  "resetting its ring buffer" );
2537
2538         for( i = 0; i < PICTURE_RING_SIZE; i++ )
2539         {
2540             pp_ring[i]->pf_release( pp_ring[i] );
2541         }
2542
2543         i = 0;
2544     }
2545
2546     p_pic = malloc( sizeof(picture_t) );
2547     p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
2548     vout_AllocatePicture( VLC_OBJECT(p_dec), p_pic,
2549                           p_dec->fmt_out.video.i_chroma,
2550                           p_dec->fmt_out.video.i_width,
2551                           p_dec->fmt_out.video.i_height,
2552                           p_dec->fmt_out.video.i_aspect );
2553
2554     if( !p_pic->i_planes )
2555     {
2556         free( p_pic );
2557         return 0;
2558     }
2559
2560     p_pic->pf_release = video_release_buffer;
2561     p_pic->p_sys = malloc( sizeof(picture_sys_t) );
2562     p_pic->p_sys->p_owner = p_this;
2563     p_pic->i_status = RESERVED_PICTURE;
2564
2565     pp_ring[i] = p_pic;
2566     return p_pic;
2567 }
2568
2569 static picture_t *video_new_buffer_decoder( decoder_t *p_dec )
2570 {
2571     return video_new_buffer( VLC_OBJECT(p_dec),
2572                              p_dec->p_owner->pp_pics, p_dec->p_owner->p_sys );
2573 }
2574
2575 static picture_t *video_new_buffer_filter( filter_t *p_filter )
2576 {
2577     return video_new_buffer( VLC_OBJECT(p_filter),
2578                              p_filter->p_owner->pp_pics,
2579                              p_filter->p_owner->p_sys );
2580 }
2581
2582 static void video_del_buffer( vlc_object_t *p_this, picture_t *p_pic )
2583 {
2584     if( p_pic && p_pic->p_data_orig ) free( p_pic->p_data_orig );
2585     if( p_pic && p_pic->p_sys ) free( p_pic->p_sys );
2586     if( p_pic ) free( p_pic );
2587 }
2588
2589 static void video_del_buffer_decoder( decoder_t *p_decoder, picture_t *p_pic )
2590 {
2591     p_pic->i_refcount = 0;
2592     p_pic->i_status = DESTROYED_PICTURE;
2593 }
2594
2595 static void video_del_buffer_filter( filter_t *p_filter, picture_t *p_pic )
2596 {
2597     p_pic->i_refcount = 0;
2598     p_pic->i_status = DESTROYED_PICTURE;
2599 }
2600
2601 static void video_link_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2602 {
2603     p_pic->i_refcount++;
2604 }
2605
2606 static void video_unlink_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2607 {
2608     video_release_buffer( p_pic );
2609 }
2610
2611 /*
2612  * SPU
2613  */
2614 static subpicture_t *spu_new_buffer( decoder_t * );
2615 static void spu_del_buffer( decoder_t *, subpicture_t * );
2616
2617 static int transcode_spu_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2618 {
2619     sout_stream_sys_t *p_sys = p_stream->p_sys;
2620
2621     /*
2622      * Open decoder
2623      */
2624
2625     /* Initialization of decoder structures */
2626     id->p_decoder->pf_spu_buffer_new = spu_new_buffer;
2627     id->p_decoder->pf_spu_buffer_del = spu_del_buffer;
2628     id->p_decoder->p_owner = (decoder_owner_sys_t *)p_stream;
2629     /* id->p_decoder->p_cfg = p_sys->p_spu_cfg; */
2630
2631     id->p_decoder->p_module =
2632         module_Need( id->p_decoder, "decoder", "$codec", 0 );
2633
2634     if( !id->p_decoder->p_module )
2635     {
2636         msg_Err( p_stream, "cannot find decoder" );
2637         return VLC_EGENERIC;
2638     }
2639
2640     if( !p_sys->b_soverlay )
2641     {
2642         /* Open encoder */
2643         /* Initialization of encoder format structures */
2644         es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
2645                         id->p_decoder->fmt_in.i_codec );
2646
2647         id->p_encoder->p_cfg = p_sys->p_spu_cfg;
2648
2649         id->p_encoder->p_module =
2650             module_Need( id->p_encoder, "encoder", p_sys->psz_senc, VLC_TRUE );
2651
2652         if( !id->p_encoder->p_module )
2653         {
2654             module_Unneed( id->p_decoder, id->p_decoder->p_module );
2655             msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_senc );
2656             return VLC_EGENERIC;
2657         }
2658     }
2659
2660     if( !p_sys->p_spu )
2661     {
2662         p_sys->p_spu = spu_Create( p_stream );
2663         spu_Init( p_sys->p_spu );
2664     }
2665
2666     return VLC_SUCCESS;
2667 }
2668
2669 static void transcode_spu_close( sout_stream_t *p_stream, sout_stream_id_t *id)
2670 {
2671     /* Close decoder */
2672     if( id->p_decoder->p_module )
2673         module_Unneed( id->p_decoder, id->p_decoder->p_module );
2674
2675     /* Close encoder */
2676     if( id->p_encoder->p_module )
2677         module_Unneed( id->p_encoder, id->p_encoder->p_module );
2678 }
2679
2680 static int transcode_spu_process( sout_stream_t *p_stream,
2681                                   sout_stream_id_t *id,
2682                                   block_t *in, block_t **out )
2683 {
2684     sout_stream_sys_t *p_sys = p_stream->p_sys;
2685     subpicture_t *p_subpic;
2686     *out = NULL;
2687
2688     p_subpic = id->p_decoder->pf_decode_sub( id->p_decoder, &in );
2689     if( !p_subpic ) return VLC_EGENERIC;
2690
2691     if( p_sys->b_master_sync && p_sys->i_master_drift )
2692     {
2693         p_subpic->i_start -= p_sys->i_master_drift;
2694         if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2695     }
2696
2697     if( p_sys->b_soverlay )
2698     {
2699         spu_DisplaySubpicture( p_sys->p_spu, p_subpic );
2700     }
2701     else
2702     {
2703         block_t *p_block;
2704
2705         p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
2706         spu_del_buffer( id->p_decoder, p_subpic );
2707
2708         if( p_block )
2709         {
2710             block_ChainAppend( out, p_block );
2711             return VLC_SUCCESS;
2712         }
2713     }
2714
2715     return VLC_EGENERIC;
2716 }
2717
2718 static subpicture_t *spu_new_buffer( decoder_t *p_dec )
2719 {
2720     sout_stream_t *p_stream = (sout_stream_t *)p_dec->p_owner;
2721     return spu_CreateSubpicture( p_stream->p_sys->p_spu );
2722 }
2723
2724 static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_subpic )
2725 {
2726     sout_stream_t *p_stream = (sout_stream_t *)p_dec->p_owner;
2727     spu_DestroySubpicture( p_stream->p_sys->p_spu, p_subpic );
2728 }
2729
2730 /*
2731  * OSD menu
2732  */
2733 static int transcode_osd_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2734 {
2735     sout_stream_sys_t *p_sys = p_stream->p_sys;
2736     es_format_t fmt;
2737
2738     fmt.i_cat = SPU_ES;
2739     fmt.i_id = 0xbd1f; /* pid ?? */
2740     fmt.i_group = 3;   /* pmt entry ?? */
2741     fmt.i_codec = VLC_FOURCC( 'Y', 'U', 'V', 'A' );
2742     fmt.psz_language = strdup( "osd" );
2743
2744     id = malloc( sizeof( sout_stream_id_t ) );
2745     memset( id, 0, sizeof(sout_stream_id_t) );
2746
2747     id->id = NULL;
2748     id->p_decoder = NULL;
2749     id->p_encoder = NULL;
2750
2751     /* Create encoder object */
2752     id->p_encoder = vlc_object_create( p_stream, VLC_OBJECT_ENCODER );
2753     if( !id->p_encoder )
2754     {
2755         msg_Err( p_stream, "out of memory" );
2756         goto error;
2757     }
2758     vlc_object_attach( id->p_encoder, p_stream );
2759     id->p_encoder->p_module = NULL;
2760
2761     /* Create fake destination format */
2762     es_format_Init( &id->p_encoder->fmt_out, fmt.i_cat, 0 );
2763     id->p_encoder->fmt_out.i_id    = fmt.i_id;
2764     id->p_encoder->fmt_out.i_group = fmt.i_group;
2765     id->p_encoder->fmt_out.psz_language = strdup( fmt.psz_language );
2766
2767     if( p_sys->i_osdcodec != 0 || p_sys->psz_osdenc )
2768     {
2769         msg_Dbg( p_stream, "creating osdmenu transcoding from fcc=`%4.4s' "
2770                  "to fcc=`%4.4s'", (char*)&fmt.i_codec,
2771                  (char*)&p_sys->i_osdcodec );
2772
2773         /* Complete destination format */
2774         id->p_encoder->fmt_out.i_codec = p_sys->i_osdcodec;
2775
2776         /* Open encoder */
2777         /* Initialization of encoder format structures */
2778         es_format_Init( &id->p_encoder->fmt_in, fmt.i_cat, fmt.i_codec );
2779         id->p_encoder->fmt_in.psz_language = strdup( fmt.psz_language );
2780
2781         id->p_encoder->p_cfg = p_sys->p_osd_cfg;
2782
2783         id->p_encoder->p_module =
2784             module_Need( id->p_encoder, "encoder", p_sys->psz_osdenc, VLC_TRUE );
2785
2786         if( !id->p_encoder->p_module )
2787         {
2788             msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_osdenc );
2789             goto error;
2790         }
2791
2792         /* open output stream */
2793         id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
2794         id->b_transcode = VLC_TRUE;
2795
2796         if( !id->id ) goto error;
2797     }
2798     else
2799     {
2800         msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
2801                  (char*)&fmt.i_codec );
2802         id->id = p_sys->p_out->pf_add( p_sys->p_out, &fmt );
2803         id->b_transcode = VLC_FALSE;
2804
2805         if( !id->id ) goto error;
2806     }
2807
2808     p_sys->id_osd = id;
2809     p_sys->b_es_osd = VLC_TRUE;
2810
2811     if( !p_sys->p_spu )
2812     {
2813         p_sys->p_spu = spu_Create( p_stream );
2814         if( spu_Init( p_sys->p_spu ) != VLC_SUCCESS )
2815             msg_Err( p_sys, "spu initialisation failed" );
2816     }
2817
2818     if( fmt.psz_language )
2819         free( fmt.psz_language );
2820
2821     return VLC_SUCCESS;
2822
2823  error:
2824     msg_Err( p_stream, "starting osd encoding thread failed" );
2825     if( id->p_encoder->p_module )
2826             module_Unneed( id->p_encoder, id->p_encoder->p_module );
2827     if( id->p_encoder )
2828     {
2829         vlc_object_detach( id->p_encoder );
2830         vlc_object_destroy( id->p_encoder );
2831     }
2832     if( fmt.psz_language ) free( fmt.psz_language );
2833     if( id ) free( id );
2834     p_sys->id_osd = NULL;
2835     p_sys->b_es_osd = VLC_FALSE;
2836     return VLC_EGENERIC;
2837 }
2838
2839 static void transcode_osd_close( sout_stream_t *p_stream, sout_stream_id_t *id)
2840 {
2841     sout_stream_sys_t *p_sys = p_stream->p_sys;
2842
2843     /* Close encoder */
2844     if( p_sys->b_es_osd && id )
2845     {
2846         if( id->p_encoder->p_module )
2847             module_Unneed( id->p_encoder, id->p_encoder->p_module );
2848
2849         if( id->id ) p_sys->p_out->pf_del( p_sys->p_out, id->id );
2850
2851         if( id->p_encoder )
2852         {
2853             vlc_object_detach( id->p_encoder );
2854             vlc_object_destroy( id->p_encoder );
2855         }
2856     }
2857     p_sys->b_es_osd = VLC_FALSE;
2858     if( id ) free( id );
2859 }
2860
2861 static int transcode_osd_process( sout_stream_t *p_stream,
2862                                   sout_stream_id_t *id,
2863                                   block_t *in, block_t **out )
2864 {
2865     sout_stream_sys_t *p_sys = p_stream->p_sys;
2866     subpicture_t *p_subpic = NULL;
2867
2868     /* Check if we have a subpicture to send */
2869     if( p_sys->p_spu && in->i_dts > 0)
2870     {
2871         p_subpic = spu_SortSubpictures( p_sys->p_spu, in->i_dts );
2872     }
2873     else
2874     {
2875         msg_Warn( p_stream, "spu channel not initialized, doing it now" );
2876         if( !p_sys->p_spu )
2877         {
2878             p_sys->p_spu = spu_Create( p_stream );
2879             if( spu_Init( p_sys->p_spu ) != VLC_SUCCESS )
2880                 msg_Err( p_stream, "spu initialisation failed" );
2881         }
2882     }
2883
2884     if( p_subpic )
2885     {
2886         block_t *p_block = NULL;
2887
2888         if( p_sys->b_master_sync && p_sys->i_master_drift )
2889         {
2890             p_subpic->i_start -= p_sys->i_master_drift;
2891             if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2892         }
2893
2894         p_block = p_sys->id_osd->p_encoder->pf_encode_sub( p_sys->id_osd->p_encoder, p_subpic );
2895         if( p_block )
2896         {
2897             p_block->i_dts = p_block->i_pts = in->i_dts;
2898             block_ChainAppend( out, p_block );
2899             if( *out )
2900             {
2901                 if( p_sys->p_out->pf_send( p_sys->p_out, p_sys->id_osd->id, *out ) == VLC_SUCCESS )
2902                     spu_DestroySubpicture( p_sys->p_spu, p_subpic );
2903             }
2904             return VLC_SUCCESS;
2905         }
2906     }
2907     return VLC_EGENERIC;
2908 }