]> git.sesse.net Git - vlc/blob - modules/stream_out/transcode.c
dc8b09bf4f3f734e80901ab9993894f4da8d0096
[vlc] / modules / stream_out / transcode.c
1 /*****************************************************************************
2  * transcode.c: transcoding stream output module
3  *****************************************************************************
4  * Copyright (C) 2003-2004 VideoLAN
5  * $Id$
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *          Gildas Bazin <gbazin@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include <vlc/vlc.h>
32 #include <vlc/input.h>
33 #include <vlc/sout.h>
34 #include <vlc/vout.h>
35 #include <vlc/decoder.h>
36 #include "vlc_filter.h"
37 #include "osd.h"
38
39 /*****************************************************************************
40  * Module descriptor
41  *****************************************************************************/
42 #define VENC_TEXT N_("Video encoder")
43 #define VENC_LONGTEXT N_( \
44     "Allows you to specify the video encoder to use and its associated " \
45     "options." )
46 #define VCODEC_TEXT N_("Destination video codec")
47 #define VCODEC_LONGTEXT N_( \
48     "Allows you to specify the destination video codec used for the " \
49     "streaming output." )
50 #define VB_TEXT N_("Video bitrate")
51 #define VB_LONGTEXT N_( \
52     "Allows you to specify the video bitrate used for the streaming " \
53     "output." )
54 #define SCALE_TEXT N_("Video scaling")
55 #define SCALE_LONGTEXT N_( \
56     "Allows you to scale the video before encoding." )
57 #define FPS_TEXT N_("Video frame-rate")
58 #define FPS_LONGTEXT N_( \
59     "Allows you to specify an output frame rate for the video." )
60 #define DEINTERLACE_TEXT N_("Deinterlace video")
61 #define DEINTERLACE_LONGTEXT N_( \
62     "Allows you to deinterlace the video before encoding." )
63 #define WIDTH_TEXT N_("Video width")
64 #define WIDTH_LONGTEXT N_( \
65     "Allows you to specify the output video width." )
66 #define HEIGHT_TEXT N_("Video height")
67 #define HEIGHT_LONGTEXT N_( \
68     "Allows you to specify the output video height." )
69
70 #define CROPTOP_TEXT N_("Video crop top")
71 #define CROPTOP_LONGTEXT N_( \
72     "Allows you to specify the top coordinate for the video cropping." )
73 #define CROPLEFT_TEXT N_("Video crop left")
74 #define CROPLEFT_LONGTEXT N_( \
75     "Allows you to specify the left coordinate for the video cropping." )
76 #define CROPBOTTOM_TEXT N_("Video crop bottom")
77 #define CROPBOTTOM_LONGTEXT N_( \
78     "Allows you to specify the bottom coordinate for the video cropping." )
79 #define CROPRIGHT_TEXT N_("Video crop right")
80 #define CROPRIGHT_LONGTEXT N_( \
81     "Allows you to specify the right coordinate for the video cropping." )
82
83 #define AENC_TEXT N_("Audio encoder")
84 #define AENC_LONGTEXT N_( \
85     "Allows you to specify the audio encoder to use and its associated " \
86     "options." )
87 #define ACODEC_TEXT N_("Destination audio codec")
88 #define ACODEC_LONGTEXT N_( \
89     "Allows you to specify the destination audio codec used for the " \
90     "streaming output." )
91 #define AB_TEXT N_("Audio bitrate")
92 #define AB_LONGTEXT N_( \
93     "Allows you to specify the audio bitrate used for the streaming " \
94     "output." )
95 #define ARATE_TEXT N_("Audio sample rate")
96 #define ARATE_LONGTEXT N_( \
97     "Allows you to specify the audio sample rate used for the streaming " \
98     "output." )
99 #define ACHANS_TEXT N_("Audio channels")
100 #define ACHANS_LONGTEXT N_( \
101     "Allows you to specify the number of audio channels used for the " \
102     "streaming output." )
103
104 #define SENC_TEXT N_("Subtitles encoder")
105 #define SENC_LONGTEXT N_( \
106     "Allows you to specify the subtitles encoder to use and its associated " \
107     "options." )
108 #define SCODEC_TEXT N_("Destination subtitles codec")
109 #define SCODEC_LONGTEXT N_( \
110     "Allows you to specify the destination subtitles codec used for the " \
111     "streaming output." )
112 #define SFILTER_TEXT N_("Subpictures filter")
113 #define SFILTER_LONGTEXT N_( \
114     "Allows you to specify subpictures filters used during the video " \
115     "transcoding. The subpictures produced by the filters will be overlayed " \
116     "directly onto the video." )
117
118 #define THREADS_TEXT N_("Number of threads")
119 #define THREADS_LONGTEXT N_( \
120     "Allows you to specify the number of threads used for the transcoding." )
121
122 #define ASYNC_TEXT N_("Synchronise on audio track")
123 #define ASYNC_LONGTEXT N_( \
124     "This option will drop/duplicate video frames to synchronise the video " \
125     "track on the audio track." )
126
127 static int  Open ( vlc_object_t * );
128 static void Close( vlc_object_t * );
129
130 #define SOUT_CFG_PREFIX "sout-transcode-"
131
132 vlc_module_begin();
133     set_description( _("Transcode stream output") );
134     set_capability( "sout stream", 50 );
135     add_shortcut( "transcode" );
136     set_callbacks( Open, Close );
137
138     add_string( SOUT_CFG_PREFIX "venc", NULL, NULL, VENC_TEXT,
139                 VENC_LONGTEXT, VLC_FALSE );
140     add_string( SOUT_CFG_PREFIX "vcodec", NULL, NULL, VCODEC_TEXT,
141                 VCODEC_LONGTEXT, VLC_FALSE );
142     add_integer( SOUT_CFG_PREFIX "vb", 800 * 1000, NULL, VB_TEXT,
143                  VB_LONGTEXT, VLC_FALSE );
144     add_float( SOUT_CFG_PREFIX "scale", 1, NULL, SCALE_TEXT,
145                SCALE_LONGTEXT, VLC_FALSE );
146     add_float( SOUT_CFG_PREFIX "fps", 0, NULL, FPS_TEXT,
147                FPS_LONGTEXT, VLC_FALSE );
148     add_bool( SOUT_CFG_PREFIX "deinterlace", 0, NULL, DEINTERLACE_TEXT,
149               DEINTERLACE_LONGTEXT, VLC_FALSE );
150     add_integer( SOUT_CFG_PREFIX "width", 0, NULL, WIDTH_TEXT,
151                  WIDTH_LONGTEXT, VLC_TRUE );
152     add_integer( SOUT_CFG_PREFIX "height", 0, NULL, HEIGHT_TEXT,
153                  HEIGHT_LONGTEXT, VLC_TRUE );
154
155     add_integer( SOUT_CFG_PREFIX "croptop", 0, NULL, CROPTOP_TEXT,
156                  CROPTOP_LONGTEXT, VLC_TRUE );
157     add_integer( SOUT_CFG_PREFIX "cropleft", 0, NULL, CROPLEFT_TEXT,
158                  CROPLEFT_LONGTEXT, VLC_TRUE );
159     add_integer( SOUT_CFG_PREFIX "cropbottom", 0, NULL, CROPBOTTOM_TEXT,
160                  CROPBOTTOM_LONGTEXT, VLC_TRUE );
161     add_integer( SOUT_CFG_PREFIX "cropright", 0, NULL, CROPRIGHT_TEXT,
162                  CROPRIGHT_LONGTEXT, VLC_TRUE );
163
164     add_string( SOUT_CFG_PREFIX "aenc", NULL, NULL, AENC_TEXT,
165                 AENC_LONGTEXT, VLC_FALSE );
166     add_string( SOUT_CFG_PREFIX "acodec", NULL, NULL, ACODEC_TEXT,
167                 ACODEC_LONGTEXT, VLC_FALSE );
168     add_integer( SOUT_CFG_PREFIX "ab", 64000, NULL, AB_TEXT,
169                  AB_LONGTEXT, VLC_FALSE );
170     add_integer( SOUT_CFG_PREFIX "channels", 0, NULL, ACHANS_TEXT,
171                  ACHANS_LONGTEXT, VLC_FALSE );
172     add_integer( SOUT_CFG_PREFIX "samplerate", 0, NULL, ARATE_TEXT,
173                  ARATE_LONGTEXT, VLC_TRUE );
174
175     add_string( SOUT_CFG_PREFIX "senc", NULL, NULL, SENC_TEXT,
176                 SENC_LONGTEXT, VLC_FALSE );
177     add_string( SOUT_CFG_PREFIX "scodec", NULL, NULL, SCODEC_TEXT,
178                 SCODEC_LONGTEXT, VLC_FALSE );
179     add_bool( SOUT_CFG_PREFIX "soverlay", 0, NULL, SCODEC_TEXT,
180                SCODEC_LONGTEXT, VLC_FALSE );
181     add_string( SOUT_CFG_PREFIX "sfilter", NULL, NULL, SFILTER_TEXT,
182                 SFILTER_LONGTEXT, VLC_FALSE );
183
184     add_integer( SOUT_CFG_PREFIX "threads", 0, NULL, THREADS_TEXT,
185                  THREADS_LONGTEXT, VLC_TRUE );
186
187     add_bool( SOUT_CFG_PREFIX "audio-sync", 0, NULL, ASYNC_TEXT,
188               ASYNC_LONGTEXT, VLC_FALSE );
189 vlc_module_end();
190
191 static const char *ppsz_sout_options[] = {
192     "venc", "vcodec", "vb", "croptop", "cropbottom", "cropleft", "cropright",
193     "scale", "fps", "width", "height", "deinterlace", "threads",
194     "aenc", "acodec", "ab", "samplerate", "channels",
195     "senc", "scodec", "soverlay", "sfilter",
196     "audio-sync", NULL
197 };
198
199 /*****************************************************************************
200  * Exported prototypes
201  *****************************************************************************/
202 static sout_stream_id_t *Add ( sout_stream_t *, es_format_t * );
203 static int               Del ( sout_stream_t *, sout_stream_id_t * );
204 static int               Send( sout_stream_t *, sout_stream_id_t *, block_t* );
205
206 static int  transcode_audio_new    ( sout_stream_t *, sout_stream_id_t * );
207 static void transcode_audio_close  ( sout_stream_t *, sout_stream_id_t * );
208 static int  transcode_audio_process( sout_stream_t *, sout_stream_id_t *,
209                                      block_t *, block_t ** );
210
211 static aout_buffer_t *audio_new_buffer( decoder_t *, int );
212 static void audio_del_buffer( decoder_t *, aout_buffer_t * );
213
214 static int  transcode_video_new    ( sout_stream_t *, sout_stream_id_t * );
215 static void transcode_video_close  ( sout_stream_t *, sout_stream_id_t * );
216 static int  transcode_video_encoder_open( sout_stream_t *, sout_stream_id_t *);
217 static int  transcode_video_process( sout_stream_t *, sout_stream_id_t *,
218                                      block_t *, block_t ** );
219
220 static void video_del_buffer( vlc_object_t *, picture_t * );
221 static picture_t *video_new_buffer_decoder( decoder_t * );
222 static void video_del_buffer_decoder( decoder_t *, picture_t * );
223 static void video_link_picture_decoder( decoder_t *, picture_t * );
224 static void video_unlink_picture_decoder( decoder_t *, picture_t * );
225 static picture_t *video_new_buffer_filter( filter_t * );
226 static void video_del_buffer_filter( filter_t *, picture_t * );
227
228 static int  transcode_spu_new    ( sout_stream_t *, sout_stream_id_t * );
229 static void transcode_spu_close  ( sout_stream_t *, sout_stream_id_t * );
230 static int  transcode_spu_process( sout_stream_t *, sout_stream_id_t *,
231                                    block_t *, block_t ** );
232
233 static int  EncoderThread( struct sout_stream_sys_t * p_sys );
234
235 static int pi_channels_maps[6] =
236 {
237     0,
238     AOUT_CHAN_CENTER,   AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
239     AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
240     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
241      | AOUT_CHAN_REARRIGHT,
242     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
243      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
244 };
245
246 #define PICTURE_RING_SIZE 64
247 #define SUBPICTURE_RING_SIZE 20
248
249 struct sout_stream_sys_t
250 {
251     VLC_COMMON_MEMBERS
252
253     sout_stream_t   *p_out;
254     sout_stream_id_t *id_video;
255     block_t         *p_buffers;
256     vlc_mutex_t     lock_out;
257     vlc_cond_t      cond;
258     picture_t *     pp_pics[PICTURE_RING_SIZE];
259     int             i_first_pic, i_last_pic;
260
261     /* Audio */
262     vlc_fourcc_t    i_acodec;   /* codec audio (0 if not transcode) */
263     char            *psz_aenc;
264     sout_cfg_t      *p_audio_cfg;
265     int             i_sample_rate;
266     int             i_channels;
267     int             i_abitrate;
268
269     /* Video */
270     vlc_fourcc_t    i_vcodec;   /* codec video (0 if not transcode) */
271     char            *psz_venc;
272     sout_cfg_t      *p_video_cfg;
273     int             i_vbitrate;
274     double          f_scale;
275     double          f_fps;
276     int             i_width;
277     int             i_height;
278     vlc_bool_t      b_deinterlace;
279     int             i_threads;
280
281     int             i_crop_top;
282     int             i_crop_bottom;
283     int             i_crop_right;
284     int             i_crop_left;
285
286     /* SPU */
287     vlc_fourcc_t    i_scodec;   /* codec spu (0 if not transcode) */
288     char            *psz_senc;
289     vlc_bool_t      b_soverlay;
290     sout_cfg_t      *p_spu_cfg;
291     spu_t           *p_spu;
292
293     /* Sync */
294     vlc_bool_t      b_master_sync;
295     mtime_t         i_master_drift;
296 };
297
298 struct decoder_owner_sys_t
299 {
300     picture_t *pp_pics[PICTURE_RING_SIZE];
301 };
302 struct filter_owner_sys_t
303 {
304     picture_t *pp_pics[PICTURE_RING_SIZE];
305 };
306
307 /*****************************************************************************
308  * Open:
309  *****************************************************************************/
310 static int Open( vlc_object_t *p_this )
311 {
312     sout_stream_t     *p_stream = (sout_stream_t*)p_this;
313     sout_stream_sys_t *p_sys;
314     vlc_value_t       val;
315
316     p_sys = vlc_object_create( p_this, sizeof( sout_stream_sys_t ) );
317
318     p_sys->p_out = sout_StreamNew( p_stream->p_sout, p_stream->psz_next );
319     if( !p_sys->p_out )
320     {
321         msg_Err( p_stream, "cannot create chain" );
322         free( p_sys );
323         return VLC_EGENERIC;
324     }
325
326     p_sys->i_master_drift = 0;
327
328     sout_CfgParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
329                    p_stream->p_cfg );
330
331     /* Audio transcoding parameters */
332     var_Get( p_stream, SOUT_CFG_PREFIX "aenc", &val );
333     p_sys->psz_aenc = NULL;
334     p_sys->p_audio_cfg = NULL;
335     if( val.psz_string && *val.psz_string )
336     {
337         char *psz_next;
338         psz_next = sout_CfgCreate( &p_sys->psz_aenc, &p_sys->p_audio_cfg,
339                                    val.psz_string );
340         if( psz_next ) free( psz_next );
341     }
342     if( val.psz_string ) free( val.psz_string );
343
344     var_Get( p_stream, SOUT_CFG_PREFIX "acodec", &val );
345     p_sys->i_acodec = 0;
346     if( val.psz_string && *val.psz_string )
347     {
348         char fcc[4] = "    ";
349         memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
350         p_sys->i_acodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
351     }
352     if( val.psz_string ) free( val.psz_string );
353
354     var_Get( p_stream, SOUT_CFG_PREFIX "ab", &val );
355     p_sys->i_abitrate = val.i_int;
356     if( p_sys->i_abitrate < 4000 ) p_sys->i_abitrate *= 1000;
357
358     var_Get( p_stream, SOUT_CFG_PREFIX "samplerate", &val );
359     p_sys->i_sample_rate = val.i_int;
360
361     var_Get( p_stream, SOUT_CFG_PREFIX "channels", &val );
362     p_sys->i_channels = val.i_int;
363
364     if( p_sys->i_acodec )
365     {
366         msg_Dbg( p_stream, "codec audio=%4.4s %dHz %d channels %dKb/s",
367                  (char *)&p_sys->i_acodec, p_sys->i_sample_rate,
368                  p_sys->i_channels, p_sys->i_abitrate / 1000 );
369     }
370
371     /* Video transcoding parameters */
372     var_Get( p_stream, SOUT_CFG_PREFIX "venc", &val );
373     p_sys->psz_venc = NULL;
374     p_sys->p_video_cfg = NULL;
375     if( val.psz_string && *val.psz_string )
376     {
377         char *psz_next;
378         psz_next = sout_CfgCreate( &p_sys->psz_venc, &p_sys->p_video_cfg,
379                                    val.psz_string );
380         if( psz_next ) free( psz_next );
381     }
382     if( val.psz_string ) free( val.psz_string );
383
384     var_Get( p_stream, SOUT_CFG_PREFIX "vcodec", &val );
385     p_sys->i_vcodec = 0;
386     if( val.psz_string && *val.psz_string )
387     {
388         char fcc[4] = "    ";
389         memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
390         p_sys->i_vcodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
391     }
392     if( val.psz_string ) free( val.psz_string );
393
394     var_Get( p_stream, SOUT_CFG_PREFIX "vb", &val );
395     p_sys->i_vbitrate = val.i_int;
396     if( p_sys->i_vbitrate < 16000 ) p_sys->i_vbitrate *= 1000;
397
398     var_Get( p_stream, SOUT_CFG_PREFIX "scale", &val );
399     p_sys->f_scale = val.f_float;
400
401     var_Get( p_stream, SOUT_CFG_PREFIX "fps", &val );
402     p_sys->f_fps = val.f_float;
403
404     var_Get( p_stream, SOUT_CFG_PREFIX "width", &val );
405     p_sys->i_width = val.i_int;
406
407     var_Get( p_stream, SOUT_CFG_PREFIX "height", &val );
408     p_sys->i_height = val.i_int;
409
410     var_Get( p_stream, SOUT_CFG_PREFIX "deinterlace", &val );
411     p_sys->b_deinterlace = val.b_bool;
412
413     var_Get( p_stream, SOUT_CFG_PREFIX "croptop", &val );
414     p_sys->i_crop_top = val.i_int;
415     var_Get( p_stream, SOUT_CFG_PREFIX "cropbottom", &val );
416     p_sys->i_crop_bottom = val.i_int;
417     var_Get( p_stream, SOUT_CFG_PREFIX "cropleft", &val );
418     p_sys->i_crop_left = val.i_int;
419     var_Get( p_stream, SOUT_CFG_PREFIX "cropright", &val );
420     p_sys->i_crop_right = val.i_int;
421
422     var_Get( p_stream, SOUT_CFG_PREFIX "threads", &val );
423     p_sys->i_threads = val.i_int;
424
425     if( p_sys->i_vcodec )
426     {
427         msg_Dbg( p_stream, "codec video=%4.4s %dx%d scaling: %f %dkb/s",
428                  (char *)&p_sys->i_vcodec, p_sys->i_width, p_sys->i_height,
429                  p_sys->f_scale, p_sys->i_vbitrate / 1000 );
430     }
431
432     /* Subpictures transcoding parameters */
433     p_sys->p_spu = 0;
434     p_sys->psz_senc = NULL;
435     p_sys->p_spu_cfg = NULL;
436     p_sys->i_scodec = 0;
437
438     var_Get( p_stream, SOUT_CFG_PREFIX "senc", &val );
439     if( val.psz_string && *val.psz_string )
440     {
441         char *psz_next;
442         psz_next = sout_CfgCreate( &p_sys->psz_senc, &p_sys->p_spu_cfg,
443                                    val.psz_string );
444         if( psz_next ) free( psz_next );
445     }
446     if( val.psz_string ) free( val.psz_string );
447
448     var_Get( p_stream, SOUT_CFG_PREFIX "scodec", &val );
449     if( val.psz_string && *val.psz_string )
450     {
451         char fcc[4] = "    ";
452         memcpy( fcc, val.psz_string, __MIN( strlen( val.psz_string ), 4 ) );
453         p_sys->i_scodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
454     }
455     if( val.psz_string ) free( val.psz_string );
456
457     if( p_sys->i_scodec )
458     {
459         msg_Dbg( p_stream, "codec spu=%4.4s", (char *)&p_sys->i_acodec );
460     }
461
462     var_Get( p_stream, SOUT_CFG_PREFIX "soverlay", &val );
463     p_sys->b_soverlay = val.b_bool;
464
465     var_Get( p_stream, SOUT_CFG_PREFIX "sfilter", &val );
466     if( val.psz_string && *val.psz_string )
467     {
468         p_sys->p_spu = spu_Create( p_stream );
469         var_Create( p_sys->p_spu, "sub-filter", VLC_VAR_STRING );
470         var_Set( p_sys->p_spu, "sub-filter", val );
471         spu_Init( p_sys->p_spu );
472     }
473     if( val.psz_string ) free( val.psz_string );
474
475     var_Get( p_stream, SOUT_CFG_PREFIX "audio-sync", &val );
476     p_sys->b_master_sync = val.b_bool;
477     if( p_sys->f_fps > 0 ) p_sys->b_master_sync = VLC_TRUE;
478
479     p_stream->pf_add    = Add;
480     p_stream->pf_del    = Del;
481     p_stream->pf_send   = Send;
482     p_stream->p_sys     = p_sys;
483
484     return VLC_SUCCESS;
485 }
486
487 /*****************************************************************************
488  * Close:
489  *****************************************************************************/
490 static void Close( vlc_object_t * p_this )
491 {
492     sout_stream_t       *p_stream = (sout_stream_t*)p_this;
493     sout_stream_sys_t   *p_sys = p_stream->p_sys;
494
495     sout_StreamDelete( p_sys->p_out );
496
497     while( p_sys->p_audio_cfg != NULL )
498     {
499         sout_cfg_t *p_next = p_sys->p_audio_cfg->p_next;
500
501         if( p_sys->p_audio_cfg->psz_name )
502             free( p_sys->p_audio_cfg->psz_name );
503         if( p_sys->p_audio_cfg->psz_value )
504             free( p_sys->p_audio_cfg->psz_value );
505         free( p_sys->p_audio_cfg );
506
507         p_sys->p_audio_cfg = p_next;
508     }
509     if( p_sys->psz_aenc ) free( p_sys->psz_aenc );
510
511     while( p_sys->p_video_cfg != NULL )
512     {
513         sout_cfg_t *p_next = p_sys->p_video_cfg->p_next;
514
515         if( p_sys->p_video_cfg->psz_name )
516             free( p_sys->p_video_cfg->psz_name );
517         if( p_sys->p_video_cfg->psz_value )
518             free( p_sys->p_video_cfg->psz_value );
519         free( p_sys->p_video_cfg );
520
521         p_sys->p_video_cfg = p_next;
522     }
523     if( p_sys->psz_venc ) free( p_sys->psz_venc );
524
525     while( p_sys->p_spu_cfg != NULL )
526     {
527         sout_cfg_t *p_next = p_sys->p_spu_cfg->p_next;
528
529         if( p_sys->p_spu_cfg->psz_name )
530             free( p_sys->p_spu_cfg->psz_name );
531         if( p_sys->p_spu_cfg->psz_value )
532             free( p_sys->p_spu_cfg->psz_value );
533         free( p_sys->p_spu_cfg );
534
535         p_sys->p_spu_cfg = p_next;
536     }
537     if( p_sys->psz_senc ) free( p_sys->psz_senc );
538
539     if( p_sys->p_spu ) spu_Destroy( p_sys->p_spu );
540
541     vlc_object_destroy( p_sys );
542 }
543
544 struct sout_stream_id_t
545 {
546     vlc_fourcc_t  b_transcode;
547
548     /* id of the out stream */
549     void *id;
550
551     /* Decoder */
552     decoder_t       *p_decoder;
553
554     /* Filters */
555     filter_t        *pp_filter[10];
556     int             i_filter;
557
558     /* Encoder */
559     encoder_t       *p_encoder;
560
561     /* Sync */
562     date_t          interpolated_pts;
563 };
564
565
566 static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
567 {
568     sout_stream_sys_t *p_sys = p_stream->p_sys;
569     sout_stream_id_t *id;
570
571     id = malloc( sizeof( sout_stream_id_t ) );
572     memset( id, 0, sizeof(sout_stream_id_t) );
573
574     id->id = NULL;
575     id->p_decoder = NULL;
576     id->p_encoder = NULL;
577
578     /* Create decoder object */
579     id->p_decoder = vlc_object_create( p_stream, VLC_OBJECT_DECODER );
580     if( !id->p_decoder )
581     {
582         msg_Err( p_stream, "out of memory" );
583         goto error;
584     }
585     vlc_object_attach( id->p_decoder, p_stream );
586     id->p_decoder->p_module = NULL;
587     id->p_decoder->fmt_in = *p_fmt;
588     id->p_decoder->fmt_out = *p_fmt;
589     id->p_decoder->fmt_out.i_extra = 0;
590     id->p_decoder->fmt_out.p_extra = 0;
591     id->p_decoder->b_pace_control = VLC_TRUE;
592
593     /* Create encoder object */
594     id->p_encoder = vlc_object_create( p_stream, VLC_OBJECT_ENCODER );
595     if( !id->p_encoder )
596     {
597         msg_Err( p_stream, "out of memory" );
598         goto error;
599     }
600     vlc_object_attach( id->p_encoder, p_stream );
601     id->p_encoder->p_module = NULL;
602
603     /* Create destination format */
604     es_format_Init( &id->p_encoder->fmt_out, p_fmt->i_cat, 0 );
605     id->p_encoder->fmt_out.i_id    = p_fmt->i_id;
606     id->p_encoder->fmt_out.i_group = p_fmt->i_group;
607     if( p_fmt->psz_language )
608         id->p_encoder->fmt_out.psz_language = strdup( p_fmt->psz_language );
609
610     if( p_fmt->i_cat == AUDIO_ES && (p_sys->i_acodec || p_sys->psz_aenc) )
611     {
612         msg_Dbg( p_stream,
613                  "creating audio transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
614                  (char*)&p_fmt->i_codec, (char*)&p_sys->i_acodec );
615
616         /* Complete destination format */
617         id->p_encoder->fmt_out.i_codec = p_sys->i_acodec;
618         id->p_encoder->fmt_out.audio.i_rate = p_sys->i_sample_rate > 0 ?
619             p_sys->i_sample_rate : (int)p_fmt->audio.i_rate;
620         id->p_encoder->fmt_out.audio.i_channels = p_sys->i_channels > 0 ?
621             p_sys->i_channels : p_fmt->audio.i_channels;
622         id->p_encoder->fmt_out.i_bitrate = p_sys->i_abitrate;
623         id->p_encoder->fmt_out.audio.i_bitspersample =
624             p_fmt->audio.i_bitspersample;
625
626         /* Build decoder -> filter -> encoder chain */
627         if( transcode_audio_new( p_stream, id ) )
628         {
629             msg_Err( p_stream, "cannot create audio chain" );
630             goto error;
631         }
632
633         /* Open output stream */
634         id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
635         id->b_transcode = VLC_TRUE;
636
637         if( !id->id ) goto error;
638
639         date_Init( &id->interpolated_pts, p_fmt->audio.i_rate, 1 );
640     }
641     else if( p_fmt->i_cat == VIDEO_ES &&
642              (p_sys->i_vcodec != 0 || p_sys->psz_venc) )
643     {
644         msg_Dbg( p_stream,
645                  "creating video transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
646                  (char*)&p_fmt->i_codec, (char*)&p_sys->i_vcodec );
647
648         /* Complete destination format */
649         id->p_encoder->fmt_out.i_codec = p_sys->i_vcodec;
650         id->p_encoder->fmt_out.video.i_width  = p_sys->i_width;
651         id->p_encoder->fmt_out.video.i_height = p_sys->i_height;
652         id->p_encoder->fmt_out.i_bitrate = p_sys->i_vbitrate;
653
654         /* Build decoder -> filter -> encoder chain */
655         if( transcode_video_new( p_stream, id ) )
656         {
657             msg_Err( p_stream, "cannot create video chain" );
658             goto error;
659         }
660
661         /* Stream will be added later on because we don't know
662          * all the characteristics of the decoded stream yet */
663         id->b_transcode = VLC_TRUE;
664
665         if( p_sys->f_fps > 0 )
666         {
667             id->p_encoder->fmt_out.video.i_frame_rate = p_sys->f_fps * 1000;
668             id->p_encoder->fmt_out.video.i_frame_rate_base = 1000;
669         }
670     }
671     else if( p_fmt->i_cat == SPU_ES && (p_sys->i_scodec || p_sys->psz_senc) )
672     {
673         msg_Dbg( p_stream, "creating subtitles transcoding from fcc=`%4.4s' "
674                  "to fcc=`%4.4s'", (char*)&p_fmt->i_codec,
675                  (char*)&p_sys->i_scodec );
676
677         /* Complete destination format */
678         id->p_encoder->fmt_out.i_codec = p_sys->i_scodec;
679
680         /* build decoder -> filter -> encoder */
681         if( transcode_spu_new( p_stream, id ) )
682         {
683             msg_Err( p_stream, "cannot create subtitles chain" );
684             goto error;
685         }
686
687         /* open output stream */
688         id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->p_encoder->fmt_out );
689         id->b_transcode = VLC_TRUE;
690
691         if( !id->id ) goto error;
692     }
693     else if( p_fmt->i_cat == SPU_ES && p_sys->b_soverlay )
694     {
695         msg_Dbg( p_stream, "subtitles (fcc=`%4.4s') overlaying",
696                  (char*)&p_fmt->i_codec );
697
698         id->b_transcode = VLC_TRUE;
699
700         /* Build decoder -> filter -> overlaying chain */
701         if( transcode_spu_new( p_stream, id ) )
702         {
703             msg_Err( p_stream, "cannot create subtitles chain" );
704             goto error;
705         }
706     }
707     else
708     {
709         msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
710                  (char*)&p_fmt->i_codec );
711         id->id = p_sys->p_out->pf_add( p_sys->p_out, p_fmt );
712         id->b_transcode = VLC_FALSE;
713
714         if( !id->id ) goto error;
715     }
716
717     return id;
718
719  error:
720     if( id->p_decoder )
721     {
722         vlc_object_detach( id->p_decoder );
723         vlc_object_destroy( id->p_decoder );
724     }
725
726     if( id->p_encoder )
727     {
728         vlc_object_detach( id->p_encoder );
729         vlc_object_destroy( id->p_encoder );
730     }
731
732     free( id );
733     return NULL;
734 }
735
736 static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
737 {
738     sout_stream_sys_t *p_sys = p_stream->p_sys;
739
740     if( id->b_transcode )
741     {
742         switch( id->p_decoder->fmt_in.i_cat )
743         {
744         case AUDIO_ES:
745             transcode_audio_close( p_stream, id );
746             break;
747         case VIDEO_ES:
748             transcode_video_close( p_stream, id );
749             break;
750         case SPU_ES:
751             transcode_spu_close( p_stream, id );
752             break;
753         }
754     }
755
756     if( id->id ) p_sys->p_out->pf_del( p_sys->p_out, id->id );
757
758     if( id->p_decoder )
759     {
760         vlc_object_detach( id->p_decoder );
761         vlc_object_destroy( id->p_decoder );
762     }
763
764     if( id->p_encoder )
765     {
766         vlc_object_detach( id->p_encoder );
767         vlc_object_destroy( id->p_encoder );
768     }
769
770     free( id );
771
772     return VLC_SUCCESS;
773 }
774
775 static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
776                  block_t *p_buffer )
777 {
778     sout_stream_sys_t *p_sys = p_stream->p_sys;
779     block_t *p_out;
780
781     if( !id->b_transcode && id->id )
782     {
783         if( p_sys->b_master_sync && p_sys->i_master_drift )
784         {
785             if( p_buffer->i_dts > 0 )
786             {
787                 p_buffer->i_dts -= p_sys->i_master_drift;
788                 if( p_buffer->i_dts < 0 )
789                 {
790                     block_Release( p_buffer );
791                     return VLC_EGENERIC;
792                 }
793             }
794             if( p_buffer->i_pts > 0 )
795             {
796                 p_buffer->i_pts -= p_sys->i_master_drift;
797                 if( p_buffer->i_pts < 0 )
798                 {
799                     block_Release( p_buffer );
800                     return VLC_EGENERIC;
801                 }
802             }
803         }
804
805         return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_buffer );
806     }
807     else if( !id->b_transcode )
808     {
809         block_Release( p_buffer );
810         return VLC_EGENERIC;
811     }
812
813     switch( id->p_decoder->fmt_in.i_cat )
814     {
815     case AUDIO_ES:
816         transcode_audio_process( p_stream, id, p_buffer, &p_out );
817         break;
818
819     case VIDEO_ES:
820         if( transcode_video_process( p_stream, id, p_buffer, &p_out )
821             != VLC_SUCCESS )
822         {
823             return VLC_EGENERIC;
824         }
825         break;
826
827     case SPU_ES:
828         if( transcode_spu_process( p_stream, id, p_buffer, &p_out ) !=
829             VLC_SUCCESS )
830         {
831             return VLC_EGENERIC;
832         }
833         break;
834
835     default:
836         block_Release( p_buffer );
837         break;
838     }
839
840     if( p_out ) return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_out );
841     return VLC_SUCCESS;
842 }
843
844 /****************************************************************************
845  * decoder reencoder part
846  ****************************************************************************/
847 int audio_BitsPerSample( vlc_fourcc_t i_format )
848 {
849     switch( i_format )
850     {
851     case VLC_FOURCC('u','8',' ',' '):
852     case VLC_FOURCC('s','8',' ',' '):
853         return 8;
854
855     case VLC_FOURCC('u','1','6','l'):
856     case VLC_FOURCC('s','1','6','l'):
857     case VLC_FOURCC('u','1','6','b'):
858     case VLC_FOURCC('s','1','6','b'):
859         return 16;
860
861     case VLC_FOURCC('u','2','4','l'):
862     case VLC_FOURCC('s','2','4','l'):
863     case VLC_FOURCC('u','2','4','b'):
864     case VLC_FOURCC('s','2','4','b'):
865         return 24;
866
867     case VLC_FOURCC('u','3','2','l'):
868     case VLC_FOURCC('s','3','2','l'):
869     case VLC_FOURCC('u','3','2','b'):
870     case VLC_FOURCC('s','3','2','b'):
871     case VLC_FOURCC('f','l','3','2'):
872     case VLC_FOURCC('f','i','3','2'):
873         return 32;
874
875     case VLC_FOURCC('f','l','6','4'):
876         return 64;
877     }
878
879     return 0;
880 }
881
882 static int transcode_audio_new( sout_stream_t *p_stream,
883                                 sout_stream_id_t *id )
884 {
885     sout_stream_sys_t *p_sys = p_stream->p_sys;
886
887     /*
888      * Open decoder
889      */
890
891     /* Initialization of decoder structures */
892     id->p_decoder->pf_decode_audio = 0;
893     id->p_decoder->pf_aout_buffer_new = audio_new_buffer;
894     id->p_decoder->pf_aout_buffer_del = audio_del_buffer;
895     //id->p_decoder->p_cfg = p_sys->p_video_cfg;
896
897     id->p_decoder->p_module =
898         module_Need( id->p_decoder, "decoder", "$codec", 0 );
899
900     if( !id->p_decoder->p_module )
901     {
902         msg_Err( p_stream, "cannot find decoder" );
903         return VLC_EGENERIC;
904     }
905     id->p_decoder->fmt_out.audio.i_bitspersample = 
906         audio_BitsPerSample( id->p_decoder->fmt_out.i_codec );
907
908     /*
909      * Open encoder
910      */
911
912     /* Initialization of encoder format structures */
913     es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
914                     id->p_decoder->fmt_out.i_codec );
915     id->p_encoder->fmt_in.audio.i_format = id->p_decoder->fmt_out.i_codec;
916
917     /* Sanity check for audio channels */
918     id->p_encoder->fmt_out.audio.i_channels =
919         __MIN( id->p_encoder->fmt_out.audio.i_channels,
920                id->p_decoder->fmt_out.audio.i_channels );
921     if( id->p_decoder->fmt_out.audio.i_channels ==
922         id->p_encoder->fmt_out.audio.i_channels )
923         id->p_encoder->fmt_out.audio.i_physical_channels =
924             id->p_encoder->fmt_out.audio.i_original_channels =
925                 id->p_decoder->fmt_out.audio.i_physical_channels;
926     else
927         id->p_encoder->fmt_out.audio.i_physical_channels =
928             id->p_encoder->fmt_out.audio.i_original_channels =
929                 pi_channels_maps[id->p_encoder->fmt_out.audio.i_channels];
930
931     /* Initialization of encoder format structures */
932     es_format_Init( &id->p_encoder->fmt_in, AUDIO_ES, AOUT_FMT_S16_NE );
933     id->p_encoder->fmt_in.audio.i_format = AOUT_FMT_S16_NE;
934     id->p_encoder->fmt_in.audio.i_rate = id->p_encoder->fmt_out.audio.i_rate;
935     id->p_encoder->fmt_in.audio.i_physical_channels =
936         id->p_encoder->fmt_in.audio.i_original_channels =
937             id->p_encoder->fmt_out.audio.i_physical_channels;
938     id->p_encoder->fmt_in.audio.i_channels =
939         id->p_encoder->fmt_out.audio.i_channels;
940     id->p_encoder->fmt_in.audio.i_bitspersample =
941         audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
942
943     id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg;
944
945     id->p_encoder->p_module =
946         module_Need( id->p_encoder, "encoder", p_sys->psz_aenc, VLC_TRUE );
947     if( !id->p_encoder->p_module )
948     {
949         msg_Err( p_stream, "cannot find encoder" );
950         module_Unneed( id->p_decoder, id->p_decoder->p_module );
951         id->p_decoder->p_module = 0;
952         return VLC_EGENERIC;
953     }
954     id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec;
955     id->p_encoder->fmt_in.audio.i_bitspersample =
956         audio_BitsPerSample( id->p_encoder->fmt_in.i_codec );
957
958     /* Check if we need a filter for chroma conversion or resizing */
959     if( id->p_decoder->fmt_out.i_codec !=
960         id->p_encoder->fmt_in.i_codec )
961     {
962         id->pp_filter[0] =
963             vlc_object_create( p_stream, VLC_OBJECT_FILTER );
964         vlc_object_attach( id->pp_filter[0], p_stream );
965
966         id->pp_filter[0]->pf_audio_buffer_new = __block_New;
967
968         id->pp_filter[0]->fmt_in = id->p_decoder->fmt_out;
969         id->pp_filter[0]->fmt_out = id->p_encoder->fmt_in;
970         id->pp_filter[0]->p_module =
971             module_Need( id->pp_filter[0], "audio filter2", 0, 0 );
972         if( id->pp_filter[0]->p_module ) id->i_filter++;
973         else
974         {
975             msg_Dbg( p_stream, "no audio filter found (%4.4s->%4.4s)",
976                      (char *)&id->pp_filter[0]->fmt_in,
977                      (char *)&id->pp_filter[0]->fmt_out );
978             vlc_object_detach( id->pp_filter[0] );
979             vlc_object_destroy( id->pp_filter[0] );
980             module_Unneed( id->p_decoder, id->p_decoder->p_module );
981             id->p_decoder->p_module = 0;
982             module_Unneed( id->p_encoder, id->p_encoder->p_module );
983             id->p_encoder->p_module = 0;
984             return VLC_EGENERIC;
985         }
986
987         id->pp_filter[0]->fmt_out.audio.i_bitspersample = 
988             audio_BitsPerSample( id->pp_filter[0]->fmt_out.i_codec );
989
990         /* Try a 2 stage conversion */
991         if( id->pp_filter[0]->fmt_out.i_codec !=
992             id->p_encoder->fmt_in.i_codec )
993         {
994             id->pp_filter[1] =
995                 vlc_object_create( p_stream, VLC_OBJECT_FILTER );
996             vlc_object_attach( id->pp_filter[1], p_stream );
997
998             id->pp_filter[1]->pf_audio_buffer_new = __block_New;
999
1000             id->pp_filter[1]->fmt_in = id->pp_filter[0]->fmt_out;
1001             id->pp_filter[1]->fmt_out = id->p_encoder->fmt_in;
1002             id->pp_filter[1]->p_module =
1003               module_Need( id->pp_filter[1], "audio filter2", 0, 0 );
1004             if( !id->pp_filter[1]->p_module ||
1005                 id->pp_filter[1]->fmt_out.i_codec !=
1006                   id->p_encoder->fmt_in.i_codec )
1007             {
1008                 msg_Dbg( p_stream, "no audio filter found (%4.4s->%4.4s)",
1009                          (char *)&id->pp_filter[1]->fmt_in,
1010                          (char *)&id->pp_filter[1]->fmt_out );
1011                 module_Unneed( id->pp_filter[0], id->pp_filter[0]->p_module );
1012                 vlc_object_detach( id->pp_filter[0] );
1013                 vlc_object_destroy( id->pp_filter[0] );
1014                 if( id->pp_filter[1]->p_module )
1015                 module_Unneed( id->pp_filter[0], id->pp_filter[0]->p_module );
1016                 vlc_object_detach( id->pp_filter[1] );
1017                 vlc_object_destroy( id->pp_filter[1] );
1018                 module_Unneed( id->p_decoder, id->p_decoder->p_module );
1019                 id->p_decoder->p_module = 0;
1020                 module_Unneed( id->p_encoder, id->p_encoder->p_module );
1021                 id->p_encoder->p_module = 0;
1022                 return VLC_EGENERIC;
1023             }
1024             else id->i_filter++;
1025         }
1026     }
1027
1028     /* FIXME: Hack for mp3 transcoding support */
1029     if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC( 'm','p','3',' ' ) )
1030         id->p_encoder->fmt_out.i_codec = VLC_FOURCC( 'm','p','g','a' );
1031
1032     return VLC_SUCCESS;
1033 }
1034
1035 static void transcode_audio_close( sout_stream_t *p_stream,
1036                                    sout_stream_id_t *id )
1037 {
1038     int i;
1039
1040     /* Close decoder */
1041     if( id->p_decoder->p_module )
1042         module_Unneed( id->p_decoder, id->p_decoder->p_module );
1043
1044     /* Close encoder */
1045     if( id->p_encoder->p_module )
1046         module_Unneed( id->p_encoder, id->p_encoder->p_module );
1047
1048     /* Close filters */
1049     for( i = 0; i < id->i_filter; i++ )
1050     {
1051         vlc_object_detach( id->pp_filter[i] );
1052         if( id->pp_filter[i]->p_module )
1053             module_Unneed( id->pp_filter[i], id->pp_filter[i]->p_module );
1054         vlc_object_destroy( id->pp_filter[i] );
1055     }
1056 }
1057
1058 static int transcode_audio_process( sout_stream_t *p_stream,
1059                                     sout_stream_id_t *id,
1060                                     block_t *in, block_t **out )
1061 {
1062     sout_stream_sys_t *p_sys = p_stream->p_sys;
1063     aout_buffer_t *p_audio_buf;
1064     block_t *p_block, *p_audio_block;
1065     int i;
1066     *out = NULL;
1067
1068     while( (p_audio_buf = id->p_decoder->pf_decode_audio( id->p_decoder,
1069                                                           &in )) )
1070     {
1071         if( p_sys->b_master_sync )
1072         {
1073             mtime_t i_dts = date_Get( &id->interpolated_pts ) + 1;
1074             p_sys->i_master_drift = p_audio_buf->start_date - i_dts;
1075             date_Increment( &id->interpolated_pts, p_audio_buf->i_nb_samples );
1076             p_audio_buf->start_date -= p_sys->i_master_drift;
1077             p_audio_buf->end_date -= p_sys->i_master_drift;
1078         }
1079
1080         p_audio_block = p_audio_buf->p_sys;
1081         p_audio_block->i_buffer = p_audio_buf->i_nb_bytes;
1082         p_audio_block->i_dts = p_audio_block->i_pts =
1083             p_audio_buf->start_date;
1084         p_audio_block->i_length = p_audio_buf->end_date -
1085             p_audio_buf->start_date;
1086         p_audio_block->i_samples = p_audio_buf->i_nb_samples;
1087
1088         /* Run filter chain */
1089         for( i = 0; i < id->i_filter; i++ )
1090         {
1091             p_audio_block =
1092                 id->pp_filter[i]->pf_audio_filter( id->pp_filter[i],
1093                                                    p_audio_block );
1094         }
1095
1096         p_audio_buf->p_buffer = p_audio_block->p_buffer;
1097         p_audio_buf->i_nb_bytes = p_audio_block->i_buffer;
1098         p_audio_buf->i_nb_samples = p_audio_block->i_samples;
1099         p_audio_buf->start_date = p_audio_block->i_dts;
1100         p_audio_buf->end_date = p_audio_block->i_dts + p_audio_block->i_length;
1101
1102         p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf );
1103         block_ChainAppend( out, p_block );
1104         block_Release( p_audio_block );
1105         free( p_audio_buf );
1106     }
1107
1108     return VLC_SUCCESS;
1109 }
1110
1111 static void audio_release_buffer( aout_buffer_t *p_buffer )
1112 {
1113     if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
1114     if( p_buffer ) free( p_buffer );
1115 }
1116
1117 static aout_buffer_t *audio_new_buffer( decoder_t *p_dec, int i_samples )
1118 {
1119     aout_buffer_t *p_buffer;
1120     block_t *p_block;
1121     int i_size;
1122
1123     if( p_dec->fmt_out.audio.i_bitspersample )
1124     {
1125         i_size = i_samples * p_dec->fmt_out.audio.i_bitspersample / 8 *
1126             p_dec->fmt_out.audio.i_channels;
1127     }
1128     else if( p_dec->fmt_out.audio.i_bytes_per_frame &&
1129              p_dec->fmt_out.audio.i_frame_length )
1130     {
1131         i_size = i_samples * p_dec->fmt_out.audio.i_bytes_per_frame /
1132             p_dec->fmt_out.audio.i_frame_length;
1133     }
1134     else
1135     {
1136         i_size = i_samples * 4 * p_dec->fmt_out.audio.i_channels;
1137     }
1138
1139     p_buffer = malloc( sizeof(aout_buffer_t) );
1140     p_buffer->pf_release = audio_release_buffer;
1141     p_buffer->p_sys = p_block = block_New( p_dec, i_size );
1142
1143     p_buffer->p_buffer = p_block->p_buffer;
1144     p_buffer->i_size = p_buffer->i_nb_bytes = p_block->i_buffer;
1145     p_buffer->i_nb_samples = i_samples;
1146     p_block->i_samples = i_samples;
1147
1148     return p_buffer;
1149 }
1150
1151 static void audio_del_buffer( decoder_t *p_dec, aout_buffer_t *p_buffer )
1152 {
1153     if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys );
1154     if( p_buffer ) free( p_buffer );
1155 }
1156
1157 /*
1158  * video
1159  */
1160 static int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_t *id )
1161 {
1162     sout_stream_sys_t *p_sys = p_stream->p_sys;
1163     int i;
1164
1165     /*
1166      * Open decoder
1167      */
1168
1169     /* Initialization of decoder structures */
1170     id->p_decoder->pf_decode_video = 0;
1171     id->p_decoder->pf_vout_buffer_new = video_new_buffer_decoder;
1172     id->p_decoder->pf_vout_buffer_del = video_del_buffer_decoder;
1173     id->p_decoder->pf_picture_link    = video_link_picture_decoder;
1174     id->p_decoder->pf_picture_unlink  = video_unlink_picture_decoder;
1175     id->p_decoder->p_owner = malloc( sizeof(decoder_owner_sys_t) );
1176     for( i = 0; i < PICTURE_RING_SIZE; i++ )
1177         id->p_decoder->p_owner->pp_pics[i] = 0;
1178     //id->p_decoder->p_cfg = p_sys->p_video_cfg;
1179
1180     id->p_decoder->p_module =
1181         module_Need( id->p_decoder, "decoder", "$codec", 0 );
1182
1183     if( !id->p_decoder->p_module )
1184     {
1185         msg_Err( p_stream, "cannot find decoder" );
1186         return VLC_EGENERIC;
1187     }
1188
1189     /*
1190      * Open encoder.
1191      * Because some info about the decoded input will only be available
1192      * once the first frame is decoded, we actually only test the availability
1193      * of the encoder here.
1194      */
1195
1196     /* Initialization of encoder format structures */
1197     es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1198                     id->p_decoder->fmt_out.i_codec );
1199     id->p_encoder->fmt_in.video.i_chroma = id->p_decoder->fmt_out.i_codec;
1200
1201     /* The dimensions will be set properly later on.
1202      * Just put sensible values so we can test an encoder is available. */
1203     id->p_encoder->fmt_in.video.i_width =
1204         id->p_encoder->fmt_out.video.i_width ?
1205         id->p_encoder->fmt_out.video.i_width :
1206         id->p_decoder->fmt_in.video.i_width ?
1207         id->p_decoder->fmt_in.video.i_width : 16;
1208     id->p_encoder->fmt_in.video.i_height =
1209         id->p_encoder->fmt_out.video.i_height ?
1210         id->p_encoder->fmt_out.video.i_height :
1211         id->p_decoder->fmt_in.video.i_height ?
1212         id->p_decoder->fmt_in.video.i_height : 16;
1213     id->p_encoder->fmt_in.video.i_frame_rate = 25;
1214     id->p_encoder->fmt_in.video.i_frame_rate_base = 1;
1215
1216     id->p_encoder->i_threads = p_sys->i_threads;
1217     id->p_encoder->p_cfg = p_sys->p_video_cfg;
1218
1219     id->p_encoder->p_module =
1220         module_Need( id->p_encoder, "encoder", p_sys->psz_venc, VLC_TRUE );
1221     if( !id->p_encoder->p_module )
1222     {
1223         msg_Err( p_stream, "cannot find encoder" );
1224         module_Unneed( id->p_decoder, id->p_decoder->p_module );
1225         id->p_decoder->p_module = 0;
1226         return VLC_EGENERIC;
1227     }
1228
1229     /* Close the encoder.
1230      * We'll open it only when we have the first frame. */
1231     module_Unneed( id->p_encoder, id->p_encoder->p_module );
1232     id->p_encoder->p_module = NULL;
1233
1234     if( p_sys->i_threads >= 1 )
1235     {
1236         p_sys->id_video = id;
1237         vlc_mutex_init( p_stream, &p_sys->lock_out );
1238         vlc_cond_init( p_stream, &p_sys->cond );
1239         memset( p_sys->pp_pics, 0, sizeof(p_sys->pp_pics) );
1240         p_sys->i_first_pic = 0;
1241         p_sys->i_last_pic = 0;
1242         p_sys->p_buffers = NULL;
1243         p_sys->b_die = p_sys->b_error = 0;
1244         if( vlc_thread_create( p_sys, "encoder", EncoderThread,
1245                                VLC_THREAD_PRIORITY_VIDEO, VLC_FALSE ) )
1246         {
1247             msg_Err( p_stream, "cannot spawn encoder thread" );
1248             module_Unneed( id->p_decoder, id->p_decoder->p_module );
1249             id->p_decoder->p_module = 0;
1250             return VLC_EGENERIC;
1251         }
1252     }
1253
1254     date_Set( &id->interpolated_pts, 0 );
1255
1256     return VLC_SUCCESS;
1257 }
1258
1259 static int transcode_video_encoder_open( sout_stream_t *p_stream,
1260                                          sout_stream_id_t *id )
1261 {
1262     sout_stream_sys_t *p_sys = p_stream->p_sys;
1263
1264     /* Hack because of the copy packetizer which can fail to detect the
1265      * proper size (which forces us to wait until the 1st frame
1266      * is decoded) */
1267     int i_width = id->p_decoder->fmt_out.video.i_width -
1268         p_sys->i_crop_left - p_sys->i_crop_right;
1269     int i_height = id->p_decoder->fmt_out.video.i_height -
1270         p_sys->i_crop_top - p_sys->i_crop_bottom;
1271
1272     if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1273         id->p_encoder->fmt_out.video.i_height <= 0 && p_sys->f_scale )
1274     {
1275         /* Apply the scaling */
1276         id->p_encoder->fmt_out.video.i_width = i_width * p_sys->f_scale;
1277         id->p_encoder->fmt_out.video.i_height = i_height * p_sys->f_scale;
1278     }
1279     else if( id->p_encoder->fmt_out.video.i_width > 0 &&
1280              id->p_encoder->fmt_out.video.i_height <= 0 )
1281     {
1282         id->p_encoder->fmt_out.video.i_height =
1283             id->p_encoder->fmt_out.video.i_width / (double)i_width * i_height;
1284     }
1285     else if( id->p_encoder->fmt_out.video.i_width <= 0 &&
1286              id->p_encoder->fmt_out.video.i_height > 0 )
1287     {
1288         id->p_encoder->fmt_out.video.i_width =
1289             id->p_encoder->fmt_out.video.i_height / (double)i_height * i_width;
1290     }
1291
1292     /* Make sure the size is at least a multiple of 2 */
1293     id->p_encoder->fmt_out.video.i_width =
1294         (id->p_encoder->fmt_out.video.i_width + 1) >> 1 << 1;
1295     id->p_encoder->fmt_out.video.i_height =
1296         (id->p_encoder->fmt_out.video.i_height + 1) >> 1 << 1;
1297
1298     id->p_encoder->fmt_in.video.i_width =
1299         id->p_encoder->fmt_out.video.i_width;
1300     id->p_encoder->fmt_in.video.i_height =
1301         id->p_encoder->fmt_out.video.i_height;
1302
1303     if( !id->p_encoder->fmt_out.video.i_frame_rate ||
1304         !id->p_encoder->fmt_out.video.i_frame_rate_base )
1305     {
1306         if( id->p_decoder->fmt_out.video.i_frame_rate &&
1307             id->p_decoder->fmt_out.video.i_frame_rate_base )
1308         {
1309             id->p_encoder->fmt_out.video.i_frame_rate =
1310                 id->p_decoder->fmt_out.video.i_frame_rate;
1311             id->p_encoder->fmt_out.video.i_frame_rate_base =
1312                 id->p_decoder->fmt_out.video.i_frame_rate_base;
1313         }
1314         else
1315         {
1316             /* Pick a sensible default value */
1317             id->p_encoder->fmt_out.video.i_frame_rate = 25;
1318             id->p_encoder->fmt_out.video.i_frame_rate_base = 1;
1319         }
1320     }
1321
1322     id->p_encoder->fmt_in.video.i_frame_rate =
1323         id->p_encoder->fmt_out.video.i_frame_rate;
1324     id->p_encoder->fmt_in.video.i_frame_rate_base =
1325         id->p_encoder->fmt_out.video.i_frame_rate_base;
1326
1327     date_Init( &id->interpolated_pts,
1328                id->p_encoder->fmt_out.video.i_frame_rate,
1329                id->p_encoder->fmt_out.video.i_frame_rate_base );
1330
1331     /* Check whether a particular aspect ratio was requested */
1332     if( !id->p_encoder->fmt_out.video.i_aspect )
1333     {
1334         id->p_encoder->fmt_out.video.i_aspect =
1335             id->p_decoder->fmt_out.video.i_aspect;
1336     }
1337     id->p_encoder->fmt_in.video.i_aspect =
1338         id->p_encoder->fmt_out.video.i_aspect;
1339
1340     id->p_encoder->p_module =
1341         module_Need( id->p_encoder, "encoder", p_sys->psz_venc, VLC_TRUE );
1342     if( !id->p_encoder->p_module )
1343     {
1344         msg_Err( p_stream, "cannot find encoder" );
1345         return VLC_EGENERIC;
1346     }
1347
1348     id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
1349
1350     /* Hack for mp2v/mp1v transcoding support */
1351     if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','1','v') ||
1352         id->p_encoder->fmt_out.i_codec == VLC_FOURCC('m','p','2','v') )
1353     {
1354         id->p_encoder->fmt_out.i_codec = VLC_FOURCC('m','p','g','v');
1355     }
1356
1357     id->id = p_stream->p_sys->p_out->pf_add( p_stream->p_sys->p_out,
1358                                              &id->p_encoder->fmt_out );
1359     if( !id->id )
1360     {
1361         msg_Err( p_stream, "cannot add this stream" );
1362         return VLC_EGENERIC;
1363     }
1364
1365     return VLC_SUCCESS;
1366 }
1367
1368 static void transcode_video_close( sout_stream_t *p_stream,
1369                                    sout_stream_id_t *id )
1370 {
1371     int i, j;
1372
1373     if( p_stream->p_sys->i_threads >= 1 )
1374     {
1375         vlc_mutex_lock( &p_stream->p_sys->lock_out );
1376         p_stream->p_sys->b_die = 1;
1377         vlc_cond_signal( &p_stream->p_sys->cond );
1378         vlc_mutex_unlock( &p_stream->p_sys->lock_out );
1379         vlc_thread_join( p_stream->p_sys );
1380         vlc_mutex_destroy( &p_stream->p_sys->lock_out );
1381         vlc_cond_destroy( &p_stream->p_sys->cond );
1382     }
1383
1384     /* Close decoder */
1385     if( id->p_decoder->p_module )
1386         module_Unneed( id->p_decoder, id->p_decoder->p_module );
1387
1388     if( id->p_decoder->p_owner )
1389     {
1390         /* Clean-up pictures ring buffer */
1391         for( i = 0; i < PICTURE_RING_SIZE; i++ )
1392         {
1393             if( id->p_decoder->p_owner->pp_pics[i] )
1394                 video_del_buffer( VLC_OBJECT(id->p_decoder),
1395                                   id->p_decoder->p_owner->pp_pics[i] );
1396         }
1397         free( id->p_decoder->p_owner );
1398     }
1399
1400     /* Close encoder */
1401     if( id->p_encoder->p_module )
1402         module_Unneed( id->p_encoder, id->p_encoder->p_module );
1403
1404     /* Close filters */
1405     for( i = 0; i < id->i_filter; i++ )
1406     {
1407         vlc_object_detach( id->pp_filter[i] );
1408         if( id->pp_filter[i]->p_module )
1409             module_Unneed( id->pp_filter[i], id->pp_filter[i]->p_module );
1410
1411         /* Clean-up pictures ring buffer */
1412         for( j = 0; j < PICTURE_RING_SIZE; j++ )
1413         {
1414             if( id->pp_filter[i]->p_owner->pp_pics[j] )
1415                 video_del_buffer( VLC_OBJECT(id->pp_filter[i]),
1416                                   id->pp_filter[i]->p_owner->pp_pics[j] );
1417         }
1418         free( id->pp_filter[i]->p_owner );
1419
1420         vlc_object_destroy( id->pp_filter[i] );
1421     }
1422 }
1423
1424 static int transcode_video_process( sout_stream_t *p_stream,
1425                                     sout_stream_id_t *id,
1426                                     block_t *in, block_t **out )
1427 {
1428     sout_stream_sys_t *p_sys = p_stream->p_sys;
1429     int i_duplicate = 1, i;
1430     picture_t *p_pic;
1431     *out = NULL;
1432
1433     while( (p_pic = id->p_decoder->pf_decode_video( id->p_decoder, &in )) )
1434     {
1435         subpicture_t *p_subpic = 0;
1436
1437         if( p_sys->b_master_sync )
1438         {
1439             mtime_t i_video_drift;
1440             mtime_t i_master_drift = p_sys->i_master_drift;
1441             mtime_t i_pts;
1442
1443             if( !i_master_drift )
1444             {
1445                 /* No audio track ? */
1446                 p_sys->i_master_drift = i_master_drift = p_pic->date;
1447             }
1448
1449             i_pts = date_Get( &id->interpolated_pts ) + 1;
1450             i_video_drift = p_pic->date - i_pts;
1451             i_duplicate = 1;
1452
1453             /* Set the pts of the frame being encoded */
1454             p_pic->date = i_pts;
1455
1456             if( i_video_drift < i_master_drift - 50000 )
1457             {
1458 #if 0
1459                 msg_Dbg( p_stream, "dropping frame (%i)",
1460                          (int)(i_video_drift - i_master_drift) );
1461 #endif
1462                 p_pic->pf_release( p_pic );
1463                 return VLC_EGENERIC;
1464             }
1465             else if( i_video_drift > i_master_drift + 50000 )
1466             {
1467 #if 0
1468                 msg_Dbg( p_stream, "adding frame (%i)",
1469                          (int)(i_video_drift - i_master_drift) );
1470 #endif
1471                 i_duplicate = 2;
1472             }
1473         }
1474
1475         if( !id->p_encoder->p_module )
1476         {
1477             if( transcode_video_encoder_open( p_stream, id ) != VLC_SUCCESS )
1478             {
1479                 transcode_video_close( p_stream, id );
1480                 id->b_transcode = VLC_FALSE;
1481                 p_pic->pf_release( p_pic );
1482                 return VLC_EGENERIC;
1483             }
1484
1485             /* Deinterlace */
1486             if( p_stream->p_sys->b_deinterlace )
1487             {
1488                 id->pp_filter[id->i_filter] =
1489                     vlc_object_create( p_stream, VLC_OBJECT_FILTER );
1490                 vlc_object_attach( id->pp_filter[id->i_filter], p_stream );
1491
1492                 id->pp_filter[id->i_filter]->pf_vout_buffer_new =
1493                     video_new_buffer_filter;
1494                 id->pp_filter[id->i_filter]->pf_vout_buffer_del =
1495                     video_del_buffer_filter;
1496
1497                 id->pp_filter[id->i_filter]->fmt_in = id->p_decoder->fmt_out;
1498                 id->pp_filter[id->i_filter]->fmt_out = id->p_decoder->fmt_out;
1499                 id->pp_filter[id->i_filter]->p_module =
1500                     module_Need( id->pp_filter[id->i_filter],
1501                                  "video filter2", "deinterlace", 0 );
1502                 if( id->pp_filter[id->i_filter]->p_module )
1503                 {
1504                     id->pp_filter[id->i_filter]->p_owner =
1505                         malloc( sizeof(filter_owner_sys_t) );
1506                     for( i = 0; i < PICTURE_RING_SIZE; i++ )
1507                         id->pp_filter[id->i_filter]->p_owner->pp_pics[i] = 0;
1508
1509                     id->i_filter++;
1510                 }
1511                 else
1512                 {
1513                     msg_Dbg( p_stream, "no video filter found" );
1514                     vlc_object_detach( id->pp_filter[id->i_filter] );
1515                     vlc_object_destroy( id->pp_filter[id->i_filter] );
1516                 }
1517             }
1518
1519             /* Check if we need a filter for chroma conversion or resizing */
1520             if( id->p_decoder->fmt_out.video.i_chroma !=
1521                 id->p_encoder->fmt_in.video.i_chroma ||
1522                 id->p_decoder->fmt_out.video.i_width !=
1523                 id->p_encoder->fmt_out.video.i_width ||
1524                 id->p_decoder->fmt_out.video.i_height !=
1525                 id->p_encoder->fmt_out.video.i_height ||
1526                 p_sys->i_crop_top > 0 || p_sys->i_crop_bottom > 0 ||
1527                 p_sys->i_crop_left > 0 || p_sys->i_crop_right > 0 )
1528             {
1529                 id->pp_filter[id->i_filter] =
1530                     vlc_object_create( p_stream, VLC_OBJECT_FILTER );
1531                 vlc_object_attach( id->pp_filter[id->i_filter], p_stream );
1532
1533                 id->pp_filter[id->i_filter]->pf_vout_buffer_new =
1534                     video_new_buffer_filter;
1535                 id->pp_filter[id->i_filter]->pf_vout_buffer_del =
1536                     video_del_buffer_filter;
1537
1538                 id->pp_filter[id->i_filter]->fmt_in = id->p_decoder->fmt_out;
1539                 id->pp_filter[id->i_filter]->fmt_out = id->p_encoder->fmt_in;
1540                 id->pp_filter[id->i_filter]->p_module =
1541                     module_Need( id->pp_filter[id->i_filter],
1542                                  "video filter2", 0, 0 );
1543                 if( id->pp_filter[id->i_filter]->p_module )
1544                 {
1545                     id->pp_filter[id->i_filter]->p_owner =
1546                         malloc( sizeof(filter_owner_sys_t) );
1547                     for( i = 0; i < PICTURE_RING_SIZE; i++ )
1548                         id->pp_filter[id->i_filter]->p_owner->pp_pics[i] = 0;
1549
1550                     id->i_filter++;
1551                 }
1552                 else
1553                 {
1554                     msg_Dbg( p_stream, "no video filter found" );
1555                     vlc_object_detach( id->pp_filter[id->i_filter] );
1556                     vlc_object_destroy( id->pp_filter[id->i_filter] );
1557
1558                     transcode_video_close( p_stream, id );
1559                     id->b_transcode = VLC_FALSE;
1560                     p_pic->pf_release( p_pic );
1561                     return VLC_EGENERIC;
1562                 }
1563             }
1564         }
1565
1566         /* Run filter chain */
1567         for( i = 0; i < id->i_filter; i++ )
1568         {
1569             p_pic = id->pp_filter[i]->pf_video_filter(id->pp_filter[i], p_pic);
1570         }
1571
1572         /*
1573          * Encoding
1574          */
1575
1576         /* Check if we have a subpicture to overlay */
1577         if( p_sys->p_spu )
1578         {
1579             p_subpic = spu_SortSubpictures( p_sys->p_spu, p_pic->date );
1580             /* TODO: get another pic */
1581         }
1582
1583         /* Overlay subpicture */
1584         if( p_subpic )
1585         {
1586             int i_scale_width, i_scale_height;
1587             video_format_t *p_fmt;
1588
1589             i_scale_width = id->p_encoder->fmt_in.video.i_width * 1000 /
1590                 id->p_decoder->fmt_out.video.i_width;
1591             i_scale_height = id->p_encoder->fmt_in.video.i_height * 1000 /
1592                 id->p_decoder->fmt_out.video.i_height;
1593
1594             if( p_pic->i_refcount && !id->i_filter )
1595             {
1596                 /* We can't modify the picture, we need to duplicate it */
1597                 picture_t *p_tmp = video_new_buffer_decoder( id->p_decoder );
1598                 if( p_tmp )
1599                 {
1600                     vout_CopyPicture( p_stream, p_tmp, p_pic );
1601                     p_pic->pf_release( p_pic );
1602                     p_pic = p_tmp;
1603                 }
1604             }
1605
1606             if( id->i_filter )
1607                 p_fmt = &id->pp_filter[id->i_filter -1]->fmt_out.video;
1608             else
1609                 p_fmt = &id->p_decoder->fmt_out.video;
1610
1611             /* FIXME (shouldn't have to be done here) */
1612             p_fmt->i_sar_num = p_fmt->i_aspect *
1613                 p_fmt->i_height / p_fmt->i_width;
1614             p_fmt->i_sar_den = VOUT_ASPECT_FACTOR;
1615
1616             spu_RenderSubpictures( p_sys->p_spu, p_fmt, p_pic, p_pic, p_subpic,
1617                                    i_scale_width, i_scale_height );
1618         }
1619
1620         if( p_sys->i_threads >= 1 )
1621         {
1622             vlc_mutex_lock( &p_sys->lock_out );
1623             p_sys->pp_pics[p_sys->i_last_pic++] = p_pic;
1624             p_sys->i_last_pic %= PICTURE_RING_SIZE;
1625             *out = p_sys->p_buffers;
1626             p_sys->p_buffers = NULL;
1627             vlc_cond_signal( &p_sys->cond );
1628             vlc_mutex_unlock( &p_sys->lock_out );
1629         }
1630         else
1631         {
1632             block_t *p_block;
1633             p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
1634             block_ChainAppend( out, p_block );
1635
1636             if( p_sys->b_master_sync )
1637                 date_Increment( &id->interpolated_pts, 1 );
1638
1639             if( p_sys->b_master_sync && i_duplicate > 1 )
1640             {
1641                 mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
1642                 date_Increment( &id->interpolated_pts, 1 );
1643                 p_pic->date = i_pts;
1644                 p_block = id->p_encoder->pf_encode_video(id->p_encoder, p_pic);
1645                 block_ChainAppend( out, p_block );
1646             }
1647
1648             p_pic->pf_release( p_pic );
1649         }
1650     }
1651
1652     return VLC_SUCCESS;
1653 }
1654
1655 static int EncoderThread( sout_stream_sys_t *p_sys )
1656 {
1657     sout_stream_id_t *id = p_sys->id_video;
1658     picture_t *p_pic;
1659     int i_plane;
1660
1661     while( !p_sys->b_die && !p_sys->b_error )
1662     {
1663         block_t *p_block;
1664
1665         vlc_mutex_lock( &p_sys->lock_out );
1666         while( p_sys->i_last_pic == p_sys->i_first_pic )
1667         {
1668             vlc_cond_wait( &p_sys->cond, &p_sys->lock_out );
1669             if( p_sys->b_die || p_sys->b_error ) break;
1670         }
1671         if( p_sys->b_die || p_sys->b_error )
1672         {
1673             vlc_mutex_unlock( &p_sys->lock_out );
1674             break;
1675         }
1676
1677         p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
1678         p_sys->i_first_pic %= PICTURE_RING_SIZE;
1679         vlc_mutex_unlock( &p_sys->lock_out );
1680
1681         p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
1682         vlc_mutex_lock( &p_sys->lock_out );
1683         block_ChainAppend( &p_sys->p_buffers, p_block );
1684         vlc_mutex_unlock( &p_sys->lock_out );
1685
1686         for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
1687         {
1688             free( p_pic->p[i_plane].p_pixels );
1689         }
1690         free( p_pic );
1691     }
1692
1693     while( p_sys->i_last_pic != p_sys->i_first_pic )
1694     {
1695         p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
1696         p_sys->i_first_pic %= PICTURE_RING_SIZE;
1697
1698         for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
1699         {
1700             free( p_pic->p[i_plane].p_pixels );
1701         }
1702         free( p_pic );
1703     }
1704
1705     block_ChainRelease( p_sys->p_buffers );
1706
1707     return 0;
1708 }
1709
1710 struct picture_sys_t
1711 {
1712     vlc_object_t *p_owner;
1713 };
1714
1715 static void video_release_buffer( picture_t *p_pic )
1716 {
1717     if( p_pic && !p_pic->i_refcount && p_pic->pf_release && p_pic->p_sys )
1718     {
1719         video_del_buffer_decoder( (decoder_t *)p_pic->p_sys->p_owner, p_pic );
1720     }
1721     else if( p_pic && p_pic->i_refcount > 0 ) p_pic->i_refcount--;
1722 }
1723
1724 static picture_t *video_new_buffer( vlc_object_t *p_this, picture_t **pp_ring )
1725 {
1726     decoder_t *p_dec = (decoder_t *)p_this;
1727     picture_t *p_pic;
1728     int i;
1729
1730     /* Find an empty space in the picture ring buffer */
1731     for( i = 0; i < PICTURE_RING_SIZE; i++ )
1732     {
1733         if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE )
1734         {
1735             pp_ring[i]->i_status = RESERVED_PICTURE;
1736             return pp_ring[i];
1737         }
1738     }
1739     for( i = 0; i < PICTURE_RING_SIZE; i++ )
1740     {
1741         if( pp_ring[i] == 0 ) break;
1742     }
1743
1744     if( i == PICTURE_RING_SIZE )
1745     {
1746         msg_Err( p_this, "decoder/filter is leaking pictures, "
1747                  "resetting its ring buffer" );
1748
1749         for( i = 0; i < PICTURE_RING_SIZE; i++ )
1750         {
1751             pp_ring[i]->pf_release( pp_ring[i] );
1752         }
1753
1754         i = 0;
1755     }
1756
1757     p_pic = malloc( sizeof(picture_t) );
1758     p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
1759     vout_AllocatePicture( VLC_OBJECT(p_dec), p_pic,
1760                           p_dec->fmt_out.video.i_chroma,
1761                           p_dec->fmt_out.video.i_width,
1762                           p_dec->fmt_out.video.i_height,
1763                           p_dec->fmt_out.video.i_aspect );
1764
1765     if( !p_pic->i_planes )
1766     {
1767         free( p_pic );
1768         return 0;
1769     }
1770
1771     p_pic->pf_release = video_release_buffer;
1772     p_pic->p_sys = malloc( sizeof(picture_sys_t) );
1773     p_pic->p_sys->p_owner = p_this;
1774     p_pic->i_status = RESERVED_PICTURE;
1775
1776     pp_ring[i] = p_pic;
1777
1778     return p_pic;
1779 }
1780
1781 static picture_t *video_new_buffer_decoder( decoder_t *p_dec )
1782 {
1783     return video_new_buffer( VLC_OBJECT(p_dec),
1784                              p_dec->p_owner->pp_pics );
1785 }
1786
1787 static picture_t *video_new_buffer_filter( filter_t *p_filter )
1788 {
1789     return video_new_buffer( VLC_OBJECT(p_filter),
1790                              p_filter->p_owner->pp_pics );
1791 }
1792
1793 static void video_del_buffer( vlc_object_t *p_this, picture_t *p_pic )
1794 {
1795     if( p_pic && p_pic->p_data_orig ) free( p_pic->p_data_orig );
1796     if( p_pic && p_pic->p_sys ) free( p_pic->p_sys );
1797     if( p_pic ) free( p_pic );
1798 }
1799
1800 static void video_del_buffer_decoder( decoder_t *p_decoder, picture_t *p_pic )
1801 {
1802     p_pic->i_refcount = 0;
1803     p_pic->i_status = DESTROYED_PICTURE;
1804 }
1805
1806 static void video_del_buffer_filter( filter_t *p_filter, picture_t *p_pic )
1807 {
1808     p_pic->i_refcount = 0;
1809     p_pic->i_status = DESTROYED_PICTURE;
1810 }
1811
1812 static void video_link_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
1813 {
1814     p_pic->i_refcount++;
1815 }
1816
1817 static void video_unlink_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
1818 {
1819     video_release_buffer( p_pic );
1820 }
1821
1822 /*
1823  * SPU
1824  */
1825 static subpicture_t *spu_new_buffer( decoder_t * );
1826 static void spu_del_buffer( decoder_t *, subpicture_t * );
1827
1828 static int transcode_spu_new( sout_stream_t *p_stream, sout_stream_id_t *id )
1829 {
1830     sout_stream_sys_t *p_sys = p_stream->p_sys;
1831
1832     /*
1833      * Open decoder
1834      */
1835
1836     /* Initialization of decoder structures */
1837     id->p_decoder->pf_spu_buffer_new = spu_new_buffer;
1838     id->p_decoder->pf_spu_buffer_del = spu_del_buffer;
1839     id->p_decoder->p_owner = (decoder_owner_sys_t *)p_stream;
1840     //id->p_decoder->p_cfg = p_sys->p_spu_cfg;
1841
1842     id->p_decoder->p_module =
1843         module_Need( id->p_decoder, "decoder", "$codec", 0 );
1844
1845     if( !id->p_decoder->p_module )
1846     {
1847         msg_Err( p_stream, "cannot find decoder" );
1848         return VLC_EGENERIC;
1849     }
1850
1851     if( !p_sys->b_soverlay )
1852     {
1853         /*
1854          * Open encoder
1855          */
1856
1857         /* Initialization of encoder format structures */
1858         es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
1859                         id->p_decoder->fmt_in.i_codec );
1860
1861         id->p_encoder->p_cfg = p_sys->p_spu_cfg;
1862
1863         id->p_encoder->p_module =
1864             module_Need( id->p_encoder, "encoder", p_sys->psz_senc, VLC_TRUE );
1865
1866         if( !id->p_encoder->p_module )
1867         {
1868             module_Unneed( id->p_decoder, id->p_decoder->p_module );
1869             msg_Err( p_stream, "cannot find encoder" );
1870             return VLC_EGENERIC;
1871         }
1872     }
1873
1874     if( !p_sys->p_spu )
1875     {
1876         p_sys->p_spu = spu_Create( p_stream );
1877         spu_Init( p_sys->p_spu );
1878     }
1879
1880     return VLC_SUCCESS;
1881 }
1882
1883 static void transcode_spu_close( sout_stream_t *p_stream, sout_stream_id_t *id)
1884 {
1885     /* Close decoder */
1886     if( id->p_decoder->p_module )
1887         module_Unneed( id->p_decoder, id->p_decoder->p_module );
1888
1889     /* Close encoder */
1890     if( id->p_encoder->p_module )
1891         module_Unneed( id->p_encoder, id->p_encoder->p_module );
1892 }
1893
1894 static int transcode_spu_process( sout_stream_t *p_stream,
1895                                   sout_stream_id_t *id,
1896                                   block_t *in, block_t **out )
1897 {
1898     sout_stream_sys_t *p_sys = p_stream->p_sys;
1899     subpicture_t *p_subpic;
1900     *out = NULL;
1901
1902     p_subpic = id->p_decoder->pf_decode_sub( id->p_decoder, &in );
1903     if( !p_subpic ) return VLC_EGENERIC;
1904
1905     if( p_sys->b_master_sync && p_sys->i_master_drift )
1906     {
1907         p_subpic->i_start -= p_sys->i_master_drift;
1908         if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
1909     }
1910
1911     if( p_sys->b_soverlay )
1912     {
1913         spu_DisplaySubpicture( p_sys->p_spu, p_subpic );
1914     }
1915     else
1916     {
1917         block_t *p_block;
1918
1919         p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
1920         spu_del_buffer( id->p_decoder, p_subpic );
1921
1922         if( p_block )
1923         {
1924             block_ChainAppend( out, p_block );
1925             return VLC_SUCCESS;
1926         }
1927     }
1928
1929     return VLC_EGENERIC;
1930 }
1931
1932 static subpicture_t *spu_new_buffer( decoder_t *p_dec )
1933 {
1934     sout_stream_t *p_stream = (sout_stream_t *)p_dec->p_owner;
1935     return spu_CreateSubpicture( p_stream->p_sys->p_spu );
1936 }
1937
1938 static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_subpic )
1939 {
1940     sout_stream_t *p_stream = (sout_stream_t *)p_dec->p_owner;
1941     spu_DestroySubpicture( p_stream->p_sys->p_spu, p_subpic );
1942 }