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