]> git.sesse.net Git - vlc/blob - modules/stream_out/transcode.c
Strings review in stream_out (Refs:#438). Please review these once more as I changed...
[vlc] / modules / stream_out / transcode.c
1 /*****************************************************************************
2  * transcode.c: transcoding stream output module
3  *****************************************************************************
4  * Copyright (C) 2003-2004 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *          Gildas Bazin <gbazin@videolan.org>
9  *          Jean-Paul Saman <jpsaman #_at_# m2x dot nl>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24  *****************************************************************************/
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include <stdlib.h>
30 #include <string.h>
31 #include <math.h>
32
33 #include <vlc/vlc.h>
34 #include <vlc/input.h>
35 #include <vlc/sout.h>
36 #include <vlc/vout.h>
37 #include <vlc/decoder.h>
38 #include "vlc_filter.h"
39 #include "vlc_osd.h"
40
41 #define MASTER_SYNC_MAX_DRIFT 100000
42
43 /*****************************************************************************
44  * Module descriptor
45  *****************************************************************************/
46 #define VENC_TEXT N_("Video encoder")
47 #define VENC_LONGTEXT N_( \
48     "This is the video encoder module that will be used (and its associated "\
49     "options).")
50 #define VCODEC_TEXT N_("Destination video codec")
51 #define VCODEC_LONGTEXT N_( \
52     "This is the video codec that will be used.")
53 #define VB_TEXT N_("Video bitrate")
54 #define VB_LONGTEXT N_( \
55     "Target bitrate of the transcoded video stream." )
56 #define SCALE_TEXT N_("Video scaling")
57 #define SCALE_LONGTEXT N_( \
58     "Scale factor to apply to the video while transcoding (eg: 0.25)")
59 #define FPS_TEXT N_("Video frame-rate")
60 #define FPS_LONGTEXT N_( \
61     "Target output frame rate for the video stream." )
62 #define DEINTERLACE_TEXT N_("Deinterlace video")
63 #define DEINTERLACE_LONGTEXT N_( \
64     "Deinterlace the video before encoding." )
65 #define DEINTERLACE_MODULE_TEXT N_("Deinterlace module")
66 #define DEINTERLACE_MODULE_LONGTEXT N_( \
67     "Specify the deinterlace module to use." )
68 #define WIDTH_TEXT N_("Video width")
69 #define WIDTH_LONGTEXT N_( \
70     "Output video width." )
71 #define HEIGHT_TEXT N_("Video height")
72 #define HEIGHT_LONGTEXT N_( \
73     "Output video height." )
74 #define MAXWIDTH_TEXT N_("Maximum video width")
75 #define MAXWIDTH_LONGTEXT N_( \
76     "Maximum output video width." )
77 #define MAXHEIGHT_TEXT N_("Maximum video height")
78 #define MAXHEIGHT_LONGTEXT N_( \
79     "Maximum output video height." )
80 #define VFILTER_TEXT N_("Video filter")
81 #define VFILTER_LONGTEXT N_( \
82     "Video filters will be applied to the video streams (after overlays " \
83     "are applied). You must enter a comma-separated list of filters." )
84
85 #define CROPTOP_TEXT N_("Video crop (top)")
86 #define CROPTOP_LONGTEXT N_( \
87     "Number of pixels to crop at the top of the video." )
88 #define CROPLEFT_TEXT N_("Video crop (left)")
89 #define CROPLEFT_LONGTEXT N_( \
90     "Number of pixels to crop at the left of the video." )
91 #define CROPBOTTOM_TEXT N_("Video crop (bottom)")
92 #define CROPBOTTOM_LONGTEXT N_( \
93     "Number of pixels to crop at the bottom of the video." )
94 #define CROPRIGHT_TEXT N_("Video crop (right)")
95 #define CROPRIGHT_LONGTEXT N_( \
96     "Number of pixels to crop at the right of the video." )
97
98 #define PADDTOP_TEXT N_("Video padding (top)")
99 #define PADDTOP_LONGTEXT N_( \
100     "Size of the black border to add at the top of the video." )
101 #define PADDLEFT_TEXT N_("Video padding (left)")
102 #define PADDLEFT_LONGTEXT N_( \
103     "Size of the black border to add at the left of the video." )
104 #define PADDBOTTOM_TEXT N_("Video padding (bottom)")
105 #define PADDBOTTOM_LONGTEXT N_( \
106     "Size of the black border to add at the bottom of the video." )
107 #define PADDRIGHT_TEXT N_("Video padding (right)")
108 #define PADDRIGHT_LONGTEXT N_( \
109     "Size of the black border to add at the right of the video." )
110
111 #define CANVAS_WIDTH_TEXT N_("Video canvas width")
112 #define CANVAS_WIDTH_LONGTEXT N_( \
113     "This will automatically crod and pad the video to a specified width." )
114 #define CANVAS_HEIGHT_TEXT N_("Video canvas height")
115 #define CANVAS_HEIGHT_LONGTEXT N_( \
116     "This will automatically crod and pad the video to a specified height." )
117 #define CANVAS_ASPECT_TEXT N_("Video canvas aspect ratio")
118 #define CANVAS_ASPECT_LONGTEXT N_( \
119     "This sets aspect (like 4:3) of the video canvas and letterbox the video "\
120     "accordingly." )
121
122 #define AENC_TEXT N_("Audio encoder")
123 #define AENC_LONGTEXT N_( \
124     "This is the audio encoder module that will be used (and its associated "\
125     "options).")
126 #define ACODEC_TEXT N_("Destination audio codec")
127 #define ACODEC_LONGTEXT N_( \
128     "This is the audio codec that will be used.")
129 #define AB_TEXT N_("Audio bitrate")
130 #define AB_LONGTEXT N_( \
131     "Target bitrate of the transcoded audio stream." )
132 #define ARATE_TEXT N_("Audio sample rate")
133 #define ARATE_LONGTEXT N_( \
134  "Sample rate of the transcoded audio stream (11250, 22500, 44100 or 48000).")
135 #define ACHANS_TEXT N_("Audio channels")
136 #define ACHANS_LONGTEXT N_( \
137     "Number of audio channels in the transcoded streams." )
138
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" );
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
1423     while( (p_audio_buf = id->p_decoder->pf_decode_audio( id->p_decoder,
1424                                                           &in )) )
1425     {
1426         stats_UpdateInteger( p_stream->p_parent->p_parent, STATS_DECODED_AUDIO,
1427                              1, NULL );
1428         if( p_sys->b_master_sync )
1429         {
1430             mtime_t i_dts = date_Get( &id->interpolated_pts ) + 1;
1431             if ( p_audio_buf->start_date - i_dts > MASTER_SYNC_MAX_DRIFT
1432                   || p_audio_buf->start_date - i_dts < -MASTER_SYNC_MAX_DRIFT )
1433             {
1434                 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
1435                 date_Set( &id->interpolated_pts, p_audio_buf->start_date );
1436                 i_dts = p_audio_buf->start_date + 1;
1437             }
1438             p_sys->i_master_drift = p_audio_buf->start_date - i_dts;
1439             date_Increment( &id->interpolated_pts, p_audio_buf->i_nb_samples );
1440             p_audio_buf->start_date -= p_sys->i_master_drift;
1441             p_audio_buf->end_date -= p_sys->i_master_drift;
1442         }
1443
1444         p_audio_block = p_audio_buf->p_sys;
1445         p_audio_block->i_buffer = p_audio_buf->i_nb_bytes;
1446         p_audio_block->i_dts = p_audio_block->i_pts =
1447             p_audio_buf->start_date;
1448         p_audio_block->i_length = p_audio_buf->end_date -
1449             p_audio_buf->start_date;
1450         p_audio_block->i_samples = p_audio_buf->i_nb_samples;
1451
1452         /* Run filter chain */
1453         for( i = 0; i < id->i_filter; i++ )
1454         {
1455             p_audio_block =
1456                 id->pp_filter[i]->pf_audio_filter( id->pp_filter[i],
1457                                                    p_audio_block );
1458         }
1459
1460         p_audio_buf->p_buffer = p_audio_block->p_buffer;
1461         p_audio_buf->i_nb_bytes = p_audio_block->i_buffer;
1462         p_audio_buf->i_nb_samples = p_audio_block->i_samples;
1463         p_audio_buf->start_date = p_audio_block->i_dts;
1464         p_audio_buf->end_date = p_audio_block->i_dts + p_audio_block->i_length;
1465
1466         p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf );
1467         block_ChainAppend( out, p_block );
1468         block_Release( p_audio_block );
1469         free( p_audio_buf );
1470     }
1471
1472     return VLC_SUCCESS;
1473 }
1474
1475 static void audio_release_buffer( aout_buffer_t *p_buffer )
1476 {
1477     if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
1478     if( p_buffer ) free( p_buffer );
1479 }
1480
1481 static aout_buffer_t *audio_new_buffer( decoder_t *p_dec, int i_samples )
1482 {
1483     aout_buffer_t *p_buffer;
1484     block_t *p_block;
1485     int i_size;
1486
1487     if( p_dec->fmt_out.audio.i_bitspersample )
1488     {
1489         i_size = i_samples * p_dec->fmt_out.audio.i_bitspersample / 8 *
1490             p_dec->fmt_out.audio.i_channels;
1491     }
1492     else if( p_dec->fmt_out.audio.i_bytes_per_frame &&
1493              p_dec->fmt_out.audio.i_frame_length )
1494     {
1495         i_size = i_samples * p_dec->fmt_out.audio.i_bytes_per_frame /
1496             p_dec->fmt_out.audio.i_frame_length;
1497     }
1498     else
1499     {
1500         i_size = i_samples * 4 * p_dec->fmt_out.audio.i_channels;
1501     }
1502
1503     p_buffer = malloc( sizeof(aout_buffer_t) );
1504     p_buffer->pf_release = audio_release_buffer;
1505     p_buffer->p_sys = p_block = block_New( p_dec, i_size );
1506
1507     p_buffer->p_buffer = p_block->p_buffer;
1508     p_buffer->i_size = p_buffer->i_nb_bytes = p_block->i_buffer;
1509     p_buffer->i_nb_samples = i_samples;
1510     p_block->i_samples = i_samples;
1511
1512     return p_buffer;
1513 }
1514
1515 static void audio_del_buffer( decoder_t *p_dec, aout_buffer_t *p_buffer )
1516 {
1517     if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
1518     if( p_buffer ) free( p_buffer );
1519 }
1520
1521 /*
1522  * video
1523  */
1524 static int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_t *id )
1525 {
1526     sout_stream_sys_t *p_sys = p_stream->p_sys;
1527     int i;
1528
1529     /*
1530      * Open decoder
1531      */
1532
1533     /* Initialization of decoder structures */
1534     id->p_decoder->fmt_out = id->p_decoder->fmt_in;
1535     id->p_decoder->fmt_out.i_extra = 0;
1536     id->p_decoder->fmt_out.p_extra = 0;
1537     id->p_decoder->pf_decode_video = 0;
1538     id->p_decoder->pf_vout_buffer_new = video_new_buffer_decoder;
1539     id->p_decoder->pf_vout_buffer_del = video_del_buffer_decoder;
1540     id->p_decoder->pf_picture_link    = video_link_picture_decoder;
1541     id->p_decoder->pf_picture_unlink  = video_unlink_picture_decoder;
1542     id->p_decoder->p_owner = malloc( sizeof(decoder_owner_sys_t) );
1543     for( i = 0; i < PICTURE_RING_SIZE; i++ )
1544         id->p_decoder->p_owner->pp_pics[i] = 0;
1545     id->p_decoder->p_owner->p_sys = p_sys;
1546     /* id->p_decoder->p_cfg = p_sys->p_video_cfg; */
1547
1548     id->p_decoder->p_module =
1549         module_Need( id->p_decoder, "decoder", "$codec", 0 );
1550
1551     if( !id->p_decoder->p_module )
1552     {
1553         msg_Err( p_stream, "cannot find decoder" );
1554         return VLC_EGENERIC;
1555     }
1556
1557     /*
1558      * Open encoder.
1559      * Because some info about the decoded input will only be available
1560      * once the first frame is decoded, we actually only test the availability
1561      * of the encoder here.
1562      */
1563
1564     /* Initialization of encoder format structures */
1565     es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1566                     id->p_decoder->fmt_out.i_codec );
1567     id->p_encoder->fmt_in.video.i_chroma = id->p_decoder->fmt_out.i_codec;
1568
1569     /* The dimensions will be set properly later on.
1570      * Just put sensible values so we can test an encoder is available. */
1571     id->p_encoder->fmt_in.video.i_width =
1572         id->p_encoder->fmt_out.video.i_width ?
1573         id->p_encoder->fmt_out.video.i_width :
1574         id->p_decoder->fmt_in.video.i_width ?
1575         id->p_decoder->fmt_in.video.i_width : 16;
1576     id->p_encoder->fmt_in.video.i_height =
1577         id->p_encoder->fmt_out.video.i_height ?
1578         id->p_encoder->fmt_out.video.i_height :
1579         id->p_decoder->fmt_in.video.i_height ?
1580         id->p_decoder->fmt_in.video.i_height : 16;
1581     id->p_encoder->fmt_in.video.i_frame_rate = 25;
1582     id->p_encoder->fmt_in.video.i_frame_rate_base = 1;
1583
1584     id->p_encoder->i_threads = p_sys->i_threads;
1585     id->p_encoder->p_cfg = p_sys->p_video_cfg;
1586
1587     id->p_encoder->p_module =
1588         module_Need( id->p_encoder, "encoder", p_sys->psz_venc, VLC_TRUE );
1589     if( !id->p_encoder->p_module )
1590     {
1591         msg_Err( p_stream, "cannot find encoder" );
1592         module_Unneed( id->p_decoder, id->p_decoder->p_module );
1593         id->p_decoder->p_module = 0;
1594         return VLC_EGENERIC;
1595     }
1596
1597     /* Close the encoder.
1598      * We'll open it only when we have the first frame. */
1599     module_Unneed( id->p_encoder, id->p_encoder->p_module );
1600     if( id->p_encoder->fmt_out.p_extra )
1601         free( id->p_encoder->fmt_out.p_extra );
1602     id->p_encoder->p_module = NULL;
1603
1604     if( p_sys->i_threads >= 1 )
1605     {
1606         int i_priority = p_sys->b_high_priority ? VLC_THREAD_PRIORITY_OUTPUT :
1607                            VLC_THREAD_PRIORITY_VIDEO;
1608         p_sys->id_video = id;
1609         vlc_mutex_init( p_stream, &p_sys->lock_out );
1610         vlc_cond_init( p_stream, &p_sys->cond );
1611         memset( p_sys->pp_pics, 0, sizeof(p_sys->pp_pics) );
1612         p_sys->i_first_pic = 0;
1613         p_sys->i_last_pic = 0;
1614         p_sys->p_buffers = NULL;
1615         p_sys->b_die = p_sys->b_error = 0;
1616         if( vlc_thread_create( p_sys, "encoder", EncoderThread, i_priority,
1617                                VLC_FALSE ) )
1618         {
1619             msg_Err( p_stream, "cannot spawn encoder thread" );
1620             module_Unneed( id->p_decoder, id->p_decoder->p_module );
1621             id->p_decoder->p_module = 0;
1622             return VLC_EGENERIC;
1623         }
1624     }
1625
1626     return VLC_SUCCESS;
1627 }
1628
1629 static int transcode_video_encoder_open( sout_stream_t *p_stream,
1630                                          sout_stream_id_t *id )
1631 {
1632     sout_stream_sys_t *p_sys = p_stream->p_sys;
1633
1634      /* Calculate scaling, padding, cropping etc. */
1635
1636      /* width/height of source */
1637      int i_src_width = id->p_decoder->fmt_out.video.i_width;
1638      int i_src_height = id->p_decoder->fmt_out.video.i_height;
1639
1640      /* with/height scaling */
1641      float f_scale_width = 1;
1642      float f_scale_height = 1;
1643
1644      /* width/height of output stream */
1645      int i_dst_width;
1646      int i_dst_height;
1647
1648      /* aspect ratio */
1649      float f_aspect = (float)id->p_decoder->fmt_out.video.i_aspect /
1650                              VOUT_ASPECT_FACTOR;
1651
1652      msg_Dbg( p_stream, "decoder aspect is %i:%i",
1653                   id->p_decoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
1654
1655      /* Change f_aspect from source frame to source pixel */
1656      f_aspect = f_aspect * i_src_height / i_src_width;
1657      msg_Dbg( p_stream, "source pixel aspect is %f:1", f_aspect );
1658
1659      /* width/height after cropping */
1660      p_sys->i_src_x_offset = p_sys->i_crop_left & ~1;
1661      p_sys->i_src_y_offset = p_sys->i_crop_top & ~1;
1662      p_sys->i_crop_width = i_src_width - ( p_sys->i_crop_left & ~1 ) -
1663                             ( p_sys->i_crop_right & ~1 );
1664      p_sys->i_crop_height = i_src_height - ( p_sys->i_crop_top & ~1 ) -
1665                             ( p_sys->i_crop_bottom & ~1 );
1666
1667     /* Calculate scaling factor for specified parameters */
1668     if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1669         id->p_encoder->fmt_out.video.i_height <= 0 && p_sys->f_scale )
1670     {
1671         /* Global scaling. Make sure width will remain a factor of 16 */
1672         float f_real_scale;
1673         int  i_new_height;
1674         int i_new_width = i_src_width * p_sys->f_scale;
1675
1676         if( i_new_width % 16 <= 7 && i_new_width >= 16 )
1677             i_new_width -= i_new_width % 16;
1678         else
1679             i_new_width += 16 - i_new_width % 16;
1680
1681         f_real_scale = (float)( i_new_width ) / (float) i_src_width;
1682
1683         i_new_height = __MAX( 16, i_src_height * (float)f_real_scale );
1684
1685         f_scale_width = f_real_scale;
1686         f_scale_height = (float) i_new_height / (float) i_src_height;
1687     }
1688     else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1689              id->p_encoder->fmt_out.video.i_height <= 0 )
1690     {
1691         /* Only width specified */
1692         f_scale_width = (float)id->p_encoder->fmt_out.video.i_width /
1693                              p_sys->i_crop_width;
1694         f_scale_height = f_scale_width;
1695     }
1696     else if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1697              id->p_encoder->fmt_out.video.i_height > 0 )
1698     {
1699          /* Only height specified */
1700          f_scale_height = (float)id->p_encoder->fmt_out.video.i_height /
1701                               p_sys->i_crop_height;
1702          f_scale_width = f_scale_height;
1703      }
1704      else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1705               id->p_encoder->fmt_out.video.i_height > 0 )
1706      {
1707          /* Width and height specified */
1708          f_scale_width = (float)id->p_encoder->fmt_out.video.i_width
1709                                / p_sys->i_crop_width;
1710          f_scale_height = (float)id->p_encoder->fmt_out.video.i_height
1711                                / p_sys->i_crop_height;
1712      }
1713
1714      /* check maxwidth and maxheight */
1715      /* note: maxwidth and maxheight currently does not handle
1716       * canvas and padding, just scaling and cropping. */
1717
1718      if( p_sys->i_maxwidth && f_scale_width > (float)p_sys->i_maxwidth /
1719                                                      p_sys->i_crop_width )
1720      {
1721          f_scale_width = (float)p_sys->i_maxwidth / p_sys->i_crop_width;
1722      }
1723      if( p_sys->i_maxheight && f_scale_height > (float)p_sys->i_maxheight /
1724                                                        p_sys->i_crop_height )
1725      {
1726          f_scale_height = (float)p_sys->i_maxheight / p_sys->i_crop_height;
1727      }
1728
1729      /* Change aspect ratio from source pixel to scaled pixel */
1730      f_aspect = f_aspect * f_scale_height / f_scale_width;
1731      msg_Dbg( p_stream, "scaled pixel aspect is %f:1", f_aspect );
1732
1733      /* Correct scaling for target aspect ratio */
1734      /* Shrink video if necessary */
1735      if ( p_sys->i_canvas_aspect > 0 )
1736      {
1737          float f_target_aspect = (float)p_sys->i_canvas_aspect /
1738                                         VOUT_ASPECT_FACTOR;
1739
1740          if( p_sys->i_canvas_width > 0 && p_sys->i_canvas_height > 0)
1741          {
1742              /* Calculate pixel aspect of canvas */
1743              f_target_aspect = f_target_aspect / p_sys->i_canvas_width *
1744                                p_sys->i_canvas_height;
1745          }
1746          if( f_target_aspect > f_aspect )
1747          {
1748              /* Reduce width scale to increase aspect */
1749              f_scale_width = f_scale_width * f_aspect / f_target_aspect;
1750          }
1751          else
1752          {
1753              /* Reduce height scale to decrease aspect */
1754              f_scale_height = f_scale_height * f_target_aspect / f_aspect;
1755          }
1756          f_aspect = f_target_aspect;
1757          msg_Dbg( p_stream, "canvas scaled pixel aspect is %f:1", f_aspect );
1758      }
1759
1760      /* f_scale_width and f_scale_height are now final */
1761
1762      /* Calculate width, height from scaling */
1763      /* Make sure its multiple of 2 */
1764
1765      i_dst_width = 2 * (int)( p_sys->i_crop_width * f_scale_width / 2 + 0.5 );
1766      i_dst_height = 2 *
1767                     (int)( p_sys->i_crop_height * f_scale_height / 2 + 0.5 );
1768
1769      p_sys->i_nopadd_width = i_dst_width;
1770      p_sys->i_nopadd_height = i_dst_height;
1771      p_sys->i_dst_x_offset = 0;
1772      p_sys->i_dst_y_offset = 0;
1773
1774      /* Handle canvas and padding */
1775
1776      if( p_sys->i_canvas_width <= 0 )
1777      {
1778          /* No canvas width set, add explicit padding border */
1779          i_dst_width = p_sys->i_nopadd_width + ( p_sys->i_padd_left & ~1 ) +
1780                       ( p_sys->i_padd_right & ~1 );
1781          p_sys->i_dst_x_offset = ( p_sys->i_padd_left & ~1 );
1782      }
1783      else
1784      {
1785          /* Canvas set, check if we have to padd or crop */
1786
1787          if( p_sys->i_canvas_width < p_sys->i_nopadd_width )
1788          {
1789              /* need to crop more, but keep same scaling */
1790              int i_crop = 2 * (int)( ( p_sys->i_canvas_width & ~1 ) /
1791                                        f_scale_width / 2 + 0.5 );
1792
1793              p_sys->i_src_x_offset += ( ( p_sys->i_crop_width - i_crop ) / 2 )
1794                                            & ~1;
1795              p_sys->i_crop_width = i_crop;
1796              i_dst_width = p_sys->i_canvas_width & ~1;
1797              p_sys->i_nopadd_width = i_dst_width;
1798          }
1799          else if( p_sys->i_canvas_width > p_sys->i_nopadd_width )
1800          {
1801              /* need to padd */
1802              i_dst_width = p_sys->i_canvas_width & ~1;
1803              p_sys->i_dst_x_offset = ( i_dst_width - p_sys->i_nopadd_width )/2;
1804              p_sys->i_dst_x_offset = p_sys->i_dst_x_offset & ~1;
1805          }
1806      }
1807
1808      if( p_sys->i_canvas_height <= 0 )
1809      {
1810          /* No canvas set, add padding border */
1811          i_dst_height = p_sys->i_nopadd_height + ( p_sys->i_padd_top & ~1 ) +
1812                         ( p_sys->i_padd_bottom & ~1 );
1813          p_sys->i_dst_y_offset = ( p_sys->i_padd_top & ~1 );
1814      }
1815      else
1816      {
1817          /* Canvas set, check if we have to padd or crop */
1818
1819          if( p_sys->i_canvas_height < p_sys->i_nopadd_height )
1820          {
1821              /* need to crop more, but keep same scaling */
1822              int i_crop = 2 * (int)( ( p_sys->i_canvas_height & ~1 ) /
1823                                         f_scale_height / 2 + 0.5 );
1824
1825              p_sys->i_src_y_offset += ( ( p_sys->i_crop_height - i_crop ) / 2 )
1826                                                 & ~1;
1827              p_sys->i_crop_height = i_crop;
1828              i_dst_height = p_sys->i_canvas_height & ~1;
1829              p_sys->i_nopadd_height = i_dst_height;
1830          }
1831          else if( p_sys->i_canvas_height > p_sys->i_nopadd_height )
1832          {
1833              /* need to padd */
1834              i_dst_height = p_sys->i_canvas_height & ~1;
1835              p_sys->i_dst_y_offset = ( i_dst_height - p_sys->i_nopadd_height )
1836                                         /2;
1837              p_sys->i_dst_y_offset = p_sys->i_dst_y_offset & ~1;
1838          }
1839      }
1840
1841
1842      /* Change aspect ratio from scaled pixel to output frame */
1843
1844      f_aspect = f_aspect * i_dst_width / i_dst_height;
1845
1846      /* Store calculated values */
1847      id->p_encoder->fmt_out.video.i_width = i_dst_width;
1848      id->p_encoder->fmt_out.video.i_height = i_dst_height;
1849
1850      id->p_encoder->fmt_in.video.i_width = i_dst_width;
1851      id->p_encoder->fmt_in.video.i_height = i_dst_height;
1852
1853      msg_Dbg( p_stream, "source %ix%i, crop %ix%i, "
1854                         "destination %ix%i, padding %ix%i",
1855          i_src_width, i_src_height,
1856          p_sys->i_crop_width, p_sys->i_crop_height,
1857          p_sys->i_nopadd_width, p_sys->i_nopadd_height,
1858          i_dst_width, i_dst_height
1859      );
1860
1861     /* Handle frame rate conversion */
1862     if( !id->p_encoder->fmt_out.video.i_frame_rate ||
1863         !id->p_encoder->fmt_out.video.i_frame_rate_base )
1864     {
1865         if( id->p_decoder->fmt_out.video.i_frame_rate &&
1866             id->p_decoder->fmt_out.video.i_frame_rate_base )
1867         {
1868             id->p_encoder->fmt_out.video.i_frame_rate =
1869                 id->p_decoder->fmt_out.video.i_frame_rate;
1870             id->p_encoder->fmt_out.video.i_frame_rate_base =
1871                 id->p_decoder->fmt_out.video.i_frame_rate_base;
1872         }
1873         else
1874         {
1875             /* Pick a sensible default value */
1876             id->p_encoder->fmt_out.video.i_frame_rate = 25;
1877             id->p_encoder->fmt_out.video.i_frame_rate_base = 1;
1878         }
1879     }
1880
1881     id->p_encoder->fmt_in.video.i_frame_rate =
1882         id->p_encoder->fmt_out.video.i_frame_rate;
1883     id->p_encoder->fmt_in.video.i_frame_rate_base =
1884         id->p_encoder->fmt_out.video.i_frame_rate_base;
1885
1886     date_Init( &id->interpolated_pts,
1887                id->p_encoder->fmt_out.video.i_frame_rate,
1888                id->p_encoder->fmt_out.video.i_frame_rate_base );
1889
1890     /* Check whether a particular aspect ratio was requested */
1891     if( !id->p_encoder->fmt_out.video.i_aspect )
1892     {
1893         id->p_encoder->fmt_out.video.i_aspect = (int)( f_aspect * VOUT_ASPECT_FACTOR + 0.5 );
1894     }
1895     id->p_encoder->fmt_in.video.i_aspect =
1896         id->p_encoder->fmt_out.video.i_aspect;
1897
1898     msg_Dbg( p_stream, "encoder aspect is %i:%i", id->p_encoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR );
1899
1900     id->p_encoder->p_module =
1901         module_Need( id->p_encoder, "encoder", p_sys->psz_venc, VLC_TRUE );
1902     if( !id->p_encoder->p_module )
1903     {
1904         msg_Err( p_stream, "cannot find encoder" );
1905         return VLC_EGENERIC;
1906     }
1907
1908     id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
1909
1910     /* Hack for mp2v/mp1v transcoding support */
1911     if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','1','v') ||
1912         id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','2','v') )
1913     {
1914         id->p_encoder->fmt_out.i_codec = VLC_FOURCC('m','p','g','v');
1915     }
1916
1917     id->id = p_stream->p_sys->p_out->pf_add( p_stream->p_sys->p_out,
1918                                              &id->p_encoder->fmt_out );
1919     if( !id->id )
1920     {
1921         msg_Err( p_stream, "cannot add this stream" );
1922         return VLC_EGENERIC;
1923     }
1924
1925     return VLC_SUCCESS;
1926 }
1927
1928 static void transcode_video_close( sout_stream_t *p_stream,
1929                                    sout_stream_id_t *id )
1930 {
1931     int i, j;
1932
1933     if( p_stream->p_sys->i_threads >= 1 )
1934     {
1935         vlc_mutex_lock( &p_stream->p_sys->lock_out );
1936         p_stream->p_sys->b_die = 1;
1937         vlc_cond_signal( &p_stream->p_sys->cond );
1938         vlc_mutex_unlock( &p_stream->p_sys->lock_out );
1939         vlc_thread_join( p_stream->p_sys );
1940         vlc_mutex_destroy( &p_stream->p_sys->lock_out );
1941         vlc_cond_destroy( &p_stream->p_sys->cond );
1942     }
1943
1944     /* Close decoder */
1945     if( id->p_decoder->p_module )
1946         module_Unneed( id->p_decoder, id->p_decoder->p_module );
1947
1948     if( id->p_decoder->p_owner )
1949     {
1950         /* Clean-up pictures ring buffer */
1951         for( i = 0; i < PICTURE_RING_SIZE; i++ )
1952         {
1953             if( id->p_decoder->p_owner->pp_pics[i] )
1954                 video_del_buffer( VLC_OBJECT(id->p_decoder),
1955                                   id->p_decoder->p_owner->pp_pics[i] );
1956         }
1957         free( id->p_decoder->p_owner );
1958     }
1959
1960     /* Close encoder */
1961     if( id->p_encoder->p_module )
1962         module_Unneed( id->p_encoder, id->p_encoder->p_module );
1963
1964     /* Close filters */
1965     for( i = 0; i < id->i_filter; i++ )
1966     {
1967         vlc_object_detach( id->pp_filter[i] );
1968         if( id->pp_filter[i]->p_module )
1969             module_Unneed( id->pp_filter[i], id->pp_filter[i]->p_module );
1970
1971         /* Clean-up pictures ring buffer */
1972         for( j = 0; j < PICTURE_RING_SIZE; j++ )
1973         {
1974             if( id->pp_filter[i]->p_owner->pp_pics[j] )
1975                 video_del_buffer( VLC_OBJECT(id->pp_filter[i]),
1976                                   id->pp_filter[i]->p_owner->pp_pics[j] );
1977         }
1978         free( id->pp_filter[i]->p_owner );
1979
1980         vlc_object_destroy( id->pp_filter[i] );
1981     }
1982     for( i = 0; i < id->i_vfilter; i++ )
1983     {
1984         vlc_object_detach( id->pp_vfilter[i] );
1985         if( id->pp_vfilter[i]->p_module )
1986             module_Unneed( id->pp_vfilter[i], id->pp_vfilter[i]->p_module );
1987
1988         /* Clean-up pictures ring buffer */
1989         for( j = 0; j < PICTURE_RING_SIZE; j++ )
1990         {
1991             if( id->pp_vfilter[i]->p_owner->pp_pics[j] )
1992                 video_del_buffer( VLC_OBJECT(id->pp_vfilter[i]),
1993                                   id->pp_vfilter[i]->p_owner->pp_pics[j] );
1994         }
1995         free( id->pp_vfilter[i]->p_owner );
1996
1997         vlc_object_destroy( id->pp_vfilter[i] );
1998     }
1999 }
2000
2001 static int transcode_video_process( sout_stream_t *p_stream,
2002                                     sout_stream_id_t *id,
2003                                     block_t *in, block_t **out )
2004 {
2005     sout_stream_sys_t *p_sys = p_stream->p_sys;
2006     int i_duplicate = 1, i;
2007     picture_t *p_pic, *p_pic2 = NULL;
2008     *out = NULL;
2009
2010     while( (p_pic = id->p_decoder->pf_decode_video( id->p_decoder, &in )) )
2011     {
2012         subpicture_t *p_subpic = 0;
2013         stats_UpdateInteger( p_stream->p_parent->p_parent, STATS_DECODED_VIDEO,
2014                               1, NULL );
2015
2016         if( p_stream->p_sout->i_out_pace_nocontrol && p_sys->b_hurry_up )
2017         {
2018             mtime_t current_date = mdate();
2019             if( current_date + 50000 > p_pic->date )
2020             {
2021                 msg_Dbg( p_stream, "late picture skipped ("I64Fd")",
2022                          current_date + 50000 - p_pic->date );
2023                 p_pic->pf_release( p_pic );
2024                 continue;
2025             }
2026         }
2027
2028         if( p_sys->b_master_sync )
2029         {
2030             mtime_t i_video_drift;
2031             mtime_t i_master_drift = p_sys->i_master_drift;
2032             mtime_t i_pts;
2033
2034             i_pts = date_Get( &id->interpolated_pts ) + 1;
2035             if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2036                   || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2037             {
2038                 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2039                 date_Set( &id->interpolated_pts, p_pic->date );
2040                 i_pts = p_pic->date + 1;
2041             }
2042             i_video_drift = p_pic->date - i_pts;
2043             i_duplicate = 1;
2044
2045             /* Set the pts of the frame being encoded */
2046             p_pic->date = i_pts;
2047
2048             if( i_video_drift < i_master_drift - 50000 )
2049             {
2050 #if 0
2051                 msg_Dbg( p_stream, "dropping frame (%i)",
2052                          (int)(i_video_drift - i_master_drift) );
2053 #endif
2054                 p_pic->pf_release( p_pic );
2055                 continue;
2056             }
2057             else if( i_video_drift > i_master_drift + 50000 )
2058             {
2059 #if 0
2060                 msg_Dbg( p_stream, "adding frame (%i)",
2061                          (int)(i_video_drift - i_master_drift) );
2062 #endif
2063                 i_duplicate = 2;
2064             }
2065         }
2066
2067         if( !id->p_encoder->p_module )
2068         {
2069             if( transcode_video_encoder_open( p_stream, id ) != VLC_SUCCESS )
2070             {
2071                 p_pic->pf_release( p_pic );
2072                 transcode_video_close( p_stream, id );
2073                 id->b_transcode = VLC_FALSE;
2074                 return VLC_EGENERIC;
2075             }
2076
2077             /* Deinterlace */
2078             if( p_stream->p_sys->b_deinterlace )
2079             {
2080                 id->pp_filter[id->i_filter] =
2081                     vlc_object_create( p_stream, VLC_OBJECT_FILTER );
2082                 vlc_object_attach( id->pp_filter[id->i_filter], p_stream );
2083
2084                 id->pp_filter[id->i_filter]->pf_vout_buffer_new =
2085                     video_new_buffer_filter;
2086                 id->pp_filter[id->i_filter]->pf_vout_buffer_del =
2087                     video_del_buffer_filter;
2088
2089                 id->pp_filter[id->i_filter]->fmt_in = id->p_decoder->fmt_out;
2090                 id->pp_filter[id->i_filter]->fmt_out = id->p_decoder->fmt_out;
2091                 id->pp_filter[id->i_filter]->p_cfg = p_sys->p_deinterlace_cfg;
2092                 id->pp_filter[id->i_filter]->p_module =
2093                     module_Need( id->pp_filter[id->i_filter],
2094                                  "video filter2", p_sys->psz_deinterlace, 0 );
2095                 if( id->pp_filter[id->i_filter]->p_module )
2096                 {
2097                     id->pp_filter[id->i_filter]->p_owner =
2098                         malloc( sizeof(filter_owner_sys_t) );
2099                     for( i = 0; i < PICTURE_RING_SIZE; i++ )
2100                         id->pp_filter[id->i_filter]->p_owner->pp_pics[i] = 0;
2101                     id->pp_filter[id->i_filter]->p_owner->p_sys = p_sys;
2102
2103                     id->i_filter++;
2104                 }
2105                 else
2106                 {
2107                     msg_Dbg( p_stream, "no video filter found" );
2108                     vlc_object_detach( id->pp_filter[id->i_filter] );
2109                     vlc_object_destroy( id->pp_filter[id->i_filter] );
2110                 }
2111             }
2112
2113             /* Check if we need a filter for chroma conversion or resizing */
2114             if( id->p_decoder->fmt_out.video.i_chroma !=
2115                 id->p_encoder->fmt_in.video.i_chroma ||
2116                 
2117                 (int)id->p_decoder->fmt_out.video.i_width != p_sys->i_crop_width ||
2118                 p_sys->i_crop_width != p_sys->i_nopadd_width ||
2119                 p_sys->i_nopadd_width != (int)id->p_encoder->fmt_out.video.i_width ||
2120                 
2121                 (int)id->p_decoder->fmt_out.video.i_height != p_sys->i_crop_height ||
2122                 p_sys->i_crop_height != p_sys->i_nopadd_height ||
2123                 p_sys->i_nopadd_height != (int)id->p_encoder->fmt_out.video.i_height)
2124             {
2125                 id->pp_filter[id->i_filter] =
2126                     vlc_object_create( p_stream, VLC_OBJECT_FILTER );
2127                 vlc_object_attach( id->pp_filter[id->i_filter], p_stream );
2128
2129                 id->pp_filter[id->i_filter]->pf_vout_buffer_new =
2130                     video_new_buffer_filter;
2131                 id->pp_filter[id->i_filter]->pf_vout_buffer_del =
2132                     video_del_buffer_filter;
2133
2134                 id->pp_filter[id->i_filter]->fmt_in = id->p_decoder->fmt_out;
2135                 id->pp_filter[id->i_filter]->fmt_out = id->p_encoder->fmt_in;
2136                 id->pp_filter[id->i_filter]->p_cfg = NULL;
2137
2138
2139                 id->pp_filter[id->i_filter]->fmt_in.video.i_x_offset = p_sys->i_src_x_offset;
2140                 id->pp_filter[id->i_filter]->fmt_in.video.i_y_offset = p_sys->i_src_y_offset;
2141                 id->pp_filter[id->i_filter]->fmt_in.video.i_visible_width = p_sys->i_crop_width;
2142                 id->pp_filter[id->i_filter]->fmt_in.video.i_visible_height = p_sys->i_crop_height;
2143
2144                 id->pp_filter[id->i_filter]->fmt_out.video.i_x_offset = p_sys->i_dst_x_offset;
2145                 id->pp_filter[id->i_filter]->fmt_out.video.i_y_offset = p_sys->i_dst_y_offset;
2146                 id->pp_filter[id->i_filter]->fmt_out.video.i_visible_width = p_sys->i_nopadd_width;
2147                 id->pp_filter[id->i_filter]->fmt_out.video.i_visible_height = p_sys->i_nopadd_height;
2148
2149                 id->pp_filter[id->i_filter]->p_module =
2150                     module_Need( id->pp_filter[id->i_filter],
2151                                  "crop padd", 0, 0 );
2152                 if( id->pp_filter[id->i_filter]->p_module )
2153                 {
2154                     id->pp_filter[id->i_filter]->p_owner =
2155                         malloc( sizeof(filter_owner_sys_t) );
2156                     for( i = 0; i < PICTURE_RING_SIZE; i++ )
2157                         id->pp_filter[id->i_filter]->p_owner->pp_pics[i] = 0;
2158                     id->pp_filter[id->i_filter]->p_owner->p_sys = p_sys;
2159
2160                     id->i_filter++;
2161                 }
2162                 else
2163                 {
2164                     msg_Dbg( p_stream, "no video filter found" );
2165                     vlc_object_detach( id->pp_filter[id->i_filter] );
2166                     vlc_object_destroy( id->pp_filter[id->i_filter] );
2167
2168                     p_pic->pf_release( p_pic );
2169                     transcode_video_close( p_stream, id );
2170                     id->b_transcode = VLC_FALSE;
2171                     return VLC_EGENERIC;
2172                 }
2173             }
2174
2175             for( i = 0; i < p_sys->i_vfilters; i++ )
2176             {
2177                 id->pp_vfilter[id->i_vfilter] =
2178                     vlc_object_create( p_stream, VLC_OBJECT_FILTER );
2179                 vlc_object_attach( id->pp_vfilter[id->i_vfilter], p_stream );
2180
2181                 id->pp_vfilter[id->i_vfilter]->pf_vout_buffer_new =
2182                     video_new_buffer_filter;
2183                 id->pp_vfilter[id->i_vfilter]->pf_vout_buffer_del =
2184                     video_del_buffer_filter;
2185
2186                 id->pp_vfilter[id->i_vfilter]->fmt_in = id->p_encoder->fmt_in;
2187                 id->pp_vfilter[id->i_vfilter]->fmt_out = id->p_encoder->fmt_in;
2188                 id->pp_vfilter[id->i_vfilter]->p_cfg = p_sys->p_vfilters_cfg[i];
2189                 id->pp_vfilter[id->i_vfilter]->p_module =
2190                     module_Need( id->pp_vfilter[id->i_vfilter],
2191                           "video filter2", p_sys->psz_vfilters[i], 0 );
2192                 if( id->pp_vfilter[id->i_vfilter]->p_module )
2193                 {
2194                     id->pp_vfilter[id->i_vfilter]->p_owner =
2195                         malloc( sizeof(filter_owner_sys_t) );
2196                     for( i = 0; i < PICTURE_RING_SIZE; i++ )
2197                         id->pp_vfilter[id->i_vfilter]->p_owner->pp_pics[i] = 0;
2198                     id->pp_vfilter[id->i_vfilter]->p_owner->p_sys = p_sys;
2199
2200                     id->i_vfilter++;
2201                 }
2202                 else
2203                 {
2204                     msg_Dbg( p_stream, "no video filter found" );
2205                     vlc_object_detach( id->pp_vfilter[id->i_vfilter] );
2206                     vlc_object_destroy( id->pp_vfilter[id->i_vfilter] );
2207                 }
2208             }
2209         }
2210
2211         /* Run filter chain */
2212         for( i = 0; i < id->i_filter; i++ )
2213         {
2214             p_pic = id->pp_filter[i]->pf_video_filter(id->pp_filter[i], p_pic);
2215         }
2216
2217         /*
2218          * Encoding
2219          */
2220
2221         /* Check if we have a subpicture to overlay */
2222         if( p_sys->p_spu )
2223         {
2224             p_subpic = spu_SortSubpictures( p_sys->p_spu, p_pic->date );
2225             /* TODO: get another pic */
2226         }
2227
2228         /* Overlay subpicture */
2229         if( p_subpic )
2230         {
2231             int i_scale_width, i_scale_height;
2232             video_format_t *p_fmt;
2233
2234             i_scale_width = id->p_encoder->fmt_in.video.i_width * 1000 /
2235                 id->p_decoder->fmt_out.video.i_width;
2236             i_scale_height = id->p_encoder->fmt_in.video.i_height * 1000 /
2237                 id->p_decoder->fmt_out.video.i_height;
2238
2239             if( p_pic->i_refcount && !id->i_filter )
2240             {
2241                 /* We can't modify the picture, we need to duplicate it */
2242                 picture_t *p_tmp = video_new_buffer_decoder( id->p_decoder );
2243                 if( p_tmp )
2244                 {
2245                     vout_CopyPicture( p_stream, p_tmp, p_pic );
2246                     p_pic->pf_release( p_pic );
2247                     p_pic = p_tmp;
2248                 }
2249             }
2250
2251             if( id->i_filter )
2252                 p_fmt = &id->pp_filter[id->i_filter -1]->fmt_out.video;
2253             else
2254                 p_fmt = &id->p_decoder->fmt_out.video;
2255
2256             /* FIXME (shouldn't have to be done here) */
2257             p_fmt->i_sar_num = p_fmt->i_aspect *
2258                 p_fmt->i_height / p_fmt->i_width;
2259             p_fmt->i_sar_den = VOUT_ASPECT_FACTOR;
2260
2261             spu_RenderSubpictures( p_sys->p_spu, p_fmt, p_pic, p_pic, p_subpic,
2262                                    i_scale_width, i_scale_height );
2263         }
2264
2265         /* Run vfilter chain */
2266         for( i = 0; i < id->i_vfilter; i++ )
2267         {
2268             p_pic = id->pp_vfilter[i]->pf_video_filter(id->pp_vfilter[i], p_pic);
2269         }
2270
2271         if( p_sys->i_threads == 0 )
2272         {
2273             block_t *p_block;
2274             p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
2275             block_ChainAppend( out, p_block );
2276         }
2277
2278         if( p_sys->b_master_sync )
2279         {
2280             mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
2281             if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2282                   || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2283             {
2284                 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2285                 date_Set( &id->interpolated_pts, p_pic->date );
2286                 i_pts = p_pic->date + 1;
2287             }
2288             date_Increment( &id->interpolated_pts, 1 );
2289         }
2290
2291         if( p_sys->b_master_sync && i_duplicate > 1 )
2292         {
2293             mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
2294             if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
2295                   || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
2296             {
2297                 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
2298                 date_Set( &id->interpolated_pts, p_pic->date );
2299                 i_pts = p_pic->date + 1;
2300             }
2301             date_Increment( &id->interpolated_pts, 1 );
2302
2303             if( p_sys->i_threads >= 1 )
2304             {
2305                 /* We can't modify the picture, we need to duplicate it */
2306                 p_pic2 = video_new_buffer_decoder( id->p_decoder );
2307                 if( p_pic2 != NULL )
2308                 {
2309                     vout_CopyPicture( p_stream, p_pic2, p_pic );
2310                     p_pic2->date = i_pts;
2311                 }
2312             }
2313             else
2314             {
2315                 block_t *p_block;
2316                 p_pic->date = i_pts;
2317                 p_block = id->p_encoder->pf_encode_video(id->p_encoder, p_pic);
2318                 block_ChainAppend( out, p_block );
2319             }
2320         }
2321
2322         if( p_sys->i_threads == 0 )
2323         {
2324             p_pic->pf_release( p_pic );
2325         }
2326         else
2327         {
2328             vlc_mutex_lock( &p_sys->lock_out );
2329             p_sys->pp_pics[p_sys->i_last_pic++] = p_pic;
2330             p_sys->i_last_pic %= PICTURE_RING_SIZE;
2331             *out = p_sys->p_buffers;
2332             p_sys->p_buffers = NULL;
2333             if( p_pic2 != NULL )
2334             {
2335                 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic2;
2336                 p_sys->i_last_pic %= PICTURE_RING_SIZE;
2337             }
2338             vlc_cond_signal( &p_sys->cond );
2339             vlc_mutex_unlock( &p_sys->lock_out );
2340         }
2341     }
2342
2343     return VLC_SUCCESS;
2344 }
2345
2346 static int EncoderThread( sout_stream_sys_t *p_sys )
2347 {
2348     sout_stream_id_t *id = p_sys->id_video;
2349     picture_t *p_pic;
2350
2351     while( !p_sys->b_die && !p_sys->b_error )
2352     {
2353         block_t *p_block;
2354
2355         vlc_mutex_lock( &p_sys->lock_out );
2356         while( p_sys->i_last_pic == p_sys->i_first_pic )
2357         {
2358             vlc_cond_wait( &p_sys->cond, &p_sys->lock_out );
2359             if( p_sys->b_die || p_sys->b_error ) break;
2360         }
2361         if( p_sys->b_die || p_sys->b_error )
2362         {
2363             vlc_mutex_unlock( &p_sys->lock_out );
2364             break;
2365         }
2366
2367         p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2368         p_sys->i_first_pic %= PICTURE_RING_SIZE;
2369         vlc_mutex_unlock( &p_sys->lock_out );
2370
2371         p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
2372         vlc_mutex_lock( &p_sys->lock_out );
2373         block_ChainAppend( &p_sys->p_buffers, p_block );
2374
2375         vlc_mutex_unlock( &p_sys->lock_out );
2376
2377         p_pic->pf_release( p_pic );
2378     }
2379
2380     while( p_sys->i_last_pic != p_sys->i_first_pic )
2381     {
2382         p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
2383         p_sys->i_first_pic %= PICTURE_RING_SIZE;
2384
2385         p_pic->pf_release( p_pic );
2386     }
2387
2388     block_ChainRelease( p_sys->p_buffers );
2389
2390     return 0;
2391 }
2392
2393 struct picture_sys_t
2394 {
2395     vlc_object_t *p_owner;
2396 };
2397
2398 static void video_release_buffer( picture_t *p_pic )
2399 {
2400     if( p_pic && !p_pic->i_refcount && p_pic->pf_release && p_pic->p_sys )
2401     {
2402         video_del_buffer_decoder( (decoder_t *)p_pic->p_sys->p_owner, p_pic );
2403     }
2404     else if( p_pic && p_pic->i_refcount > 0 ) p_pic->i_refcount--;
2405 }
2406
2407 static picture_t *video_new_buffer( vlc_object_t *p_this, picture_t **pp_ring,
2408                                     sout_stream_sys_t *p_sys )
2409 {
2410     decoder_t *p_dec = (decoder_t *)p_this;
2411     picture_t *p_pic;
2412     int i;
2413
2414     /* Find an empty space in the picture ring buffer */
2415     for( i = 0; i < PICTURE_RING_SIZE; i++ )
2416     {
2417         if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
2418         {
2419             pp_ring[i]->i_status = RESERVED_PICTURE;
2420             return pp_ring[i];
2421         }
2422     }
2423     for( i = 0; i < PICTURE_RING_SIZE; i++ )
2424     {
2425         if( pp_ring[i] == 0 ) break;
2426     }
2427
2428     if( i == PICTURE_RING_SIZE && p_sys->i_threads >= 1 )
2429     {
2430         int i_first_pic = p_sys->i_first_pic;
2431
2432         if( p_sys->i_first_pic != p_sys->i_last_pic )
2433         {
2434             /* Encoder still has stuff to encode, wait to clear-up the list */
2435             while( p_sys->i_first_pic == i_first_pic )
2436                 msleep( 100000 );
2437         }
2438
2439         /* Find an empty space in the picture ring buffer */
2440         for( i = 0; i < PICTURE_RING_SIZE; i++ )
2441         {
2442             if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
2443             {
2444                 pp_ring[i]->i_status = RESERVED_PICTURE;
2445                 return pp_ring[i];
2446             }
2447         }
2448         for( i = 0; i < PICTURE_RING_SIZE; i++ )
2449         {
2450             if( pp_ring[i] == 0 ) break;
2451         }
2452     }
2453
2454     if( i == PICTURE_RING_SIZE )
2455     {
2456         msg_Err( p_this, "decoder/filter is leaking pictures, "
2457                  "resetting its ring buffer" );
2458
2459         for( i = 0; i < PICTURE_RING_SIZE; i++ )
2460         {
2461             pp_ring[i]->pf_release( pp_ring[i] );
2462         }
2463
2464         i = 0;
2465     }
2466
2467     p_pic = malloc( sizeof(picture_t) );
2468     p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
2469     vout_AllocatePicture( VLC_OBJECT(p_dec), p_pic,
2470                           p_dec->fmt_out.video.i_chroma,
2471                           p_dec->fmt_out.video.i_width,
2472                           p_dec->fmt_out.video.i_height,
2473                           p_dec->fmt_out.video.i_aspect );
2474
2475     if( !p_pic->i_planes )
2476     {
2477         free( p_pic );
2478         return 0;
2479     }
2480
2481     p_pic->pf_release = video_release_buffer;
2482     p_pic->p_sys = malloc( sizeof(picture_sys_t) );
2483     p_pic->p_sys->p_owner = p_this;
2484     p_pic->i_status = RESERVED_PICTURE;
2485
2486     pp_ring[i] = p_pic;
2487
2488     return p_pic;
2489 }
2490
2491 static picture_t *video_new_buffer_decoder( decoder_t *p_dec )
2492 {
2493     return video_new_buffer( VLC_OBJECT(p_dec),
2494                              p_dec->p_owner->pp_pics, p_dec->p_owner->p_sys );
2495 }
2496
2497 static picture_t *video_new_buffer_filter( filter_t *p_filter )
2498 {
2499     return video_new_buffer( VLC_OBJECT(p_filter),
2500                              p_filter->p_owner->pp_pics,
2501                              p_filter->p_owner->p_sys );
2502 }
2503
2504 static void video_del_buffer( vlc_object_t *p_this, picture_t *p_pic )
2505 {
2506     if( p_pic && p_pic->p_data_orig ) free( p_pic->p_data_orig );
2507     if( p_pic && p_pic->p_sys ) free( p_pic->p_sys );
2508     if( p_pic ) free( p_pic );
2509 }
2510
2511 static void video_del_buffer_decoder( decoder_t *p_decoder, picture_t *p_pic )
2512 {
2513     p_pic->i_refcount = 0;
2514     p_pic->i_status = DESTROYED_PICTURE;
2515 }
2516
2517 static void video_del_buffer_filter( filter_t *p_filter, picture_t *p_pic )
2518 {
2519     p_pic->i_refcount = 0;
2520     p_pic->i_status = DESTROYED_PICTURE;
2521 }
2522
2523 static void video_link_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2524 {
2525     p_pic->i_refcount++;
2526 }
2527
2528 static void video_unlink_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
2529 {
2530     video_release_buffer( p_pic );
2531 }
2532
2533 /*
2534  * SPU
2535  */
2536 static subpicture_t *spu_new_buffer( decoder_t * );
2537 static void spu_del_buffer( decoder_t *, subpicture_t * );
2538
2539 static int transcode_spu_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2540 {
2541     sout_stream_sys_t *p_sys = p_stream->p_sys;
2542
2543     /*
2544      * Open decoder
2545      */
2546
2547     /* Initialization of decoder structures */
2548     id->p_decoder->pf_spu_buffer_new = spu_new_buffer;
2549     id->p_decoder->pf_spu_buffer_del = spu_del_buffer;
2550     id->p_decoder->p_owner = (decoder_owner_sys_t *)p_stream;
2551     /* id->p_decoder->p_cfg = p_sys->p_spu_cfg; */
2552
2553     id->p_decoder->p_module =
2554         module_Need( id->p_decoder, "decoder", "$codec", 0 );
2555
2556     if( !id->p_decoder->p_module )
2557     {
2558         msg_Err( p_stream, "cannot find decoder" );
2559         return VLC_EGENERIC;
2560     }
2561
2562     if( !p_sys->b_soverlay )
2563     {
2564         /*
2565          * Open encoder
2566          */
2567
2568         /* Initialization of encoder format structures */
2569         es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
2570                         id->p_decoder->fmt_in.i_codec );
2571
2572         id->p_encoder->p_cfg = p_sys->p_spu_cfg;
2573
2574         id->p_encoder->p_module =
2575             module_Need( id->p_encoder, "encoder", p_sys->psz_senc, VLC_TRUE );
2576
2577         if( !id->p_encoder->p_module )
2578         {
2579             module_Unneed( id->p_decoder, id->p_decoder->p_module );
2580             msg_Err( p_stream, "cannot find encoder" );
2581             return VLC_EGENERIC;
2582         }
2583     }
2584
2585     if( !p_sys->p_spu )
2586     {
2587         p_sys->p_spu = spu_Create( p_stream );
2588         spu_Init( p_sys->p_spu );
2589     }
2590
2591     return VLC_SUCCESS;
2592 }
2593
2594 static void transcode_spu_close( sout_stream_t *p_stream, sout_stream_id_t *id)
2595 {
2596     /* Close decoder */
2597     if( id->p_decoder->p_module )
2598         module_Unneed( id->p_decoder, id->p_decoder->p_module );
2599
2600     /* Close encoder */
2601     if( id->p_encoder->p_module )
2602         module_Unneed( id->p_encoder, id->p_encoder->p_module );
2603 }
2604
2605 static int transcode_spu_process( sout_stream_t *p_stream,
2606                                   sout_stream_id_t *id,
2607                                   block_t *in, block_t **out )
2608 {
2609     sout_stream_sys_t *p_sys = p_stream->p_sys;
2610     subpicture_t *p_subpic;
2611     *out = NULL;
2612
2613     p_subpic = id->p_decoder->pf_decode_sub( id->p_decoder, &in );
2614     if( !p_subpic ) return VLC_EGENERIC;
2615
2616     if( p_sys->b_master_sync && p_sys->i_master_drift )
2617     {
2618         p_subpic->i_start -= p_sys->i_master_drift;
2619         if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2620     }
2621
2622     if( p_sys->b_soverlay )
2623     {
2624         spu_DisplaySubpicture( p_sys->p_spu, p_subpic );
2625     }
2626     else
2627     {
2628         block_t *p_block;
2629
2630         p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
2631         spu_del_buffer( id->p_decoder, p_subpic );
2632
2633         if( p_block )
2634         {
2635             block_ChainAppend( out, p_block );
2636             return VLC_SUCCESS;
2637         }
2638     }
2639
2640     return VLC_EGENERIC;
2641 }
2642
2643 static subpicture_t *spu_new_buffer( decoder_t *p_dec )
2644 {
2645     sout_stream_t *p_stream = (sout_stream_t *)p_dec->p_owner;
2646     return spu_CreateSubpicture( p_stream->p_sys->p_spu );
2647 }
2648
2649 static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_subpic )
2650 {
2651     sout_stream_t *p_stream = (sout_stream_t *)p_dec->p_owner;
2652     spu_DestroySubpicture( p_stream->p_sys->p_spu, p_subpic );
2653 }
2654
2655 /*
2656  * OSD menu
2657  */
2658 static int transcode_osd_new( sout_stream_t *p_stream, sout_stream_id_t *id )
2659 {
2660     sout_stream_sys_t *p_sys = p_stream->p_sys;
2661     es_format_t fmt;
2662
2663     fmt.i_cat = SPU_ES;
2664     fmt.i_id = 0xbd1f; /* pid ?? */
2665     fmt.i_group = 3;   /* pmt entry ?? */
2666     fmt.i_codec = VLC_FOURCC( 'Y', 'U', 'V', 'A' );
2667     fmt.psz_language = strdup( "osd" );
2668
2669     id = malloc( sizeof( sout_stream_id_t ) );
2670     memset( id, 0, sizeof(sout_stream_id_t) );
2671
2672     id->id = NULL;
2673     id->p_decoder = NULL;
2674     id->p_encoder = NULL;
2675
2676     /* Create encoder object */
2677     id->p_encoder = vlc_object_create( p_stream, VLC_OBJECT_ENCODER );
2678     if( !id->p_encoder )
2679     {
2680         msg_Err( p_stream, "out of memory" );
2681         goto error;
2682     }
2683     vlc_object_attach( id->p_encoder, p_stream );
2684     id->p_encoder->p_module = NULL;
2685
2686     /* Create fake destination format */
2687     es_format_Init( &id->p_encoder->fmt_out, fmt.i_cat, 0 );
2688     id->p_encoder->fmt_out.i_id    = fmt.i_id;
2689     id->p_encoder->fmt_out.i_group = fmt.i_group;
2690     id->p_encoder->fmt_out.psz_language = strdup( fmt.psz_language );
2691
2692     if( p_sys->i_osdcodec != 0 || p_sys->psz_osdenc )
2693     {
2694         msg_Dbg( p_stream, "creating osdmenu transcoding from fcc=`%4.4s' "
2695                  "to fcc=`%4.4s'", (char*)&fmt.i_codec,
2696                  (char*)&p_sys->i_osdcodec );
2697
2698         /* Complete destination format */
2699         id->p_encoder->fmt_out.i_codec = p_sys->i_osdcodec;
2700
2701         /*
2702          * Open encoder
2703          */
2704
2705         /* Initialization of encoder format structures */
2706         es_format_Init( &id->p_encoder->fmt_in, fmt.i_cat, fmt.i_codec );
2707         id->p_encoder->fmt_in.psz_language = strdup( fmt.psz_language );
2708
2709         id->p_encoder->p_cfg = p_sys->p_osd_cfg;
2710
2711         id->p_encoder->p_module =
2712             module_Need( id->p_encoder, "encoder", p_sys->psz_osdenc, VLC_TRUE );
2713
2714         if( !id->p_encoder->p_module )
2715         {
2716             msg_Err( p_stream, "cannot find encoder" );
2717             goto error;
2718         }
2719
2720         /* open output stream */
2721         id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
2722         id->b_transcode = VLC_TRUE;
2723
2724         if( !id->id ) goto error;
2725     }
2726     else
2727     {
2728         msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
2729                  (char*)&fmt.i_codec );
2730         id->id = p_sys->p_out->pf_add( p_sys->p_out, &fmt );
2731         id->b_transcode = VLC_FALSE;
2732
2733         if( !id->id ) goto error;
2734     }
2735
2736     p_sys->id_osd = id;
2737     p_sys->b_es_osd = VLC_TRUE;
2738
2739     if( !p_sys->p_spu )
2740     {
2741         p_sys->p_spu = spu_Create( p_stream );
2742         if( spu_Init( p_sys->p_spu ) != VLC_SUCCESS )
2743             msg_Err( p_sys, "spu initialisation failed" );
2744     }
2745
2746     if( fmt.psz_language )
2747         free( fmt.psz_language );
2748
2749     return VLC_SUCCESS;
2750
2751  error:
2752     msg_Err( p_stream, "starting osd encoding thread failed" );
2753     if( id->p_encoder->p_module )
2754             module_Unneed( id->p_encoder, id->p_encoder->p_module );
2755     if( id->p_encoder )
2756     {
2757         vlc_object_detach( id->p_encoder );
2758         vlc_object_destroy( id->p_encoder );
2759     }
2760     if( fmt.psz_language ) free( fmt.psz_language );
2761     if( id ) free( id );
2762     p_sys->id_osd = NULL;
2763     p_sys->b_es_osd = VLC_FALSE;
2764     return VLC_EGENERIC;
2765 }
2766
2767 static void transcode_osd_close( sout_stream_t *p_stream, sout_stream_id_t *id)
2768 {
2769     sout_stream_sys_t *p_sys = p_stream->p_sys;
2770
2771     /* Close encoder */
2772     if( p_sys->b_es_osd && id )
2773     {
2774         if( id->p_encoder->p_module )
2775             module_Unneed( id->p_encoder, id->p_encoder->p_module );
2776
2777         if( id->id ) p_sys->p_out->pf_del( p_sys->p_out, id->id );
2778
2779         if( id->p_encoder )
2780         {
2781             vlc_object_detach( id->p_encoder );
2782             vlc_object_destroy( id->p_encoder );
2783         }
2784     }
2785     p_sys->b_es_osd = VLC_FALSE;
2786     if( id ) free( id );
2787 }
2788
2789 static int transcode_osd_process( sout_stream_t *p_stream,
2790                                   sout_stream_id_t *id,
2791                                   block_t *in, block_t **out )
2792 {
2793     sout_stream_sys_t *p_sys = p_stream->p_sys;
2794     subpicture_t *p_subpic = NULL;
2795
2796     /* Check if we have a subpicture to send */
2797     if( p_sys->p_spu && in->i_dts > 0)
2798     {
2799         p_subpic = spu_SortSubpictures( p_sys->p_spu, in->i_dts );
2800     }
2801     else
2802     {
2803         msg_Warn( p_stream, "spu channel not initialized, doing it now" );
2804         if( !p_sys->p_spu )
2805         {
2806             p_sys->p_spu = spu_Create( p_stream );
2807             if( spu_Init( p_sys->p_spu ) != VLC_SUCCESS )
2808                 msg_Err( p_stream, "spu initialisation failed" );
2809         }
2810     }
2811
2812     if( p_subpic )
2813     {
2814         block_t *p_block = NULL;
2815
2816         if( p_sys->b_master_sync && p_sys->i_master_drift )
2817         {
2818             p_subpic->i_start -= p_sys->i_master_drift;
2819             if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
2820         }
2821
2822         p_block = p_sys->id_osd->p_encoder->pf_encode_sub( p_sys->id_osd->p_encoder, p_subpic );
2823         if( p_block )
2824         {
2825             p_block->i_dts = p_block->i_pts = in->i_dts;
2826             block_ChainAppend( out, p_block );
2827             if( *out )
2828             {
2829                 if( p_sys->p_out->pf_send( p_sys->p_out, p_sys->id_osd->id, *out ) == VLC_SUCCESS )
2830                     spu_DestroySubpicture( p_sys->p_spu, p_subpic );
2831             }
2832             return VLC_SUCCESS;
2833         }
2834     }
2835     return VLC_EGENERIC;
2836 }