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