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