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