]> git.sesse.net Git - vlc/blob - modules/stream_out/transcode.c
Added HuffYuv and A-law codes for low bitrate and CPU load encodings/transcoding
[vlc] / modules / stream_out / transcode.c
1 /*****************************************************************************
2  * transcode.c
3  *****************************************************************************
4  * Copyright (C) 2001, 2002 VideoLAN
5  * $Id: transcode.c,v 1.27 2003/07/28 20:25:30 jpsaman Exp $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include <vlc/vlc.h>
31 #include <vlc/input.h>
32 #include <vlc/sout.h>
33
34 /* ffmpeg header */
35 #ifdef HAVE_FFMPEG_AVCODEC_H
36 #   include <ffmpeg/avcodec.h>
37 #else
38 #   include <avcodec.h>
39 #endif
40
41 /* vorbis header */
42 #ifdef HAVE_VORBIS_VORBISENC_H
43 #   include <vorbis/vorbisenc.h>
44 #   ifndef OV_ECTL_RATEMANAGE_AVG
45 #       define OV_ECTL_RATEMANAGE_AVG 0x0
46 #   endif
47 #endif
48
49 /*****************************************************************************
50  * Exported prototypes
51  *****************************************************************************/
52 static int      Open    ( vlc_object_t * );
53 static void     Close   ( vlc_object_t * );
54
55 static sout_stream_id_t *Add ( sout_stream_t *, sout_format_t * );
56 static int               Del ( sout_stream_t *, sout_stream_id_t * );
57 static int               Send( sout_stream_t *, sout_stream_id_t *, sout_buffer_t* );
58
59 static int  transcode_audio_ffmpeg_new    ( sout_stream_t *, sout_stream_id_t * );
60 static void transcode_audio_ffmpeg_close  ( sout_stream_t *, sout_stream_id_t * );
61 static int  transcode_audio_ffmpeg_process( sout_stream_t *, sout_stream_id_t *, sout_buffer_t *, sout_buffer_t ** );
62
63 static int  transcode_video_ffmpeg_new    ( sout_stream_t *, sout_stream_id_t * );
64 static void transcode_video_ffmpeg_close  ( sout_stream_t *, sout_stream_id_t * );
65 static int  transcode_video_ffmpeg_process( sout_stream_t *, sout_stream_id_t *, sout_buffer_t *, sout_buffer_t ** );
66
67 /*****************************************************************************
68  * Module descriptor
69  *****************************************************************************/
70 vlc_module_begin();
71     set_description( _("Transcode stream") );
72     set_capability( "sout stream", 50 );
73     add_shortcut( "transcode" );
74     set_callbacks( Open, Close );
75 vlc_module_end();
76
77 struct sout_stream_sys_t
78 {
79     sout_stream_t   *p_out;
80
81     vlc_fourcc_t    i_acodec;   /* codec audio (0 if not transcode) */
82     int             i_sample_rate;
83     int             i_channels;
84     int             i_abitrate;
85
86     vlc_fourcc_t    i_vcodec;   /*    "   video  " "   "      " */
87     int             i_vbitrate;
88     int             i_vtolerance;
89     int             i_width;
90     int             i_height;
91     int             i_key_int;
92     int             i_qmin;
93     int             i_qmax;
94     vlc_bool_t      b_hq;
95     vlc_bool_t      b_deinterlace;
96
97     int             i_crop_top;
98     int             i_crop_bottom;
99     int             i_crop_right;
100     int             i_crop_left;
101 };
102
103 /*****************************************************************************
104  * Open:
105  *****************************************************************************/
106 static int Open( vlc_object_t *p_this )
107 {
108     sout_stream_t     *p_stream = (sout_stream_t*)p_this;
109     sout_stream_sys_t *p_sys;
110     char *codec;
111
112     p_sys = malloc( sizeof( sout_stream_sys_t ) );
113     p_sys->p_out = sout_stream_new( p_stream->p_sout, p_stream->psz_next );
114
115     p_sys->i_acodec      = 0;
116     p_sys->i_sample_rate = 0;
117     p_sys->i_channels    = 0;
118     p_sys->i_abitrate    = 0;
119
120     p_sys->i_vcodec     = 0;
121     p_sys->i_vbitrate   = 0;
122     p_sys->i_vtolerance = -1;
123     p_sys->i_width      = 0;
124     p_sys->i_height     = 0;
125     p_sys->i_key_int    = -1;
126     p_sys->i_qmin       = 2;
127     p_sys->i_qmax       = 31;
128     p_sys->b_hq         = VLC_FALSE;
129     p_sys->b_deinterlace= VLC_FALSE;
130
131     p_sys->i_crop_top   = 0;
132     p_sys->i_crop_bottom= 0;
133     p_sys->i_crop_right = 0;
134     p_sys->i_crop_left  = 0;
135
136     if( ( codec = sout_cfg_find_value( p_stream->p_cfg, "acodec" ) ) )
137     {
138         char fcc[4] = "    ";
139         char *val;
140
141         memcpy( fcc, codec, strlen( codec ) );
142
143         p_sys->i_acodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
144
145         if( ( val = sout_cfg_find_value( p_stream->p_cfg, "samplerate" ) ) )
146         {
147             p_sys->i_sample_rate = atoi( val );
148         }
149         if( ( val = sout_cfg_find_value( p_stream->p_cfg, "channels" ) ) )
150         {
151             p_sys->i_channels = atoi( val );
152         }
153         if( ( val = sout_cfg_find_value( p_stream->p_cfg, "ab" ) ) )
154         {
155             p_sys->i_abitrate = atoi( val );
156             if( p_sys->i_abitrate < 4000 )
157             {
158                 p_sys->i_abitrate *= 1000;
159             }
160         }
161
162         msg_Dbg( p_stream, "codec audio=%4.4s %dHz %d channels %dKb/s", fcc,
163                  p_sys->i_sample_rate, p_sys->i_channels,
164                  p_sys->i_abitrate / 1024 );
165     }
166
167     if( ( codec = sout_cfg_find_value( p_stream->p_cfg, "vcodec" ) ) )
168     {
169         char fcc[4] = "    ";
170         char *val;
171
172         memcpy( fcc, codec, strlen( codec ) );
173
174         p_sys->i_vcodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
175
176         if( ( val = sout_cfg_find_value( p_stream->p_cfg, "width" ) ) )
177         {
178             p_sys->i_width = atoi( val );
179         }
180         if( ( val = sout_cfg_find_value( p_stream->p_cfg, "height" ) ) )
181         {
182             p_sys->i_height = atoi( val );
183         }
184         if( ( val = sout_cfg_find_value( p_stream->p_cfg, "vb" ) ) )
185         {
186             p_sys->i_vbitrate = atoi( val );
187             if( p_sys->i_vbitrate < 16000 )
188             {
189                 p_sys->i_vbitrate *= 1000;
190             }
191         }
192         if( ( val = sout_cfg_find_value( p_stream->p_cfg, "vt" ) ) )
193         {
194             p_sys->i_vtolerance = atoi( val );
195         }
196         if( sout_cfg_find( p_stream->p_cfg, "deinterlace" ) )
197         {
198             p_sys->b_deinterlace = VLC_TRUE;
199         }
200         /* crop */
201         if( ( val = sout_cfg_find_value( p_stream->p_cfg, "croptop" ) ) )
202         {
203             p_sys->i_crop_top = atoi( val );
204         }
205         if( ( val = sout_cfg_find_value( p_stream->p_cfg, "cropbottom" ) ) )
206         {
207             p_sys->i_crop_bottom = atoi( val );
208         }
209         if( ( val = sout_cfg_find_value( p_stream->p_cfg, "cropleft" ) ) )
210         {
211             p_sys->i_crop_left = atoi( val );
212         }
213         if( ( val = sout_cfg_find_value( p_stream->p_cfg, "cropright" ) ) )
214         {
215             p_sys->i_crop_right = atoi( val );
216         }
217         if( ( val = sout_cfg_find_value( p_stream->p_cfg, "keyint" ) ) )
218         {
219             p_sys->i_key_int    = atoi( val );
220         }
221         if( sout_cfg_find( p_stream->p_cfg, "hq" ) )
222         {
223             p_sys->b_hq = VLC_TRUE;
224         }
225         if( ( val = sout_cfg_find_value( p_stream->p_cfg, "qmin" ) ) )
226         {
227             p_sys->i_qmin   = atoi( val );
228         }
229         if( ( val = sout_cfg_find_value( p_stream->p_cfg, "qmax" ) ) )
230         {
231             p_sys->i_qmax   = atoi( val );
232         }
233
234         msg_Dbg( p_stream, "codec video=%4.4s %dx%d %dkb/s",
235                  fcc,
236                  p_sys->i_width, p_sys->i_height,
237                  p_sys->i_vbitrate / 1024 );
238     }
239
240     if( !p_sys->p_out )
241     {
242         msg_Err( p_stream, "cannot create chain" );
243         free( p_sys );
244         return VLC_EGENERIC;
245     }
246     p_stream->pf_add    = Add;
247     p_stream->pf_del    = Del;
248     p_stream->pf_send   = Send;
249
250     p_stream->p_sys     = p_sys;
251
252     avcodec_init();
253     avcodec_register_all();
254
255     return VLC_SUCCESS;
256 }
257
258 /*****************************************************************************
259  * Close:
260  *****************************************************************************/
261
262 static void Close( vlc_object_t * p_this )
263 {
264     sout_stream_t       *p_stream = (sout_stream_t*)p_this;
265     sout_stream_sys_t   *p_sys = p_stream->p_sys;
266
267     sout_stream_delete( p_sys->p_out );
268     free( p_sys );
269 }
270
271 struct sout_stream_id_t
272 {
273     vlc_fourcc_t  b_transcode;
274     sout_format_t f_src;        /* only if transcoding */
275     sout_format_t f_dst;        /*  "   "      " */
276
277     /* id of the out stream */
278     void *id;
279
280     /* ffmpeg part */
281     AVCodec         *ff_dec;
282     AVCodecContext  *ff_dec_c;
283
284
285     vlc_fourcc_t    b_enc_inited;
286     AVCodec         *ff_enc;
287     AVCodecContext  *ff_enc_c;
288
289     mtime_t         i_dts;
290     mtime_t         i_length;
291
292     int             i_buffer_in;
293     int             i_buffer_in_pos;
294     uint8_t         *p_buffer_in;
295
296     int             i_buffer;
297     int             i_buffer_pos;
298     uint8_t         *p_buffer;
299
300     int             i_buffer_out;
301     int             i_buffer_out_pos;
302     uint8_t         *p_buffer_out;
303
304     AVFrame         *p_ff_pic;
305     AVFrame         *p_ff_pic_tmp0; /* to do deinterlace */
306     AVFrame         *p_ff_pic_tmp1; /* to do pix conversion */
307     AVFrame         *p_ff_pic_tmp2; /* to do resample */
308
309     ImgReSampleContext *p_vresample;
310
311 #ifdef HAVE_VORBIS_VORBISENC_H
312
313     /* Vorbis part */
314     vorbis_info      *p_vi;
315     vorbis_dsp_state *p_vd;
316     vorbis_block     *p_vb;
317     vorbis_comment   *p_vc;
318     int              i_last_block_size;
319     int              i_samples_delay;
320     vlc_bool_t       b_headers_sent;
321 #endif
322 };
323
324
325 static sout_stream_id_t * Add( sout_stream_t *p_stream, sout_format_t *p_fmt )
326 {
327     sout_stream_sys_t   *p_sys = p_stream->p_sys;
328     sout_stream_id_t    *id;
329
330     id = malloc( sizeof( sout_stream_id_t ) );
331     id->i_dts = 0;
332     id->id = NULL;
333     if( p_fmt->i_cat == AUDIO_ES && p_sys->i_acodec != 0 )
334     {
335         msg_Dbg( p_stream,
336                  "creating audio transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
337                  (char*)&p_fmt->i_fourcc,
338                  (char*)&p_sys->i_acodec );
339
340         /* src format */
341         memcpy( &id->f_src, p_fmt, sizeof( sout_format_t ) );
342
343         /* create dst format */
344         id->f_dst.i_cat    = AUDIO_ES;
345         id->f_dst.i_fourcc = p_sys->i_acodec;
346         id->f_dst.i_sample_rate = p_sys->i_sample_rate  > 0 ? p_sys->i_sample_rate : id->f_src.i_sample_rate;
347         id->f_dst.i_channels    = p_sys->i_channels > 0 ? p_sys->i_channels : id->f_src.i_channels;
348         id->f_dst.i_bitrate     = p_sys->i_abitrate > 0 ? p_sys->i_abitrate : 64000;
349         id->f_dst.i_block_align = 0;
350         id->f_dst.i_extra_data  = 0;
351         id->f_dst.p_extra_data  = NULL;
352
353         /* build decoder -> filter -> encoder */
354         if( transcode_audio_ffmpeg_new( p_stream, id ) )
355         {
356             msg_Err( p_stream, "cannot create audio chain" );
357             free( id );
358             return NULL;
359         }
360
361         /* open output stream */
362         id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->f_dst );
363         id->b_transcode = VLC_TRUE;
364
365         if( id->id == NULL )
366         {
367             free( id );
368             return NULL;
369         }
370     }
371     else if( p_fmt->i_cat == VIDEO_ES && p_sys->i_vcodec != 0 )
372     {
373         msg_Dbg( p_stream,
374                  "creating video transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
375                  (char*)&p_fmt->i_fourcc,
376                  (char*)&p_sys->i_vcodec );
377
378         memcpy( &id->f_src, p_fmt, sizeof( sout_format_t ) );
379
380         /* create dst format */
381         id->f_dst.i_cat         = VIDEO_ES;
382         id->f_dst.i_fourcc      = p_sys->i_vcodec;
383         id->f_dst.i_width       = p_sys->i_width ; /* > 0 ? p_sys->i_width : id->f_src.i_width; */
384         id->f_dst.i_height      = p_sys->i_height; /* > 0 ? p_sys->i_height: id->f_src.i_height; */
385         id->f_dst.i_bitrate     = p_sys->i_vbitrate > 0 ? p_sys->i_vbitrate : 800*1000;
386         id->f_dst.i_extra_data  = 0;
387         id->f_dst.p_extra_data  = NULL;
388
389         /* build decoder -> filter -> encoder */
390         if( transcode_video_ffmpeg_new( p_stream, id ) )
391         {
392             msg_Err( p_stream, "cannot create video chain" );
393             free( id );
394             return NULL;
395         }
396 #if 0
397         /* open output stream */
398         id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->f_dst );
399 #endif
400         id->b_transcode = VLC_TRUE;
401     }
402     else
403     {
404         msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')", (char*)&p_fmt->i_fourcc );
405         id->id = p_sys->p_out->pf_add( p_sys->p_out, p_fmt );
406         id->b_transcode = VLC_FALSE;
407
408         if( id->id == NULL )
409         {
410             free( id );
411             return NULL;
412         }
413     }
414
415     return id;
416 }
417
418 static int     Del      ( sout_stream_t *p_stream, sout_stream_id_t *id )
419 {
420     sout_stream_sys_t   *p_sys = p_stream->p_sys;
421
422     if( id->b_transcode )
423     {
424         if( id->f_src.i_cat == AUDIO_ES )
425         {
426             transcode_audio_ffmpeg_close( p_stream, id );
427         }
428         else if( id->f_src.i_cat == VIDEO_ES )
429         {
430             transcode_video_ffmpeg_close( p_stream, id );
431         }
432     }
433
434     if( id->id ) p_sys->p_out->pf_del( p_sys->p_out, id->id );
435     free( id );
436
437     return VLC_SUCCESS;
438 }
439
440 static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
441                  sout_buffer_t *p_buffer )
442 {
443     sout_stream_sys_t   *p_sys = p_stream->p_sys;
444
445     if( id->b_transcode )
446     {
447         sout_buffer_t *p_buffer_out;
448         if( id->f_src.i_cat == AUDIO_ES )
449         {
450             transcode_audio_ffmpeg_process( p_stream, id, p_buffer, &p_buffer_out );
451         }
452         else if( id->f_src.i_cat == VIDEO_ES )
453         {
454             transcode_video_ffmpeg_process( p_stream, id, p_buffer, &p_buffer_out );
455         }
456         sout_BufferDelete( p_stream->p_sout, p_buffer );
457
458         if( p_buffer_out )
459         {
460             return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_buffer_out );
461         }
462         return VLC_SUCCESS;
463     }
464     else if( id->id != NULL )
465     {
466         return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_buffer );
467     }
468     else
469     {
470         sout_BufferDelete( p_stream->p_sout, p_buffer );
471         return VLC_EGENERIC;
472     }
473 }
474
475 /****************************************************************************
476  * ffmpeg decoder reencocdr part
477  ****************************************************************************/
478
479 static struct
480 {
481     vlc_fourcc_t i_fcc;
482     int          i_ff_codec;
483 } fourcc_to_ff_code[] =
484 {
485     /* audio */
486     { VLC_FOURCC( 'm', 'p', 'g', 'a' ), CODEC_ID_MP2 },
487     { VLC_FOURCC( 'm', 'p', '3', ' ' ), CODEC_ID_MP3LAME },
488     { VLC_FOURCC( 'a', '5', '2', ' ' ), CODEC_ID_AC3 },
489     { VLC_FOURCC( 'a', 'c', '3', ' ' ), CODEC_ID_AC3 },
490     { VLC_FOURCC( 'w', 'm', 'a', '1' ), CODEC_ID_WMAV1 },
491     { VLC_FOURCC( 'w', 'm', 'a', '2' ), CODEC_ID_WMAV2 },
492     { VLC_FOURCC( 'v', 'o', 'r', 'b' ), CODEC_ID_VORBIS },
493     { VLC_FOURCC( 'a', 'l', 'a', 'w' ), CODEC_ID_PCM_ALAW },
494
495     /* video */
496     { VLC_FOURCC( 'm', 'p', '4', 'v'),  CODEC_ID_MPEG4 },
497     { VLC_FOURCC( 'm', 'p', 'g', 'v' ), CODEC_ID_MPEG1VIDEO },
498     { VLC_FOURCC( 'D', 'I', 'V', '1' ), CODEC_ID_MSMPEG4V1 },
499     { VLC_FOURCC( 'D', 'I', 'V', '2' ), CODEC_ID_MSMPEG4V2 },
500     { VLC_FOURCC( 'D', 'I', 'V', '3' ), CODEC_ID_MSMPEG4V3 },
501     { VLC_FOURCC( 'H', '2', '6', '3' ), CODEC_ID_H263 },
502     { VLC_FOURCC( 'I', '2', '6', '3' ), CODEC_ID_H263I },
503     { VLC_FOURCC( 'h', 'u', 'f', 'f' ), CODEC_ID_HUFFYUV },
504     { VLC_FOURCC( 'W', 'M', 'V', '1' ), CODEC_ID_WMV1 },
505     { VLC_FOURCC( 'W', 'M', 'V', '2' ), CODEC_ID_WMV2 },
506     { VLC_FOURCC( 'M', 'J', 'P', 'G' ), CODEC_ID_MJPEG },
507     { VLC_FOURCC( 'm', 'j', 'p', 'b' ), CODEC_ID_MJPEGB },
508     { VLC_FOURCC( 'd', 'v', 's', 'l' ), CODEC_ID_DVVIDEO },
509     { VLC_FOURCC( 'S', 'V', 'Q', '1' ), CODEC_ID_SVQ1 },
510 #if LIBAVCODEC_BUILD >= 4666
511     { VLC_FOURCC( 'S', 'V', 'Q', '3' ), CODEC_ID_SVQ3 },
512 #endif
513
514     /* raw video code, only used for 'encoding' */
515     { VLC_FOURCC( 'I', '4', '2', '0' ), CODEC_ID_RAWVIDEO },
516     { VLC_FOURCC( 'I', '4', '2', '2' ), CODEC_ID_RAWVIDEO },
517     { VLC_FOURCC( 'I', '4', '4', '4' ), CODEC_ID_RAWVIDEO },
518     { VLC_FOURCC( 'R', 'V', '1', '5' ), CODEC_ID_RAWVIDEO },
519     { VLC_FOURCC( 'R', 'V', '1', '6' ), CODEC_ID_RAWVIDEO },
520     { VLC_FOURCC( 'R', 'V', '2', '4' ), CODEC_ID_RAWVIDEO },
521     { VLC_FOURCC( 'R', 'V', '3', '2' ), CODEC_ID_RAWVIDEO },
522     { VLC_FOURCC( 'Y', 'U', 'Y', '2' ), CODEC_ID_RAWVIDEO },
523
524     { VLC_FOURCC(   0,   0,   0,   0 ), 0 }
525 };
526
527 static inline int get_ff_codec( vlc_fourcc_t i_fcc )
528 {
529     int i;
530
531     for( i = 0; fourcc_to_ff_code[i].i_fcc != 0; i++ )
532     {
533         if( fourcc_to_ff_code[i].i_fcc == i_fcc )
534         {
535             return fourcc_to_ff_code[i].i_ff_codec;
536         }
537     }
538
539     return 0;
540 }
541
542 static inline int get_ff_chroma( vlc_fourcc_t i_chroma )
543 {
544     switch( i_chroma )
545     {
546         case VLC_FOURCC( 'I', '4', '2', '0' ):
547             return PIX_FMT_YUV420P;
548         case VLC_FOURCC( 'I', '4', '2', '2' ):
549             return PIX_FMT_YUV422P;
550         case VLC_FOURCC( 'I', '4', '4', '4' ):
551             return PIX_FMT_YUV444P;
552         case VLC_FOURCC( 'R', 'V', '1', '5' ):
553             return PIX_FMT_RGB555;
554         case VLC_FOURCC( 'R', 'V', '1', '6' ):
555             return PIX_FMT_RGB565;
556         case VLC_FOURCC( 'R', 'V', '2', '4' ):
557             return PIX_FMT_RGB24;
558         case VLC_FOURCC( 'R', 'V', '3', '2' ):
559             return PIX_FMT_RGBA32;
560         case VLC_FOURCC( 'G', 'R', 'E', 'Y' ):
561             return PIX_FMT_GRAY8;
562         case VLC_FOURCC( 'Y', 'U', 'Y', '2' ):
563             return PIX_FMT_YUV422;
564         default:
565             return 0;
566     }
567 }
568
569 static int transcode_audio_ffmpeg_new( sout_stream_t *p_stream,
570                                        sout_stream_id_t *id )
571 {
572     int i_ff_codec;
573
574     if( id->f_src.i_fourcc == VLC_FOURCC('s','1','6','l') ||
575         id->f_src.i_fourcc == VLC_FOURCC('s','1','6','b') ||
576         id->f_src.i_fourcc == VLC_FOURCC('s','8',' ',' ') ||
577         id->f_src.i_fourcc == VLC_FOURCC('u','8',' ',' ') )
578     {
579         id->ff_dec = NULL;
580
581         id->ff_dec_c = avcodec_alloc_context();
582         id->ff_dec_c->sample_rate = id->f_src.i_sample_rate;
583         id->ff_dec_c->channels    = id->f_src.i_channels;
584         id->ff_dec_c->block_align = id->f_src.i_block_align;
585         id->ff_dec_c->bit_rate    = id->f_src.i_bitrate;
586     }
587     else
588     {
589         /* find decoder */
590         i_ff_codec = get_ff_codec( id->f_src.i_fourcc );
591         if( i_ff_codec == 0 )
592         {
593             msg_Err( p_stream, "cannot find decoder" );
594             return VLC_EGENERIC;
595         }
596
597         id->ff_dec = avcodec_find_decoder( i_ff_codec );
598         if( !id->ff_dec )
599         {
600             msg_Err( p_stream, "cannot find decoder" );
601             return VLC_EGENERIC;
602         }
603
604         id->ff_dec_c = avcodec_alloc_context();
605         id->ff_dec_c->sample_rate = id->f_src.i_sample_rate;
606         id->ff_dec_c->channels    = id->f_src.i_channels;
607         id->ff_dec_c->block_align = id->f_src.i_block_align;
608         id->ff_dec_c->bit_rate    = id->f_src.i_bitrate;
609
610         id->ff_dec_c->extradata_size = id->f_src.i_extra_data;
611         id->ff_dec_c->extradata      = id->f_src.p_extra_data;
612         if( avcodec_open( id->ff_dec_c, id->ff_dec ) )
613         {
614             msg_Err( p_stream, "cannot open decoder" );
615             return VLC_EGENERIC;
616         }
617     }
618
619     /* find encoder */
620     id->i_buffer_in      = 2 * AVCODEC_MAX_AUDIO_FRAME_SIZE;
621     id->i_buffer_in_pos = 0;
622     id->p_buffer_in      = malloc( id->i_buffer_in );
623
624     id->i_buffer     = 2 * AVCODEC_MAX_AUDIO_FRAME_SIZE;
625     id->i_buffer_pos = 0;
626     id->p_buffer     = malloc( id->i_buffer );
627
628     id->i_buffer_out     = 2 * AVCODEC_MAX_AUDIO_FRAME_SIZE;
629     id->i_buffer_out_pos = 0;
630     id->p_buffer_out     = malloc( id->i_buffer_out );
631
632     /* Sanity check for audio channels */
633     id->f_dst.i_channels = __MIN( id->f_dst.i_channels, id->f_src.i_channels );
634
635 #ifdef HAVE_VORBIS_VORBISENC_H
636     if( id->f_dst.i_fourcc == VLC_FOURCC('v','o','r','b') )
637     {
638         id->p_vi = (vorbis_info *)malloc( sizeof(vorbis_info) );
639         id->p_vd = (vorbis_dsp_state *)malloc( sizeof(vorbis_dsp_state) );
640         id->p_vb = (vorbis_block *)malloc( sizeof(vorbis_block) );
641         id->p_vc = (vorbis_comment *)malloc( sizeof(vorbis_comment) );
642
643         vorbis_info_init( id->p_vi );
644
645         if( vorbis_encode_setup_managed( id->p_vi, id->f_dst.i_channels,
646               id->f_dst.i_sample_rate, -1, id->f_dst.i_bitrate, -1 ) ||
647             vorbis_encode_ctl( id->p_vi, OV_ECTL_RATEMANAGE_AVG, NULL ) ||
648              vorbis_encode_setup_init( id->p_vi ) ){}
649
650         /* add a comment */
651         vorbis_comment_init( id->p_vc);
652         vorbis_comment_add_tag( id->p_vc, "ENCODER", "VLC media player");
653
654         /* set up the analysis state and auxiliary encoding storage */
655         vorbis_analysis_init( id->p_vd, id->p_vi );
656         vorbis_block_init( id->p_vd, id->p_vb );
657
658         id->b_headers_sent = VLC_FALSE;
659         id->i_last_block_size = 0;
660         id->i_samples_delay = 0;
661
662         return VLC_SUCCESS;
663     }
664 #endif
665
666     i_ff_codec = get_ff_codec( id->f_dst.i_fourcc );
667     if( i_ff_codec == 0 )
668     {
669         msg_Err( p_stream, "cannot find encoder" );
670         return VLC_EGENERIC;
671     }
672
673     id->ff_enc = avcodec_find_encoder( i_ff_codec );
674     if( !id->ff_enc )
675     {
676         msg_Err( p_stream, "cannot find encoder" );
677         return VLC_EGENERIC;
678     }
679
680     /* Hack for mp3 transcoding support */
681     if( id->f_dst.i_fourcc == VLC_FOURCC( 'm','p','3',' ' ) )
682         id->f_dst.i_fourcc = VLC_FOURCC( 'm','p','g','a' );
683
684     id->ff_enc_c = avcodec_alloc_context();
685     id->ff_enc_c->bit_rate    = id->f_dst.i_bitrate;
686     id->ff_enc_c->sample_rate = id->f_dst.i_sample_rate;
687     id->ff_enc_c->channels    = id->f_dst.i_channels;
688
689     if( avcodec_open( id->ff_enc_c, id->ff_enc ) )
690     {
691         msg_Err( p_stream, "cannot open encoder" );
692         return VLC_EGENERIC;
693     }
694
695     return VLC_SUCCESS;
696 }
697
698 static void transcode_audio_ffmpeg_close( sout_stream_t *p_stream,
699                                           sout_stream_id_t *id )
700 {
701     if( id->ff_dec )
702     {
703         avcodec_close( id->ff_dec_c );
704     }
705
706 #ifdef HAVE_VORBIS_VORBISENC_H
707     if( id->f_dst.i_fourcc == VLC_FOURCC('v','o','r','b') )
708     {
709         vorbis_block_clear( id->p_vb );
710         vorbis_dsp_clear( id->p_vd );
711         vorbis_comment_clear( id->p_vc );
712         vorbis_info_clear( id->p_vi );  /* must be called last */
713
714         free( id->p_vi );
715         free( id->p_vd );
716         free( id->p_vb );
717         free( id->p_vc );
718     }
719     else
720 #endif
721         avcodec_close( id->ff_enc_c );
722
723     free( id->ff_dec_c );
724     if( id->f_dst.i_fourcc != VLC_FOURCC('v','o','r','b') )
725         free( id->ff_enc_c );
726
727     free( id->p_buffer_in );
728     free( id->p_buffer );
729     free( id->p_buffer_out );
730 }
731
732 static int transcode_audio_ffmpeg_process( sout_stream_t *p_stream,
733                                            sout_stream_id_t *id,
734                                            sout_buffer_t *in,
735                                            sout_buffer_t **out )
736 {
737     vlc_bool_t b_again = VLC_FALSE;
738
739     *out = NULL;
740
741     /* gather data into p_buffer_in */
742 #ifdef HAVE_VORBIS_VORBISENC_H
743     if( id->f_dst.i_fourcc == VLC_FOURCC( 'v', 'o', 'r', 'b' ) )
744     id->i_dts = in->i_dts -
745                 (mtime_t)1000000 * (mtime_t)id->i_samples_delay /
746                 (mtime_t)id->f_dst.i_sample_rate;
747     else
748 #endif
749     id->i_dts = in->i_dts -
750                 (mtime_t)1000000 *
751                 (mtime_t)(id->i_buffer_pos / 2 / id->ff_dec_c->channels )/
752                 (mtime_t)id->ff_dec_c->sample_rate;
753
754     if( id->i_buffer_in_pos + (int)in->i_size > id->i_buffer_in )
755     {
756         /* extend buffer_in */
757         id->i_buffer_in = id->i_buffer_in_pos + in->i_size + 1024;
758         id->p_buffer_in = realloc( id->p_buffer_in, id->i_buffer_in );
759     }
760     memcpy( &id->p_buffer_in[id->i_buffer_in_pos],
761             in->p_buffer, in->i_size );
762     id->i_buffer_in_pos += in->i_size;
763
764     do
765     {
766         int i_buffer_pos;
767
768         /* decode as much data as possible */
769         if( id->ff_dec )
770         {
771             for( ;; )
772             {
773                 int i_buffer_size;
774                 int i_used;
775
776                 i_buffer_size = id->i_buffer - id->i_buffer_pos;
777
778                 i_used = avcodec_decode_audio( id->ff_dec_c,
779                          (int16_t*)&id->p_buffer[id->i_buffer_pos],
780                          &i_buffer_size, id->p_buffer_in,
781                          id->i_buffer_in_pos );
782
783                 /* msg_Warn( p_stream, "avcodec_decode_audio: %d used",
784                              i_used ); */
785                 id->i_buffer_pos += i_buffer_size;
786
787                 if( i_used < 0 )
788                 {
789                     msg_Warn( p_stream, "error");
790                     id->i_buffer_in_pos = 0;
791                     break;
792                 }
793                 else if( i_used < id->i_buffer_in_pos )
794                 {
795                     memmove( id->p_buffer_in,
796                              &id->p_buffer_in[i_used],
797                              id->i_buffer_in - i_used );
798                     id->i_buffer_in_pos -= i_used;
799                 }
800                 else
801                 {
802                     id->i_buffer_in_pos = 0;
803                     break;
804                 }
805
806                 if( id->i_buffer_pos >= AVCODEC_MAX_AUDIO_FRAME_SIZE )
807                 {
808                     /* buffer full */
809                     b_again = VLC_TRUE;
810                     break;
811                 }
812             }
813         }
814         else
815         {
816             int16_t *sout  = (int16_t*)&id->p_buffer[id->i_buffer_pos];
817             int     i_used = 0;
818
819             if( id->f_src.i_fourcc == VLC_FOURCC( 's', '8', ' ', ' ' ) )
820             {
821                 int8_t *sin = (int8_t*)id->p_buffer_in;
822                 int     i_samples = __MIN( ( id->i_buffer - id->i_buffer_pos )
823                                            / 2, id->i_buffer_in_pos );
824                 i_used = i_samples;
825                 while( i_samples > 0 )
826                 {
827                     *sout++ = ( *sin++ ) << 8;
828                     i_samples--;
829                 }
830             }
831             else if( id->f_src.i_fourcc == VLC_FOURCC( 'u', '8', ' ', ' ' ) )
832             {
833                 int8_t *sin = (int8_t*)id->p_buffer_in;
834                 int     i_samples = __MIN( ( id->i_buffer - id->i_buffer_pos )
835                                            / 2, id->i_buffer_in_pos );
836                 i_used = i_samples;
837                 while( i_samples > 0 )
838                 {
839                     *sout++ = ( *sin++ - 128 ) << 8;
840                     i_samples--;
841                 }
842             }
843             else if( id->f_src.i_fourcc == VLC_FOURCC( 's', '1', '6', 'l' ) )
844             {
845                 int     i_samples = __MIN( ( id->i_buffer - id->i_buffer_pos )
846                                            / 2, id->i_buffer_in_pos / 2);
847 #ifdef WORDS_BIGENDIAN
848                 uint8_t *sin = (uint8_t*)id->p_buffer_in;
849                 i_used = i_samples * 2;
850                 while( i_samples > 0 )
851                 {
852                     uint8_t tmp[2];
853
854                     tmp[1] = *sin++;
855                     tmp[0] = *sin++;
856                     *sout++ = *(int16_t*)tmp;
857                     i_samples--;
858                 }
859
860 #else
861                 memcpy( sout, id->p_buffer_in, i_samples * 2 );
862                 sout += i_samples;
863                 i_used = i_samples * 2;
864 #endif
865             }
866             else if( id->f_src.i_fourcc == VLC_FOURCC( 's', '1', '6', 'b' ) )
867             {
868                 int     i_samples = __MIN( ( id->i_buffer - id->i_buffer_pos )
869                                            / 2, id->i_buffer_in_pos / 2);
870 #ifdef WORDS_BIGENDIAN
871                 memcpy( sout, id->p_buffer_in, i_samples * 2 );
872                 sout += i_samples;
873                 i_used = i_samples * 2;
874 #else
875                 uint8_t *sin = (uint8_t*)id->p_buffer_in;
876                 i_used = i_samples * 2;
877                 while( i_samples > 0 )
878                 {
879                     uint8_t tmp[2];
880
881                     tmp[1] = *sin++;
882                     tmp[0] = *sin++;
883                     *sout++ = *(int16_t*)tmp;
884                     i_samples--;
885                 }
886 #endif
887             }
888
889             id->i_buffer_pos = (uint8_t*)sout - id->p_buffer;
890             if( i_used < id->i_buffer_in_pos )
891             {
892                 memmove( id->p_buffer_in,
893                          &id->p_buffer_in[i_used],
894                          id->i_buffer_in - i_used );
895             }
896             id->i_buffer_in_pos -= i_used;
897         }
898
899         i_buffer_pos = id->i_buffer_pos;
900
901         /* encode as much data as possible */
902
903 #ifdef HAVE_VORBIS_VORBISENC_H
904         if( id->i_buffer_pos == 0 );
905         else if( id->f_dst.i_fourcc == VLC_FOURCC( 'v', 'o', 'r', 'b' ) )
906         {
907             float **buffer;
908             int i, j, i_samples;
909             sout_buffer_t *p_out;
910             ogg_packet op;
911
912             if( !id->b_headers_sent )
913             {
914                 ogg_packet header[3];
915                 vorbis_analysis_headerout( id->p_vd, id->p_vc,
916                                            &header[0], &header[1], &header[2]);
917                 for( i = 0; i < 3; i++ )
918                 {
919                     p_out = sout_BufferNew( p_stream->p_sout, header[i].bytes);
920                     memcpy( p_out->p_buffer, header[i].packet,
921                             header[i].bytes );
922
923                     p_out->i_size = header[i].bytes;
924                     p_out->i_length = 0;
925
926                     p_out->i_dts = p_out->i_pts = 0;
927
928                     sout_BufferChain( out, p_out );
929                 }
930                 id->b_headers_sent = VLC_TRUE;
931             }
932
933             i_samples = id->i_buffer_pos / id->f_src.i_channels / 2;
934             id->i_samples_delay += i_samples;
935             id->i_buffer_pos = 0;
936
937             buffer = vorbis_analysis_buffer( id->p_vd, i_samples );
938
939             /* convert samples to float and uninterleave */
940             for( i = 0; i < id->f_dst.i_channels; i++ )
941             {
942                 for( j = 0 ; j < i_samples ; j++ )
943                 {
944                     buffer[i][j]= ((float)( ((int16_t *)id->p_buffer)
945                                   [j*id->f_src.i_channels + i ] ))/ 32768.f;
946                 }
947             }
948
949             vorbis_analysis_wrote( id->p_vd, i_samples );
950
951             while( vorbis_analysis_blockout( id->p_vd, id->p_vb ) == 1 )
952             {
953                 vorbis_analysis( id->p_vb, NULL );
954                 vorbis_bitrate_addblock( id->p_vb );
955
956                 while( vorbis_bitrate_flushpacket( id->p_vd, &op ) )
957                 {
958                     int i_block_size;
959                     p_out = sout_BufferNew( p_stream->p_sout, op.bytes );
960                     memcpy( p_out->p_buffer, op.packet, op.bytes );
961
962                     i_block_size = vorbis_packet_blocksize( id->p_vi, &op );
963
964                     if( i_block_size < 0 ) i_block_size = 0;
965                     i_samples = ( id->i_last_block_size +
966                                   i_block_size ) >> 2;
967                     id->i_last_block_size = i_block_size;
968
969                     p_out->i_size = op.bytes;
970                     p_out->i_length = (mtime_t)1000000 *
971                       (mtime_t)i_samples /
972                       (mtime_t)id->f_dst.i_sample_rate;
973
974                     //msg_Err( p_stream, "i_dts: %lld", id->i_dts );
975
976                     /* FIXME */
977                     p_out->i_dts = id->i_dts;
978                     p_out->i_pts = id->i_dts;
979
980                     id->i_samples_delay -= i_samples;
981
982                     /* update dts */
983                     id->i_dts += p_out->i_length;
984                     sout_BufferChain( out, p_out );
985
986                 }
987             }
988         }
989         else
990 #endif
991
992         for( ;; )
993         {
994             int i_frame_size = id->ff_enc_c->frame_size * 2 *
995                                  id->ff_dec_c->channels;
996             int i_out_size, i, j;
997             sout_buffer_t *p_out;
998             int16_t *p_buffer = (int16_t *)(id->p_buffer + i_buffer_pos -
999                                             id->i_buffer_pos);
1000
1001             if( id->i_buffer_pos < i_frame_size )
1002             {
1003                 break;
1004             }
1005
1006             if( id->ff_dec_c->channels != id->ff_enc_c->channels )
1007             {
1008                 /* dumb downmixing */
1009                 for( i = 0; i < id->ff_enc_c->frame_size; i++ )
1010                 {
1011                     for( j = 0 ; j < id->f_dst.i_channels; j++ )
1012                     {
1013                         p_buffer[i*id->f_dst.i_channels+j] =
1014                             p_buffer[i*id->f_src.i_channels+j];
1015                     }
1016                 }
1017             }
1018
1019             /* msg_Warn( p_stream, "avcodec_encode_audio: frame size%d",
1020                          i_frame_size); */
1021             i_out_size = avcodec_encode_audio( id->ff_enc_c,
1022                            id->p_buffer_out, id->i_buffer_out, p_buffer );
1023
1024             if( i_out_size <= 0 )
1025             {
1026                 break;
1027             }
1028
1029             id->i_buffer_pos -= i_frame_size;
1030
1031             p_out = sout_BufferNew( p_stream->p_sout, i_out_size );
1032             memcpy( p_out->p_buffer, id->p_buffer_out, i_out_size );
1033             p_out->i_size = i_out_size;
1034             p_out->i_length = (mtime_t)1000000 *
1035                               (mtime_t)id->ff_enc_c->frame_size /
1036                               (mtime_t)id->ff_enc_c->sample_rate;
1037
1038             /* FIXME */
1039             p_out->i_dts = id->i_dts;
1040             p_out->i_pts = id->i_dts;
1041
1042             /* update dts */
1043             id->i_dts += p_out->i_length;
1044
1045            /* msg_Warn( p_stream, "frame dts=%lld len %lld out=%d",
1046                         p_out->i_dts, p_out->i_length, i_out_size ); */
1047
1048             sout_BufferChain( out, p_out );
1049         }
1050
1051         /* Copy the remaining raw samples */
1052         if( id->i_buffer_pos != 0 )
1053         {
1054             memmove( id->p_buffer,
1055                      &id->p_buffer[i_buffer_pos - id->i_buffer_pos],
1056                      id->i_buffer_pos );
1057         }
1058
1059     } while( b_again );
1060
1061     return VLC_SUCCESS;
1062 }
1063
1064
1065 /*
1066  * video
1067  */
1068 static int transcode_video_ffmpeg_new( sout_stream_t *p_stream,
1069                                        sout_stream_id_t *id )
1070 {
1071     sout_stream_sys_t   *p_sys = p_stream->p_sys;
1072
1073     int i_ff_codec;
1074
1075     if( id->f_src.i_fourcc == VLC_FOURCC( 'I', '4', '2', '0' ) ||
1076         id->f_src.i_fourcc == VLC_FOURCC( 'I', '4', '2', '2' ) ||
1077         id->f_src.i_fourcc == VLC_FOURCC( 'I', '4', '4', '4' ) ||
1078         id->f_src.i_fourcc == VLC_FOURCC( 'Y', 'U', 'Y', '2' ) ||
1079         id->f_src.i_fourcc == VLC_FOURCC( 'R', 'V', '1', '5' ) ||
1080         id->f_src.i_fourcc == VLC_FOURCC( 'R', 'V', '1', '6' ) ||
1081         id->f_src.i_fourcc == VLC_FOURCC( 'R', 'V', '2', '4' ) ||
1082         id->f_src.i_fourcc == VLC_FOURCC( 'R', 'V', '3', '2' ) ||
1083         id->f_src.i_fourcc == VLC_FOURCC( 'G', 'R', 'E', 'Y' ) )
1084     {
1085         id->ff_dec   = NULL;
1086         id->ff_dec_c            = avcodec_alloc_context();
1087         id->ff_dec_c->width     = id->f_src.i_width;
1088         id->ff_dec_c->height    = id->f_src.i_height;
1089         id->ff_dec_c->pix_fmt   = get_ff_chroma( id->f_src.i_fourcc );
1090     }
1091     else
1092     {
1093         /* find decoder */
1094         i_ff_codec = get_ff_codec( id->f_src.i_fourcc );
1095         if( i_ff_codec == 0 )
1096         {
1097             msg_Err( p_stream, "cannot find decoder" );
1098             return VLC_EGENERIC;
1099         }
1100
1101         id->ff_dec = avcodec_find_decoder( i_ff_codec );
1102         if( !id->ff_dec )
1103         {
1104             msg_Err( p_stream, "cannot find decoder" );
1105             return VLC_EGENERIC;
1106         }
1107
1108         id->ff_dec_c = avcodec_alloc_context();
1109         id->ff_dec_c->width         = id->f_src.i_width;
1110         id->ff_dec_c->height        = id->f_src.i_height;
1111         /* id->ff_dec_c->bit_rate      = id->f_src.i_bitrate; */
1112         id->ff_dec_c->extradata_size= id->f_src.i_extra_data;
1113         id->ff_dec_c->extradata     = id->f_src.p_extra_data;
1114         id->ff_dec_c->workaround_bugs = FF_BUG_AUTODETECT;
1115         id->ff_dec_c->error_resilience= -1;
1116         if( id->ff_dec->capabilities & CODEC_CAP_TRUNCATED )
1117         {
1118             id->ff_dec_c->flags |= CODEC_FLAG_TRUNCATED;
1119         }
1120
1121         if( avcodec_open( id->ff_dec_c, id->ff_dec ) < 0 )
1122         {
1123             msg_Err( p_stream, "cannot open decoder" );
1124             return VLC_EGENERIC;
1125         }
1126
1127         if( i_ff_codec == CODEC_ID_MPEG4 && id->ff_dec_c->extradata_size > 0 )
1128         {
1129             int b_gotpicture;
1130             AVFrame frame;
1131
1132             avcodec_decode_video( id->ff_dec_c, &frame,
1133                                   &b_gotpicture,
1134                                   id->ff_dec_c->extradata, id->ff_dec_c->extradata_size );
1135         }
1136     }
1137
1138
1139     /* find encoder */
1140     i_ff_codec = get_ff_codec( id->f_dst.i_fourcc );
1141     if( i_ff_codec == 0 )
1142     {
1143         msg_Err( p_stream, "cannot find encoder" );
1144         return VLC_EGENERIC;
1145     }
1146
1147     id->ff_enc = avcodec_find_encoder( i_ff_codec );
1148     if( !id->ff_enc )
1149     {
1150         msg_Err( p_stream, "cannot find encoder" );
1151         return VLC_EGENERIC;
1152     }
1153
1154     id->ff_enc_c = avcodec_alloc_context();
1155     id->ff_enc_c->width          = id->f_dst.i_width;
1156     id->ff_enc_c->height         = id->f_dst.i_height;
1157     id->ff_enc_c->bit_rate       = id->f_dst.i_bitrate;
1158 #if LIBAVCODEC_BUILD >= 4662
1159     id->ff_enc_c->frame_rate     = 25 ; /* FIXME as it break mpeg */
1160     id->ff_enc_c->frame_rate_base= 1;
1161 #else
1162     id->ff_enc_c->frame_rate     = 25 * FRAME_RATE_BASE;
1163 #endif
1164     id->ff_enc_c->gop_size       = p_sys->i_key_int >= 0 ? p_sys->i_key_int : 50;
1165
1166     if( p_sys->i_vtolerance >= 0 )
1167     {
1168         id->ff_enc_c->bit_rate_tolerance = p_sys->i_vtolerance;
1169     }
1170     id->ff_enc_c->qmin           = p_sys->i_qmin;
1171     id->ff_enc_c->qmax           = p_sys->i_qmax;
1172     if( p_sys->b_hq )
1173     {
1174         id->ff_enc_c->flags      |= CODEC_FLAG_HQ;
1175     }
1176
1177     if( i_ff_codec == CODEC_ID_RAWVIDEO )
1178     {
1179         id->ff_enc_c->pix_fmt = get_ff_chroma( id->f_dst.i_fourcc );
1180     }
1181     /* XXX open it only when we have the first frame */
1182     id->b_enc_inited     = VLC_FALSE;
1183     id->i_buffer_in      = 0;
1184     id->i_buffer_in_pos  = 0;
1185     id->p_buffer_in      = NULL;
1186
1187     id->i_buffer     = 3*1024*1024;
1188     id->i_buffer_pos = 0;
1189     id->p_buffer     = malloc( id->i_buffer );
1190
1191     id->i_buffer_out     = 0;
1192     id->i_buffer_out_pos = 0;
1193     id->p_buffer_out     = NULL;
1194
1195     id->p_ff_pic         = avcodec_alloc_frame();
1196     id->p_ff_pic_tmp0    = NULL;
1197     id->p_ff_pic_tmp1    = NULL;
1198     id->p_ff_pic_tmp2    = NULL;
1199     id->p_vresample      = NULL;
1200     return VLC_SUCCESS;
1201 }
1202
1203 static void transcode_video_ffmpeg_close ( sout_stream_t *p_stream, sout_stream_id_t *id )
1204 {
1205     if( id->ff_dec )
1206     {
1207         avcodec_close( id->ff_dec_c );
1208     }
1209     if( id->b_enc_inited )
1210     {
1211         avcodec_close( id->ff_enc_c );
1212     }
1213
1214     if( id->p_ff_pic)
1215     {
1216         free( id->p_ff_pic );
1217     }
1218
1219     if( id->p_ff_pic_tmp0 )
1220     {
1221         free( id->p_ff_pic_tmp0->data[0] );
1222         free( id->p_ff_pic_tmp0 );
1223     }
1224     if( id->p_ff_pic_tmp1)
1225     {
1226         free( id->p_ff_pic_tmp1->data[0] );
1227         free( id->p_ff_pic_tmp1 );
1228     }
1229     if( id->p_ff_pic_tmp2)
1230     {
1231         free( id->p_ff_pic_tmp2->data[0] );
1232         free( id->p_ff_pic_tmp2 );
1233     }
1234     if( id->p_vresample )
1235     {
1236         free( id->p_vresample );
1237     }
1238
1239     free( id->ff_dec_c );
1240     free( id->ff_enc_c );
1241
1242     free( id->p_buffer );
1243 }
1244
1245 static int transcode_video_ffmpeg_process( sout_stream_t *p_stream, sout_stream_id_t *id,
1246                                            sout_buffer_t *in, sout_buffer_t **out )
1247 {
1248     sout_stream_sys_t   *p_sys = p_stream->p_sys;
1249     int     i_used;
1250     int     i_out;
1251     int     b_gotpicture;
1252     AVFrame *frame;
1253
1254     int     i_data;
1255     uint8_t *p_data;
1256
1257     *out = NULL;
1258
1259     i_data = in->i_size;
1260     p_data = in->p_buffer;
1261
1262     for( ;; )
1263     {
1264         /* decode frame */
1265         frame = id->p_ff_pic;
1266         if( id->ff_dec )
1267         {
1268             i_used = avcodec_decode_video( id->ff_dec_c, frame,
1269                                            &b_gotpicture,
1270                                            p_data, i_data );
1271         }
1272         else
1273         {
1274             /* raw video */
1275             avpicture_fill( (AVPicture*)frame,
1276                             p_data,
1277                             id->ff_dec_c->pix_fmt,
1278                             id->ff_dec_c->width, id->ff_dec_c->height );
1279             i_used = i_data;
1280             b_gotpicture = 1;
1281         }
1282
1283         if( i_used < 0 )
1284         {
1285             msg_Warn( p_stream, "error");
1286             return VLC_EGENERIC;
1287         }
1288         i_data -= i_used;
1289         p_data += i_used;
1290
1291         if( !b_gotpicture )
1292         {
1293             return VLC_SUCCESS;
1294         }
1295
1296         if( !id->b_enc_inited )
1297         {
1298             /* XXX hack because of copy packetizer and mpeg4video that can failed
1299                detecting size */
1300             if( id->ff_enc_c->width <= 0 )
1301             {
1302                 id->ff_enc_c->width    =
1303                     id->f_dst.i_width  = id->ff_dec_c->width - p_sys->i_crop_left - p_sys->i_crop_right;
1304             }
1305             if( id->ff_enc_c->height <= 0 )
1306             {
1307                 id->ff_enc_c->height   =
1308                     id->f_dst.i_height = id->ff_dec_c->height - p_sys->i_crop_top - p_sys->i_crop_bottom;
1309             }
1310
1311             if( avcodec_open( id->ff_enc_c, id->ff_enc ) )
1312             {
1313                 msg_Err( p_stream, "cannot open encoder" );
1314                 return VLC_EGENERIC;
1315             }
1316
1317             if( !( id->id = p_stream->p_sys->p_out->pf_add( p_stream->p_sys->p_out, &id->f_dst ) ) )
1318             {
1319                 msg_Err( p_stream, "cannot add this stream" );
1320                 transcode_video_ffmpeg_close( p_stream, id );
1321                 id->b_transcode = VLC_FALSE;
1322                 return VLC_EGENERIC;
1323             }
1324             id->b_enc_inited = VLC_TRUE;
1325         }
1326
1327
1328         /* deinterlace */
1329         if( p_stream->p_sys->b_deinterlace )
1330         {
1331             if( id->p_ff_pic_tmp0 == NULL )
1332             {
1333                 int     i_size;
1334                 uint8_t *buf;
1335                 id->p_ff_pic_tmp0 = avcodec_alloc_frame();
1336                 i_size = avpicture_get_size( id->ff_dec_c->pix_fmt,
1337                                              id->ff_dec_c->width, id->ff_dec_c->height );
1338
1339                 buf = malloc( i_size );
1340
1341                 avpicture_fill( (AVPicture*)id->p_ff_pic_tmp0, buf,
1342                                 id->ff_enc_c->pix_fmt,
1343                                 id->ff_dec_c->width, id->ff_dec_c->height );
1344             }
1345
1346             avpicture_deinterlace( (AVPicture*)id->p_ff_pic_tmp0, (AVPicture*)frame,
1347                                    id->ff_dec_c->pix_fmt,
1348                                    id->ff_dec_c->width, id->ff_dec_c->height );
1349
1350             frame = id->p_ff_pic_tmp0;
1351         }
1352
1353         /* convert pix format */
1354         if( id->ff_dec_c->pix_fmt != id->ff_enc_c->pix_fmt )
1355         {
1356             if( id->p_ff_pic_tmp1 == NULL )
1357             {
1358                 int     i_size;
1359                 uint8_t *buf;
1360                 id->p_ff_pic_tmp1 = avcodec_alloc_frame();
1361                 i_size = avpicture_get_size( id->ff_enc_c->pix_fmt,
1362                                              id->ff_dec_c->width, id->ff_dec_c->height );
1363
1364                 buf = malloc( i_size );
1365
1366                 avpicture_fill( (AVPicture*)id->p_ff_pic_tmp1, buf,
1367                                 id->ff_enc_c->pix_fmt,
1368                                 id->ff_dec_c->width, id->ff_dec_c->height );
1369             }
1370
1371             img_convert( (AVPicture*)id->p_ff_pic_tmp1, id->ff_enc_c->pix_fmt,
1372                          (AVPicture*)frame,             id->ff_dec_c->pix_fmt,
1373                          id->ff_dec_c->width, id->ff_dec_c->height );
1374
1375             frame = id->p_ff_pic_tmp1;
1376         }
1377
1378         /* convert size and crop */
1379         if( id->ff_dec_c->width  != id->ff_enc_c->width ||
1380             id->ff_dec_c->height != id->ff_enc_c->height ||
1381             p_sys->i_crop_top > 0 || p_sys->i_crop_bottom > 0 ||
1382             p_sys->i_crop_left > 0 || p_sys->i_crop_right )
1383         {
1384             if( id->p_ff_pic_tmp2 == NULL )
1385             {
1386                 int     i_size;
1387                 uint8_t *buf;
1388                 id->p_ff_pic_tmp2 = avcodec_alloc_frame();
1389                 i_size = avpicture_get_size( id->ff_enc_c->pix_fmt,
1390                                              id->ff_enc_c->width, id->ff_enc_c->height );
1391
1392                 buf = malloc( i_size );
1393
1394                 avpicture_fill( (AVPicture*)id->p_ff_pic_tmp2, buf,
1395                                 id->ff_enc_c->pix_fmt,
1396                                 id->ff_enc_c->width, id->ff_enc_c->height );
1397
1398                 id->p_vresample =
1399                     img_resample_full_init( id->ff_enc_c->width, id->ff_enc_c->height,
1400                                             id->ff_dec_c->width, id->ff_dec_c->height,
1401                                             p_stream->p_sys->i_crop_top,
1402                                             p_stream->p_sys->i_crop_bottom,
1403                                             p_stream->p_sys->i_crop_left,
1404                                             p_stream->p_sys->i_crop_right );
1405             }
1406
1407             img_resample( id->p_vresample, (AVPicture*)id->p_ff_pic_tmp2, (AVPicture*)frame );
1408
1409             frame = id->p_ff_pic_tmp2;
1410         }
1411
1412         i_out = avcodec_encode_video( id->ff_enc_c, id->p_buffer, id->i_buffer, frame );
1413         if( i_out > 0 )
1414         {
1415             sout_buffer_t *p_out;
1416             p_out = sout_BufferNew( p_stream->p_sout, i_out );
1417
1418             memcpy( p_out->p_buffer, id->p_buffer, i_out );
1419
1420             p_out->i_size   = i_out;
1421             p_out->i_length = in->i_length;
1422             p_out->i_dts    = in->i_dts;
1423             p_out->i_pts    = in->i_dts; /* FIXME */
1424
1425             sout_BufferChain( out, p_out );
1426         }
1427
1428         if( i_data <= 0 )
1429         {
1430             return VLC_SUCCESS;
1431         }
1432     }
1433
1434     return VLC_SUCCESS;
1435 }