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