ae2e8f6e72f052b48d9c0ca8aab2394db731f79f
[vlc.git] / modules / stream_out / transcode.c
1 /*****************************************************************************
2  * transcode.c
3  *****************************************************************************
4  * Copyright (C) 2001, 2002 VideoLAN
5  * $Id: transcode.c,v 1.6 2003/05/02 03:41:03 fenrir 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 /*****************************************************************************
42  * Exported prototypes
43  *****************************************************************************/
44 static int      Open    ( vlc_object_t * );
45 static void     Close   ( vlc_object_t * );
46
47 static sout_stream_id_t *Add ( sout_stream_t *, sout_format_t * );
48 static int               Del ( sout_stream_t *, sout_stream_id_t * );
49 static int               Send( sout_stream_t *, sout_stream_id_t *, sout_buffer_t* );
50
51 static int  transcode_audio_ffmpeg_new    ( sout_stream_t *, sout_stream_id_t * );
52 static void transcode_audio_ffmpeg_close  ( sout_stream_t *, sout_stream_id_t * );
53 static int  transcode_audio_ffmpeg_process( sout_stream_t *, sout_stream_id_t *, sout_buffer_t *, sout_buffer_t ** );
54
55 static int  transcode_video_ffmpeg_new    ( sout_stream_t *, sout_stream_id_t * );
56 static void transcode_video_ffmpeg_close  ( sout_stream_t *, sout_stream_id_t * );
57 static int  transcode_video_ffmpeg_process( sout_stream_t *, sout_stream_id_t *, sout_buffer_t *, sout_buffer_t ** );
58
59 /*****************************************************************************
60  * Module descriptor
61  *****************************************************************************/
62 vlc_module_begin();
63     set_description( _("Transcode stream") );
64     set_capability( "sout stream", 50 );
65     add_shortcut( "transcode" );
66     set_callbacks( Open, Close );
67 vlc_module_end();
68
69 struct sout_stream_sys_t
70 {
71     sout_stream_t   *p_out;
72
73     vlc_fourcc_t    i_acodec;   /* codec audio (0 if not transcode) */
74     int             i_sample_rate;
75     int             i_channels;
76     int             i_abitrate;
77
78     vlc_fourcc_t    i_vcodec;   /*    "   video  " "   "      " */
79     int             i_vbitrate;
80     int             i_width;
81     int             i_height;
82     vlc_bool_t      b_deinterlace;
83
84     int             i_crop_top;
85     int             i_crop_bottom;
86     int             i_crop_right;
87     int             i_crop_left;
88 };
89
90 /*****************************************************************************
91  * Open:
92  *****************************************************************************/
93 static int Open( vlc_object_t *p_this )
94 {
95     sout_stream_t     *p_stream = (sout_stream_t*)p_this;
96     sout_stream_sys_t *p_sys;
97     char *codec;
98
99     p_sys = malloc( sizeof( sout_stream_sys_t ) );
100     p_sys->p_out = sout_stream_new( p_stream->p_sout, p_stream->psz_next );
101
102     p_sys->i_acodec      = 0;
103     p_sys->i_sample_rate = 0;
104     p_sys->i_channels    = 0;
105     p_sys->i_abitrate    = 0;
106
107     p_sys->i_vcodec     = 0;
108     p_sys->i_vbitrate   = 0;
109     p_sys->i_width      = 0;
110     p_sys->i_height     = 0;
111     p_sys->b_deinterlace= VLC_FALSE;
112
113     p_sys->i_crop_top   = 0;
114     p_sys->i_crop_bottom= 0;
115     p_sys->i_crop_right = 0;
116     p_sys->i_crop_left  = 0;
117
118     if( ( codec = sout_cfg_find_value( p_stream->p_cfg, "acodec" ) ) )
119     {
120         char fcc[4] = "    ";
121         char *val;
122
123         memcpy( fcc, codec, strlen( codec ) );
124
125         p_sys->i_acodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
126
127         if( ( val = sout_cfg_find_value( p_stream->p_cfg, "samplerate" ) ) )
128         {
129             p_sys->i_sample_rate = atoi( val );
130         }
131         if( ( val = sout_cfg_find_value( p_stream->p_cfg, "channels" ) ) )
132         {
133             p_sys->i_channels = atoi( val );
134         }
135         if( ( val = sout_cfg_find_value( p_stream->p_cfg, "ab" ) ) )
136         {
137             p_sys->i_abitrate = atoi( val );
138         }
139
140         msg_Dbg( p_stream, "codec audio=%4.4s %dHz %d channels %dKb/s",
141                  fcc,
142                  p_sys->i_sample_rate, p_sys->i_channels,
143                  p_sys->i_abitrate / 1024 );
144     }
145
146     if( ( codec = sout_cfg_find_value( p_stream->p_cfg, "vcodec" ) ) )
147     {
148         char fcc[4] = "    ";
149         char *val;
150
151         memcpy( fcc, codec, strlen( codec ) );
152
153         p_sys->i_vcodec = VLC_FOURCC( fcc[0], fcc[1], fcc[2], fcc[3] );
154
155         if( ( val = sout_cfg_find_value( p_stream->p_cfg, "width" ) ) )
156         {
157             p_sys->i_width = atoi( val );
158         }
159         if( ( val = sout_cfg_find_value( p_stream->p_cfg, "height" ) ) )
160         {
161             p_sys->i_height = atoi( val );
162         }
163         if( ( val = sout_cfg_find_value( p_stream->p_cfg, "vb" ) ) )
164         {
165             p_sys->i_vbitrate = atoi( val );
166         }
167         if( sout_cfg_find( p_stream->p_cfg, "deinterlace" ) )
168         {
169             p_sys->b_deinterlace = VLC_TRUE;
170         }
171         /* crop */
172         if( ( val = sout_cfg_find_value( p_stream->p_cfg, "croptop" ) ) )
173         {
174             p_sys->i_crop_top = atoi( val );
175         }
176         if( ( val = sout_cfg_find_value( p_stream->p_cfg, "cropbottom" ) ) )
177         {
178             p_sys->i_crop_bottom = atoi( val );
179         }
180         if( ( val = sout_cfg_find_value( p_stream->p_cfg, "cropleft" ) ) )
181         {
182             p_sys->i_crop_left = atoi( val );
183         }
184         if( ( val = sout_cfg_find_value( p_stream->p_cfg, "cropright" ) ) )
185         {
186             p_sys->i_crop_right = atoi( val );
187         }
188
189         msg_Dbg( p_stream, "codec video=%4.4s %dx%d %dkb/s",
190                  fcc,
191                  p_sys->i_width, p_sys->i_height,
192                  p_sys->i_vbitrate / 1024 );
193     }
194
195     if( !p_sys->p_out )
196     {
197         msg_Err( p_stream, "cannot create chain" );
198         free( p_sys );
199         return VLC_EGENERIC;
200     }
201     p_stream->pf_add    = Add;
202     p_stream->pf_del    = Del;
203     p_stream->pf_send   = Send;
204
205     p_stream->p_sys     = p_sys;
206
207     avcodec_init();
208     avcodec_register_all();
209
210     return VLC_SUCCESS;
211 }
212
213 /*****************************************************************************
214  * Close:
215  *****************************************************************************/
216
217 static void Close( vlc_object_t * p_this )
218 {
219     sout_stream_t       *p_stream = (sout_stream_t*)p_this;
220     sout_stream_sys_t   *p_sys = p_stream->p_sys;
221
222     sout_stream_delete( p_sys->p_out );
223     free( p_sys );
224 }
225
226 struct sout_stream_id_t
227 {
228     vlc_fourcc_t  b_transcode;
229     sout_format_t f_src;        /* only if transcoding */
230     sout_format_t f_dst;        /*  "   "      " */
231
232     /* id of the out stream */
233     void *id;
234
235     /* ffmpeg part */
236     AVCodec         *ff_dec;
237     AVCodecContext  *ff_dec_c;
238
239
240     vlc_fourcc_t    b_enc_inited;
241     AVCodec         *ff_enc;
242     AVCodecContext  *ff_enc_c;
243
244     mtime_t         i_dts;
245     mtime_t         i_length;
246
247     int             i_buffer_in;
248     int             i_buffer_in_pos;
249     uint8_t         *p_buffer_in;
250
251     int             i_buffer;
252     int             i_buffer_pos;
253     uint8_t         *p_buffer;
254
255     int             i_buffer_out;
256     int             i_buffer_out_pos;
257     uint8_t         *p_buffer_out;
258
259     AVFrame         *p_ff_pic;
260     AVFrame         *p_ff_pic_tmp0; /* to do deinterlace */
261     AVFrame         *p_ff_pic_tmp1; /* to do pix conversion */
262     AVFrame         *p_ff_pic_tmp2; /* to do resample */
263
264     ImgReSampleContext *p_vresample;
265 };
266
267
268 static sout_stream_id_t * Add      ( sout_stream_t *p_stream, sout_format_t *p_fmt )
269 {
270     sout_stream_sys_t   *p_sys = p_stream->p_sys;
271     sout_stream_id_t    *id;
272
273     id = malloc( sizeof( sout_stream_id_t ) );
274     id->i_dts = 0;
275     if( p_fmt->i_cat == AUDIO_ES && p_sys->i_acodec != 0 )
276     {
277         msg_Dbg( p_stream,
278                  "creating audio transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
279                  (char*)&p_fmt->i_fourcc,
280                  (char*)&p_sys->i_acodec );
281
282         /* src format */
283         memcpy( &id->f_src, p_fmt, sizeof( sout_format_t ) );
284
285         /* create dst format */
286         id->f_dst.i_cat    = AUDIO_ES;
287         id->f_dst.i_fourcc = p_sys->i_acodec;
288         id->f_dst.i_sample_rate = p_sys->i_sample_rate  > 0 ? p_sys->i_sample_rate : id->f_src.i_sample_rate;
289         id->f_dst.i_channels    = p_sys->i_channels > 0 ? p_sys->i_channels : id->f_src.i_channels;
290         id->f_dst.i_bitrate     = p_sys->i_abitrate > 0 ? p_sys->i_abitrate : 64000;
291         id->f_dst.i_block_align = 0;
292         id->f_dst.i_extra_data  = 0;
293         id->f_dst.p_extra_data  = NULL;
294
295         /* build decoder -> filter -> encoder */
296         if( transcode_audio_ffmpeg_new( p_stream, id ) )
297         {
298             msg_Err( p_stream, "cannot create audio chain" );
299             free( id );
300             return NULL;
301         }
302
303         /* open output stream */
304         id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->f_dst );
305         id->b_transcode = VLC_TRUE;
306     }
307     else if( p_fmt->i_cat == VIDEO_ES && p_sys->i_vcodec != 0 )
308     {
309         msg_Dbg( p_stream,
310                  "creating video transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
311                  (char*)&p_fmt->i_fourcc,
312                  (char*)&p_sys->i_vcodec );
313
314         memcpy( &id->f_src, p_fmt, sizeof( sout_format_t ) );
315
316         /* create dst format */
317         id->f_dst.i_cat         = VIDEO_ES;
318         id->f_dst.i_fourcc      = p_sys->i_vcodec;
319         id->f_dst.i_width       = p_sys->i_width ; /* > 0 ? p_sys->i_width : id->f_src.i_width; */
320         id->f_dst.i_height      = p_sys->i_height; /* > 0 ? p_sys->i_height: id->f_src.i_height; */
321         id->f_dst.i_bitrate     = p_sys->i_vbitrate > 0 ? p_sys->i_vbitrate : 800*1000;
322         id->f_dst.i_extra_data  = 0;
323         id->f_dst.p_extra_data  = NULL;
324
325         /* build decoder -> filter -> encoder */
326         if( transcode_video_ffmpeg_new( p_stream, id ) )
327         {
328             msg_Err( p_stream, "cannot create video chain" );
329             free( id );
330             return NULL;
331         }
332 #if 0
333         /* open output stream */
334         id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->f_dst );
335 #endif
336         id->b_transcode = VLC_TRUE;
337     }
338     else
339     {
340         msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')", (char*)&p_fmt->i_fourcc );
341         id->id = p_sys->p_out->pf_add( p_sys->p_out, p_fmt );
342         id->b_transcode = VLC_FALSE;
343
344         if( id->id == NULL )
345         {
346             free( id );
347             return NULL;
348         }
349     }
350
351     return id;
352 }
353
354 static int     Del      ( sout_stream_t *p_stream, sout_stream_id_t *id )
355 {
356     sout_stream_sys_t   *p_sys = p_stream->p_sys;
357
358     if( id->b_transcode )
359     {
360         if( id->f_src.i_cat == AUDIO_ES )
361         {
362             transcode_audio_ffmpeg_close( p_stream, id );
363         }
364         else if( id->f_src.i_cat == VIDEO_ES )
365         {
366             transcode_video_ffmpeg_close( p_stream, id );
367         }
368     }
369
370     p_sys->p_out->pf_del( p_sys->p_out, id->id );
371     free( id );
372
373     return VLC_SUCCESS;
374 }
375
376 static int     Send     ( sout_stream_t *p_stream, sout_stream_id_t *id, sout_buffer_t *p_buffer )
377 {
378     sout_stream_sys_t   *p_sys = p_stream->p_sys;
379
380     if( id->b_transcode )
381     {
382         sout_buffer_t *p_buffer_out;
383         if( id->f_src.i_cat == AUDIO_ES )
384         {
385             transcode_audio_ffmpeg_process( p_stream, id, p_buffer, &p_buffer_out );
386         }
387         else if( id->f_src.i_cat == VIDEO_ES )
388         {
389             transcode_video_ffmpeg_process( p_stream, id, p_buffer, &p_buffer_out );
390         }
391         sout_BufferDelete( p_stream->p_sout, p_buffer );
392
393         if( p_buffer_out )
394         {
395             return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_buffer_out );
396         }
397         return VLC_SUCCESS;
398     }
399     else if( id->id != NULL )
400     {
401         return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_buffer );
402     }
403     else
404     {
405         sout_BufferDelete( p_stream->p_sout, p_buffer );
406         return VLC_EGENERIC;
407     }
408 }
409
410 /****************************************************************************
411  * ffmpeg decoder reencocdr part
412  ****************************************************************************/
413
414 static struct
415 {
416     vlc_fourcc_t i_fcc;
417     int          i_ff_codec;
418 } fourcc_to_ff_code[] =
419 {
420     /* audio */
421     { VLC_FOURCC( 'm', 'p', 'g', 'a' ), CODEC_ID_MP2 },
422     { VLC_FOURCC( 'a', '5', '2', ' ' ), CODEC_ID_AC3 },
423     { VLC_FOURCC( 'a', 'c', '3', ' ' ), CODEC_ID_AC3 },
424     { VLC_FOURCC( 'w', 'm', 'a', '1' ), CODEC_ID_WMAV1 },
425     { VLC_FOURCC( 'w', 'm', 'a', '2' ), CODEC_ID_WMAV2 },
426
427     /* video */
428     { VLC_FOURCC( 'm', 'p', '4', 'v'),  CODEC_ID_MPEG4 },
429     { VLC_FOURCC( 'm', 'p', 'g', 'v' ), CODEC_ID_MPEG1VIDEO },
430     { VLC_FOURCC( 'D', 'I', 'V', '1' ), CODEC_ID_MSMPEG4V1 },
431     { VLC_FOURCC( 'D', 'I', 'V', '2' ), CODEC_ID_MSMPEG4V2 },
432     { VLC_FOURCC( 'D', 'I', 'V', '3' ), CODEC_ID_MSMPEG4V3 },
433     { VLC_FOURCC( 'H', '2', '6', '3' ), CODEC_ID_H263 },
434     { VLC_FOURCC( 'I', '2', '6', '3' ), CODEC_ID_H263I },
435     { VLC_FOURCC( 'W', 'M', 'V', '1' ), CODEC_ID_WMV1 },
436     { VLC_FOURCC( 'W', 'M', 'V', '2' ), CODEC_ID_WMV2 },
437     { VLC_FOURCC( 'M', 'J', 'P', 'G' ), CODEC_ID_MJPEG },
438     { VLC_FOURCC( 'm', 'j', 'p', 'b' ), CODEC_ID_MJPEGB },
439     { VLC_FOURCC( 'd', 'v', 's', 'l' ), CODEC_ID_DVVIDEO },
440     { VLC_FOURCC( 'S', 'V', 'Q', '1' ), CODEC_ID_SVQ1 },
441
442     /* raw video code, only used for 'encoding' */
443     { VLC_FOURCC( 'I', '4', '2', '0' ), CODEC_ID_RAWVIDEO },
444     { VLC_FOURCC( 'I', '4', '2', '2' ), CODEC_ID_RAWVIDEO },
445     { VLC_FOURCC( 'I', '4', '4', '4' ), CODEC_ID_RAWVIDEO },
446     { VLC_FOURCC( 'R', 'V', '2', '4' ), CODEC_ID_RAWVIDEO },
447     { VLC_FOURCC( 'Y', 'U', 'Y', '2' ), CODEC_ID_RAWVIDEO },
448
449     { VLC_FOURCC(   0,   0,   0,   0 ), 0 }
450 };
451
452 static inline int get_ff_codec( vlc_fourcc_t i_fcc )
453 {
454     int i;
455
456     for( i = 0; fourcc_to_ff_code[i].i_fcc != 0; i++ )
457     {
458         if( fourcc_to_ff_code[i].i_fcc == i_fcc )
459         {
460             return fourcc_to_ff_code[i].i_ff_codec;
461         }
462     }
463
464     return 0;
465 }
466
467 static inline int get_ff_chroma( vlc_fourcc_t i_chroma )
468 {
469     switch( i_chroma )
470     {
471         case VLC_FOURCC( 'I', '4', '2', '0' ):
472             return PIX_FMT_YUV420P;
473         case VLC_FOURCC( 'I', '4', '2', '2' ):
474             return PIX_FMT_YUV422P;
475         case VLC_FOURCC( 'I', '4', '4', '4' ):
476             return PIX_FMT_YUV444P;
477         case VLC_FOURCC( 'R', 'V', '2', '4' ):
478             return PIX_FMT_RGB24;
479         case VLC_FOURCC( 'Y', 'U', 'Y', '2' ):
480             return PIX_FMT_YUV422;
481         default:
482             return 0;
483     }
484 }
485
486 static int transcode_audio_ffmpeg_new   ( sout_stream_t *p_stream, sout_stream_id_t *id )
487 {
488     int i_ff_codec;
489
490     /* find decoder */
491
492     i_ff_codec = get_ff_codec( id->f_src.i_fourcc );
493     if( i_ff_codec == 0 )
494     {
495         msg_Err( p_stream, "cannot find decoder" );
496         return VLC_EGENERIC;
497     }
498
499     id->ff_dec = avcodec_find_decoder( i_ff_codec );
500     if( !id->ff_dec )
501     {
502         msg_Err( p_stream, "cannot find decoder" );
503         return VLC_EGENERIC;
504     }
505
506     id->ff_dec_c = avcodec_alloc_context();
507     id->ff_dec_c->sample_rate = id->f_src.i_sample_rate;
508     id->ff_dec_c->channels    = id->f_src.i_channels;
509     id->ff_dec_c->block_align = id->f_src.i_block_align;
510     id->ff_dec_c->bit_rate    = id->f_src.i_bitrate;
511
512     id->ff_dec_c->extradata_size = id->f_src.i_extra_data;
513     id->ff_dec_c->extradata      = id->f_src.p_extra_data;
514     if( avcodec_open( id->ff_dec_c, id->ff_dec ) )
515     {
516         msg_Err( p_stream, "cannot open decoder" );
517         return VLC_EGENERIC;
518     }
519
520     /* find encoder */
521     i_ff_codec = get_ff_codec( id->f_dst.i_fourcc );
522     if( i_ff_codec == 0 )
523     {
524         msg_Err( p_stream, "cannot find encoder" );
525         return VLC_EGENERIC;
526     }
527
528     id->ff_enc = avcodec_find_encoder( i_ff_codec );
529     if( !id->ff_enc )
530     {
531         msg_Err( p_stream, "cannot find encoder" );
532         return VLC_EGENERIC;
533     }
534
535     id->ff_enc_c = avcodec_alloc_context();
536     id->ff_enc_c->bit_rate    = id->f_dst.i_bitrate;
537     id->ff_enc_c->sample_rate = id->f_dst.i_sample_rate;
538     id->ff_enc_c->channels    = id->f_dst.i_channels;
539
540     if( avcodec_open( id->ff_enc_c, id->ff_enc ) )
541     {
542         msg_Err( p_stream, "cannot open encoder" );
543         return VLC_EGENERIC;
544     }
545
546
547     id->i_buffer_in      = AVCODEC_MAX_AUDIO_FRAME_SIZE;
548     id->i_buffer_in_pos = 0;
549     id->p_buffer_in      = malloc( id->i_buffer_in );
550
551     id->i_buffer     = AVCODEC_MAX_AUDIO_FRAME_SIZE;
552     id->i_buffer_pos = 0;
553     id->p_buffer     = malloc( id->i_buffer );
554
555     id->i_buffer_out     = AVCODEC_MAX_AUDIO_FRAME_SIZE;
556     id->i_buffer_out_pos = 0;
557     id->p_buffer_out     = malloc( id->i_buffer_out );
558
559     return VLC_SUCCESS;
560 }
561
562 static void transcode_audio_ffmpeg_close ( sout_stream_t *p_stream, sout_stream_id_t *id )
563 {
564     avcodec_close( id->ff_dec_c );
565     avcodec_close( id->ff_enc_c );
566
567     free( id->ff_dec_c );
568     free( id->ff_enc_c );
569
570     free( id->p_buffer );
571 }
572
573 static int transcode_audio_ffmpeg_process( sout_stream_t *p_stream, sout_stream_id_t *id,
574                                            sout_buffer_t *in, sout_buffer_t **out )
575 {
576     *out = NULL;
577
578     /* gather data into p_buffer_in */
579     id->i_dts = in->i_dts -
580                 (mtime_t)1000000 *
581                 (mtime_t)(id->i_buffer_pos / 2 / id->ff_enc_c->channels )/
582                 (mtime_t)id->ff_enc_c->sample_rate;
583
584     memcpy( &id->p_buffer_in[id->i_buffer_in_pos],
585             in->p_buffer,
586             in->i_size );
587     id->i_buffer_in_pos += in->i_size;
588
589     /* decode as many data as possible */
590     for( ;; )
591     {
592         int i_buffer_size;
593         int i_used;
594
595         i_buffer_size = id->i_buffer - id->i_buffer_pos;
596
597         i_used = avcodec_decode_audio( id->ff_dec_c,
598                                        (int16_t*)&id->p_buffer[id->i_buffer_pos], &i_buffer_size,
599                                        id->p_buffer_in, id->i_buffer_in_pos );
600
601         /* msg_Warn( p_stream, "avcodec_decode_audio: %d used", i_used ); */
602         id->i_buffer_pos += i_buffer_size;
603
604         if( i_used < 0 )
605         {
606             msg_Warn( p_stream, "error");
607             id->i_buffer_in_pos = 0;
608             break;
609         }
610         else if( i_used < id->i_buffer_in_pos )
611         {
612             memmove( id->p_buffer_in,
613                      &id->p_buffer_in[i_used],
614                      id->i_buffer_in - i_used );
615             id->i_buffer_in_pos -= i_used;
616         }
617         else
618         {
619             id->i_buffer_in_pos = 0;
620             break;
621         }
622     }
623
624     /* encode as many data as possible */
625     for( ;; )
626     {
627         int i_frame_size = id->ff_enc_c->frame_size * 2 * id->ff_enc_c->channels;
628         int i_out_size;
629         sout_buffer_t *p_out;
630
631         if( id->i_buffer_pos < i_frame_size )
632         {
633             break;
634         }
635
636         /* msg_Warn( p_stream, "avcodec_encode_audio: frame size%d", i_frame_size); */
637         i_out_size = avcodec_encode_audio( id->ff_enc_c,
638                                            id->p_buffer_out, id->i_buffer_out,
639                                            (int16_t*)id->p_buffer );
640
641         if( i_out_size <= 0 )
642         {
643             break;
644         }
645         memmove( id->p_buffer,
646                  &id->p_buffer[i_frame_size],
647                  id->i_buffer - i_frame_size );
648         id->i_buffer_pos -= i_frame_size;
649
650         p_out = sout_BufferNew( p_stream->p_sout, i_out_size );
651         memcpy( p_out->p_buffer, id->p_buffer_out, i_out_size );
652         p_out->i_size = i_out_size;
653         p_out->i_length = (mtime_t)1000000 * (mtime_t)id->ff_enc_c->frame_size / (mtime_t)id->ff_enc_c->sample_rate;
654         /* FIXME */
655         p_out->i_dts = id->i_dts;
656         p_out->i_pts = id->i_dts;
657
658         /* update dts */
659         id->i_dts += p_out->i_length;
660
661        /* msg_Warn( p_stream, "frame dts=%lld len %lld out=%d", p_out->i_dts, p_out->i_length, i_out_size ); */
662         sout_BufferChain( out, p_out );
663     }
664
665     return VLC_SUCCESS;
666 }
667
668
669 /*
670  * video
671  */
672 static int transcode_video_ffmpeg_new   ( sout_stream_t *p_stream, sout_stream_id_t *id )
673 {
674     int i_ff_codec;
675
676     if( id->f_src.i_fourcc == VLC_FOURCC( 'I', '4', '2', '0' ) ||
677         id->f_src.i_fourcc == VLC_FOURCC( 'I', '4', '2', '2' ) ||
678         id->f_src.i_fourcc == VLC_FOURCC( 'I', '4', '4', '4' ) ||
679         id->f_src.i_fourcc == VLC_FOURCC( 'Y', 'U', 'Y', '2' ) ||
680         id->f_src.i_fourcc == VLC_FOURCC( 'R', 'V', '2', '4' ) )
681     {
682         id->ff_dec   = NULL;
683         id->ff_dec_c            = avcodec_alloc_context();
684         id->ff_dec_c->width     = id->f_src.i_width;
685         id->ff_dec_c->height    = id->f_src.i_height;
686         id->ff_dec_c->pix_fmt   = get_ff_chroma( id->f_src.i_fourcc );
687     }
688     else
689     {
690         /* find decoder */
691         i_ff_codec = get_ff_codec( id->f_src.i_fourcc );
692         if( i_ff_codec == 0 )
693         {
694             msg_Err( p_stream, "cannot find decoder" );
695             return VLC_EGENERIC;
696         }
697
698         id->ff_dec = avcodec_find_decoder( i_ff_codec );
699         if( !id->ff_dec )
700         {
701             msg_Err( p_stream, "cannot find decoder" );
702             return VLC_EGENERIC;
703         }
704
705         id->ff_dec_c = avcodec_alloc_context();
706         id->ff_dec_c->width         = id->f_src.i_width;
707         id->ff_dec_c->height        = id->f_src.i_height;
708         /* id->ff_dec_c->bit_rate      = id->f_src.i_bitrate; */
709         id->ff_dec_c->extradata_size= id->f_src.i_extra_data;
710         id->ff_dec_c->extradata     = id->f_src.p_extra_data;
711         id->ff_dec_c->workaround_bugs = FF_BUG_AUTODETECT;
712         id->ff_dec_c->error_resilience= -1;
713         if( id->ff_dec->capabilities & CODEC_CAP_TRUNCATED )
714         {
715             id->ff_dec_c->flags |= CODEC_FLAG_TRUNCATED;
716         }
717
718         if( avcodec_open( id->ff_dec_c, id->ff_dec ) < 0 )
719         {
720             msg_Err( p_stream, "cannot open decoder" );
721             return VLC_EGENERIC;
722         }
723
724         if( i_ff_codec == CODEC_ID_MPEG4 && id->ff_dec_c->extradata_size > 0 )
725         {
726             int b_gotpicture;
727             AVFrame frame;
728
729             avcodec_decode_video( id->ff_dec_c, &frame,
730                                   &b_gotpicture,
731                                   id->ff_dec_c->extradata, id->ff_dec_c->extradata_size );
732         }
733     }
734
735
736     /* find encoder */
737     i_ff_codec = get_ff_codec( id->f_dst.i_fourcc );
738     if( i_ff_codec == 0 )
739     {
740         msg_Err( p_stream, "cannot find encoder" );
741         return VLC_EGENERIC;
742     }
743
744     id->ff_enc = avcodec_find_encoder( i_ff_codec );
745     if( !id->ff_enc )
746     {
747         msg_Err( p_stream, "cannot find encoder" );
748         return VLC_EGENERIC;
749     }
750
751     id->ff_enc_c = avcodec_alloc_context();
752     id->ff_enc_c->width          = id->f_dst.i_width;
753     id->ff_enc_c->height         = id->f_dst.i_height;
754     id->ff_enc_c->bit_rate       = id->f_dst.i_bitrate;
755 #if LIBAVCODEC_BUILD >= 4662
756     id->ff_enc_c->frame_rate     = 25 ; /* FIXME as it break mpeg */
757     id->ff_enc_c->frame_rate_base= 1;
758 #else
759     id->ff_enc_c->frame_rate     = 25 * FRAME_RATE_BASE;
760 #endif
761     id->ff_enc_c->gop_size       = 25;
762     id->ff_enc_c->qmin           = 2;
763     id->ff_enc_c->qmax           = 31;
764
765     if( i_ff_codec == CODEC_ID_RAWVIDEO )
766     {
767         id->ff_enc_c->pix_fmt = get_ff_chroma( id->f_dst.i_fourcc );
768     }
769     /* XXX open it only when we have the first frame */
770     id->b_enc_inited     = VLC_FALSE;
771     id->i_buffer_in      = 0;
772     id->i_buffer_in_pos  = 0;
773     id->p_buffer_in      = NULL;
774
775     id->i_buffer     = 3*1024*1024;
776     id->i_buffer_pos = 0;
777     id->p_buffer     = malloc( id->i_buffer );
778
779     id->i_buffer_out     = 0;
780     id->i_buffer_out_pos = 0;
781     id->p_buffer_out     = NULL;
782
783     id->p_ff_pic         = avcodec_alloc_frame();
784     id->p_ff_pic_tmp0    = NULL;
785     id->p_ff_pic_tmp1    = NULL;
786     id->p_ff_pic_tmp2    = NULL;
787     id->p_vresample      = NULL;
788     return VLC_SUCCESS;
789 }
790
791 static void transcode_video_ffmpeg_close ( sout_stream_t *p_stream, sout_stream_id_t *id )
792 {
793     if( id->ff_dec )
794     {
795         avcodec_close( id->ff_dec_c );
796     }
797     if( id->b_enc_inited )
798     {
799         avcodec_close( id->ff_enc_c );
800     }
801
802     if( id->p_ff_pic)
803     {
804         free( id->p_ff_pic );
805     }
806
807     if( id->p_ff_pic_tmp0 )
808     {
809         free( id->p_ff_pic_tmp0->data[0] );
810         free( id->p_ff_pic_tmp0 );
811     }
812     if( id->p_ff_pic_tmp1)
813     {
814         free( id->p_ff_pic_tmp1->data[0] );
815         free( id->p_ff_pic_tmp1 );
816     }
817     if( id->p_ff_pic_tmp2)
818     {
819         free( id->p_ff_pic_tmp2->data[0] );
820         free( id->p_ff_pic_tmp2 );
821     }
822     if( id->p_vresample )
823     {
824         free( id->p_vresample );
825     }
826
827     free( id->ff_dec_c );
828     free( id->ff_enc_c );
829
830     free( id->p_buffer );
831 }
832
833 static int transcode_video_ffmpeg_process( sout_stream_t *p_stream, sout_stream_id_t *id,
834                                            sout_buffer_t *in, sout_buffer_t **out )
835 {
836     int     i_used;
837     int     i_out;
838     int     b_gotpicture;
839     AVFrame *frame;
840
841     int     i_data;
842     uint8_t *p_data;
843
844     *out = NULL;
845
846     i_data = in->i_size;
847     p_data = in->p_buffer;
848
849     for( ;; )
850     {
851         /* decode frame */
852         frame = id->p_ff_pic;
853         if( id->ff_dec )
854         {
855             i_used = avcodec_decode_video( id->ff_dec_c, frame,
856                                            &b_gotpicture,
857                                            p_data, i_data );
858         }
859         else
860         {
861             /* raw video */
862             avpicture_fill( (AVPicture*)frame,
863                             p_data,
864                             id->ff_dec_c->pix_fmt,
865                             id->ff_dec_c->width, id->ff_dec_c->height );
866             i_used = i_data;
867             b_gotpicture = 1;
868         }
869
870         if( i_used < 0 )
871         {
872             msg_Warn( p_stream, "error");
873             return VLC_EGENERIC;
874         }
875         i_data -= i_used;
876         p_data += i_used;
877
878         if( !b_gotpicture )
879         {
880             return VLC_SUCCESS;
881         }
882
883         if( !id->b_enc_inited )
884         {
885             /* XXX hack because of copy packetizer and mpeg4video that can failed
886                detecting size */
887             if( id->ff_enc_c->width <= 0 || id->ff_enc_c->height <= 0 )
888             {
889                 id->ff_enc_c->width  = id->f_dst.i_width  = id->ff_dec_c->width;
890                 id->ff_enc_c->height = id->f_dst.i_height = id->ff_dec_c->height;
891             }
892
893             if( avcodec_open( id->ff_enc_c, id->ff_enc ) )
894             {
895                 msg_Err( p_stream, "cannot open encoder" );
896                 return VLC_EGENERIC;
897             }
898
899             if( !( id->id = p_stream->p_sys->p_out->pf_add( p_stream->p_sys->p_out, &id->f_dst ) ) )
900             {
901                 msg_Err( p_stream, "cannot add this stream" );
902                 transcode_video_ffmpeg_close( p_stream, id );
903                 id->b_transcode = VLC_FALSE;
904                 return VLC_EGENERIC;
905             }
906             id->b_enc_inited = VLC_TRUE;
907         }
908
909
910         /* deinterlace */
911         if( p_stream->p_sys->b_deinterlace )
912         {
913             if( id->p_ff_pic_tmp0 == NULL )
914             {
915                 int     i_size;
916                 uint8_t *buf;
917                 id->p_ff_pic_tmp0 = avcodec_alloc_frame();
918                 i_size = avpicture_get_size( id->ff_dec_c->pix_fmt,
919                                              id->ff_dec_c->width, id->ff_dec_c->height );
920
921                 buf = malloc( i_size );
922
923                 avpicture_fill( (AVPicture*)id->p_ff_pic_tmp0, buf,
924                                 id->ff_enc_c->pix_fmt,
925                                 id->ff_dec_c->width, id->ff_dec_c->height );
926             }
927
928             avpicture_deinterlace( (AVPicture*)id->p_ff_pic_tmp0, (AVPicture*)frame,
929                                    id->ff_dec_c->pix_fmt,
930                                    id->ff_dec_c->width, id->ff_dec_c->height );
931
932             frame = id->p_ff_pic_tmp0;
933         }
934
935         /* convert pix format */
936         if( id->ff_dec_c->pix_fmt != id->ff_enc_c->pix_fmt )
937         {
938             if( id->p_ff_pic_tmp1 == NULL )
939             {
940                 int     i_size;
941                 uint8_t *buf;
942                 id->p_ff_pic_tmp1 = avcodec_alloc_frame();
943                 i_size = avpicture_get_size( id->ff_enc_c->pix_fmt,
944                                              id->ff_dec_c->width, id->ff_dec_c->height );
945
946                 buf = malloc( i_size );
947
948                 avpicture_fill( (AVPicture*)id->p_ff_pic_tmp1, buf,
949                                 id->ff_enc_c->pix_fmt,
950                                 id->ff_dec_c->width, id->ff_dec_c->height );
951             }
952
953             img_convert( (AVPicture*)id->p_ff_pic_tmp1, id->ff_enc_c->pix_fmt,
954                          (AVPicture*)frame,             id->ff_dec_c->pix_fmt,
955                          id->ff_dec_c->width, id->ff_dec_c->height );
956
957             frame = id->p_ff_pic_tmp1;
958         }
959
960         /* convert size and crop */
961         if( ( id->ff_dec_c->width  != id->ff_enc_c->width ) ||
962             ( id->ff_dec_c->height != id->ff_enc_c->height ) )
963         {
964             if( id->p_ff_pic_tmp2 == NULL )
965             {
966                 int     i_size;
967                 uint8_t *buf;
968                 id->p_ff_pic_tmp2 = avcodec_alloc_frame();
969                 i_size = avpicture_get_size( id->ff_enc_c->pix_fmt,
970                                              id->ff_enc_c->width, id->ff_enc_c->height );
971
972                 buf = malloc( i_size );
973
974                 avpicture_fill( (AVPicture*)id->p_ff_pic_tmp2, buf,
975                                 id->ff_enc_c->pix_fmt,
976                                 id->ff_enc_c->width, id->ff_enc_c->height );
977
978                 id->p_vresample =
979                     img_resample_full_init( id->ff_enc_c->width, id->ff_enc_c->height,
980                                             id->ff_dec_c->width, id->ff_dec_c->height,
981                                             p_stream->p_sys->i_crop_top,
982                                             p_stream->p_sys->i_crop_bottom,
983                                             p_stream->p_sys->i_crop_left,
984                                             p_stream->p_sys->i_crop_right );
985             }
986
987             img_resample( id->p_vresample, (AVPicture*)id->p_ff_pic_tmp2, (AVPicture*)frame );
988
989             frame = id->p_ff_pic_tmp2;
990         }
991
992         i_out = avcodec_encode_video( id->ff_enc_c, id->p_buffer, id->i_buffer, frame );
993         if( i_out > 0 )
994         {
995             sout_buffer_t *p_out;
996             p_out = sout_BufferNew( p_stream->p_sout, i_out );
997
998             memcpy( p_out->p_buffer, id->p_buffer, i_out );
999
1000             p_out->i_size   = i_out;
1001             p_out->i_length = in->i_length;
1002             p_out->i_dts    = in->i_dts;
1003             p_out->i_pts    = in->i_dts; /* FIXME */
1004
1005             sout_BufferChain( out, p_out );
1006         }
1007
1008         if( i_data <= 0 )
1009         {
1010             return VLC_SUCCESS;
1011         }
1012     }
1013
1014     return VLC_SUCCESS;
1015 }
1016