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