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