* transcode: should be able to compress raw audio, need to be cleaned up.
[vlc.git] / modules / stream_out / transcode.c
1 /*****************************************************************************
2  * transcode.c
3  *****************************************************************************
4  * Copyright (C) 2001, 2002 VideoLAN
5  * $Id: transcode.c,v 1.7 2003/05/02 14:51:57 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     if( id->f_src.i_fourcc == VLC_FOURCC('s','1','6','l') ||
491         id->f_src.i_fourcc == VLC_FOURCC('s','1','6','b') ||
492         id->f_src.i_fourcc == VLC_FOURCC('s','8',' ',' ') ||
493         id->f_src.i_fourcc == VLC_FOURCC('u','8',' ',' ') )
494     {
495         id->ff_dec = NULL;
496
497         id->ff_dec_c = avcodec_alloc_context();
498         id->ff_dec_c->sample_rate = id->f_src.i_sample_rate;
499         id->ff_dec_c->channels    = id->f_src.i_channels;
500         id->ff_dec_c->block_align = id->f_src.i_block_align;
501         id->ff_dec_c->bit_rate    = id->f_src.i_bitrate;
502     }
503     else
504     {
505         /* find decoder */
506         i_ff_codec = get_ff_codec( id->f_src.i_fourcc );
507         if( i_ff_codec == 0 )
508         {
509             msg_Err( p_stream, "cannot find decoder" );
510             return VLC_EGENERIC;
511         }
512
513         id->ff_dec = avcodec_find_decoder( i_ff_codec );
514         if( !id->ff_dec )
515         {
516             msg_Err( p_stream, "cannot find decoder" );
517             return VLC_EGENERIC;
518         }
519
520         id->ff_dec_c = avcodec_alloc_context();
521         id->ff_dec_c->sample_rate = id->f_src.i_sample_rate;
522         id->ff_dec_c->channels    = id->f_src.i_channels;
523         id->ff_dec_c->block_align = id->f_src.i_block_align;
524         id->ff_dec_c->bit_rate    = id->f_src.i_bitrate;
525
526         id->ff_dec_c->extradata_size = id->f_src.i_extra_data;
527         id->ff_dec_c->extradata      = id->f_src.p_extra_data;
528         if( avcodec_open( id->ff_dec_c, id->ff_dec ) )
529         {
530             msg_Err( p_stream, "cannot open decoder" );
531             return VLC_EGENERIC;
532         }
533     }
534
535     /* find encoder */
536     i_ff_codec = get_ff_codec( id->f_dst.i_fourcc );
537     if( i_ff_codec == 0 )
538     {
539         msg_Err( p_stream, "cannot find encoder" );
540         return VLC_EGENERIC;
541     }
542
543     id->ff_enc = avcodec_find_encoder( i_ff_codec );
544     if( !id->ff_enc )
545     {
546         msg_Err( p_stream, "cannot find encoder" );
547         return VLC_EGENERIC;
548     }
549
550     id->ff_enc_c = avcodec_alloc_context();
551     id->ff_enc_c->bit_rate    = id->f_dst.i_bitrate;
552     id->ff_enc_c->sample_rate = id->f_dst.i_sample_rate;
553     id->ff_enc_c->channels    = id->f_dst.i_channels;
554
555     if( avcodec_open( id->ff_enc_c, id->ff_enc ) )
556     {
557         msg_Err( p_stream, "cannot open encoder" );
558         return VLC_EGENERIC;
559     }
560
561
562     id->i_buffer_in      = AVCODEC_MAX_AUDIO_FRAME_SIZE;
563     id->i_buffer_in_pos = 0;
564     id->p_buffer_in      = malloc( id->i_buffer_in );
565
566     id->i_buffer     = AVCODEC_MAX_AUDIO_FRAME_SIZE;
567     id->i_buffer_pos = 0;
568     id->p_buffer     = malloc( id->i_buffer );
569
570     id->i_buffer_out     = AVCODEC_MAX_AUDIO_FRAME_SIZE;
571     id->i_buffer_out_pos = 0;
572     id->p_buffer_out     = malloc( id->i_buffer_out );
573
574     return VLC_SUCCESS;
575 }
576
577 static void transcode_audio_ffmpeg_close ( sout_stream_t *p_stream, sout_stream_id_t *id )
578 {
579     if( id->ff_dec )
580     {
581         avcodec_close( id->ff_dec_c );
582     }
583     avcodec_close( id->ff_enc_c );
584
585     free( id->ff_dec_c );
586     free( id->ff_enc_c );
587
588     free( id->p_buffer );
589 }
590
591 static int transcode_audio_ffmpeg_process( sout_stream_t *p_stream, sout_stream_id_t *id,
592                                            sout_buffer_t *in, sout_buffer_t **out )
593 {
594     *out = NULL;
595
596     /* gather data into p_buffer_in */
597     id->i_dts = in->i_dts -
598                 (mtime_t)1000000 *
599                 (mtime_t)(id->i_buffer_pos / 2 / id->ff_enc_c->channels )/
600                 (mtime_t)id->ff_enc_c->sample_rate;
601
602     if( id->i_buffer_in_pos + in->i_size > id->i_buffer_in )
603     {
604         /* extend buffer_in */
605         id->i_buffer_in = id->i_buffer_in_pos + in->i_size + 1024;
606         id->p_buffer_in = realloc( id->p_buffer_in, id->i_buffer_in );
607     }
608     memcpy( &id->p_buffer_in[id->i_buffer_in_pos],
609             in->p_buffer,
610             in->i_size );
611     id->i_buffer_in_pos += in->i_size;
612
613     /* decode as many data as possible */
614     if( id->ff_dec )
615     {
616         for( ;; )
617         {
618             int i_buffer_size;
619             int i_used;
620
621             i_buffer_size = id->i_buffer - id->i_buffer_pos;
622
623             i_used = avcodec_decode_audio( id->ff_dec_c,
624                                            (int16_t*)&id->p_buffer[id->i_buffer_pos], &i_buffer_size,
625                                            id->p_buffer_in, id->i_buffer_in_pos );
626
627             /* msg_Warn( p_stream, "avcodec_decode_audio: %d used", i_used ); */
628             id->i_buffer_pos += i_buffer_size;
629
630             if( i_used < 0 )
631             {
632                 msg_Warn( p_stream, "error");
633                 id->i_buffer_in_pos = 0;
634                 break;
635             }
636             else if( i_used < id->i_buffer_in_pos )
637             {
638                 memmove( id->p_buffer_in,
639                          &id->p_buffer_in[i_used],
640                          id->i_buffer_in - i_used );
641                 id->i_buffer_in_pos -= i_used;
642             }
643             else
644             {
645                 id->i_buffer_in_pos = 0;
646                 break;
647             }
648         }
649     }
650     else
651     {
652         int16_t *sout = (int16_t*)&id->p_buffer[id->i_buffer_pos];
653         int     i_used;
654
655         if( id->f_src.i_fourcc == VLC_FOURCC( 's', '8', ' ', ' ' ) )
656         {
657             int8_t *sin = (int8_t*)id->p_buffer_in;
658             int     i_samples = __MIN( ( id->i_buffer - id->i_buffer_pos ) / 2, id->i_buffer_in_pos );
659             i_used = i_samples;
660             while( i_samples > 0 )
661             {
662                 *sout++ = ( *sin++ ) << 8;
663                 i_samples--;
664             }
665         }
666         else if( id->f_src.i_fourcc == VLC_FOURCC( 'u', '8', ' ', ' ' ) )
667         {
668             int8_t *sin = (int8_t*)id->p_buffer_in;
669             int     i_samples = __MIN( ( id->i_buffer - id->i_buffer_pos ) / 2, id->i_buffer_in_pos );
670             i_used = i_samples;
671             while( i_samples > 0 )
672             {
673                 *sout++ = ( *sin++ - 128 ) << 8;
674                 i_samples--;
675             }
676         }
677         else if( id->f_src.i_fourcc == VLC_FOURCC( 's', '1', '6', 'l' ) )
678         {
679             int     i_samples = __MIN( ( id->i_buffer - id->i_buffer_pos ) / 2, id->i_buffer_in_pos / 2);
680             i_used = i_samples * 2;
681 #ifdef WORDS_BIGENDIAN
682             uint8_t *sin = (uint8_t*)id->p_buffer_in;
683             while( i_samples > 0 )
684             {
685                 uint8_t tmp[2];
686
687                 tmp[1] = *sin++;
688                 tmp[0] = *sin++;
689                 *sout++ = *(int16_t*)tmp;
690                 i_samples--;
691             }
692
693 #else
694             memcpy( sout, id->p_buffer_in, i_samples * 2 );
695             sout += i_samples;
696 #endif
697         }
698         else if( id->f_src.i_fourcc == VLC_FOURCC( 's', '1', '6', 'b' ) )
699         {
700             int     i_samples = __MIN( ( id->i_buffer - id->i_buffer_pos ) / 2, id->i_buffer_in_pos / 2);
701             i_used = i_samples * 2;
702 #ifdef WORDS_BIGENDIAN
703             memcpy( sout, id->p_buffer_in, i_samples * 2 );
704             sout += i_samples;
705 #else
706             uint8_t *sin = (uint8_t*)id->p_buffer_in;
707             while( i_samples > 0 )
708             {
709                 uint8_t tmp[2];
710
711                 tmp[1] = *sin++;
712                 tmp[0] = *sin++;
713                 *sout++ = *(int16_t*)tmp;
714                 i_samples--;
715             }
716 #endif
717         }
718
719         id->i_buffer_pos = (uint8_t*)sout - id->p_buffer;
720         if( i_used < id->i_buffer_in_pos )
721         {
722             memmove( id->p_buffer_in,
723                      &id->p_buffer_in[i_used],
724                      id->i_buffer_in - i_used );
725         }
726         id->i_buffer_in_pos -= i_used;
727     }
728
729     /* encode as many data as possible */
730     for( ;; )
731     {
732         int i_frame_size = id->ff_enc_c->frame_size * 2 * id->ff_enc_c->channels;
733         int i_out_size;
734         sout_buffer_t *p_out;
735
736         if( id->i_buffer_pos < i_frame_size )
737         {
738             break;
739         }
740
741         /* msg_Warn( p_stream, "avcodec_encode_audio: frame size%d", i_frame_size); */
742         i_out_size = avcodec_encode_audio( id->ff_enc_c,
743                                            id->p_buffer_out, id->i_buffer_out,
744                                            (int16_t*)id->p_buffer );
745
746         if( i_out_size <= 0 )
747         {
748             break;
749         }
750         memmove( id->p_buffer,
751                  &id->p_buffer[i_frame_size],
752                  id->i_buffer - i_frame_size );
753         id->i_buffer_pos -= i_frame_size;
754
755         p_out = sout_BufferNew( p_stream->p_sout, i_out_size );
756         memcpy( p_out->p_buffer, id->p_buffer_out, i_out_size );
757         p_out->i_size = i_out_size;
758         p_out->i_length = (mtime_t)1000000 * (mtime_t)id->ff_enc_c->frame_size / (mtime_t)id->ff_enc_c->sample_rate;
759         /* FIXME */
760         p_out->i_dts = id->i_dts;
761         p_out->i_pts = id->i_dts;
762
763         /* update dts */
764         id->i_dts += p_out->i_length;
765
766        /* msg_Warn( p_stream, "frame dts=%lld len %lld out=%d", p_out->i_dts, p_out->i_length, i_out_size ); */
767         sout_BufferChain( out, p_out );
768     }
769
770     return VLC_SUCCESS;
771 }
772
773
774 /*
775  * video
776  */
777 static int transcode_video_ffmpeg_new   ( sout_stream_t *p_stream, sout_stream_id_t *id )
778 {
779     int i_ff_codec;
780
781     if( id->f_src.i_fourcc == VLC_FOURCC( 'I', '4', '2', '0' ) ||
782         id->f_src.i_fourcc == VLC_FOURCC( 'I', '4', '2', '2' ) ||
783         id->f_src.i_fourcc == VLC_FOURCC( 'I', '4', '4', '4' ) ||
784         id->f_src.i_fourcc == VLC_FOURCC( 'Y', 'U', 'Y', '2' ) ||
785         id->f_src.i_fourcc == VLC_FOURCC( 'R', 'V', '2', '4' ) )
786     {
787         id->ff_dec   = NULL;
788         id->ff_dec_c            = avcodec_alloc_context();
789         id->ff_dec_c->width     = id->f_src.i_width;
790         id->ff_dec_c->height    = id->f_src.i_height;
791         id->ff_dec_c->pix_fmt   = get_ff_chroma( id->f_src.i_fourcc );
792     }
793     else
794     {
795         /* find decoder */
796         i_ff_codec = get_ff_codec( id->f_src.i_fourcc );
797         if( i_ff_codec == 0 )
798         {
799             msg_Err( p_stream, "cannot find decoder" );
800             return VLC_EGENERIC;
801         }
802
803         id->ff_dec = avcodec_find_decoder( i_ff_codec );
804         if( !id->ff_dec )
805         {
806             msg_Err( p_stream, "cannot find decoder" );
807             return VLC_EGENERIC;
808         }
809
810         id->ff_dec_c = avcodec_alloc_context();
811         id->ff_dec_c->width         = id->f_src.i_width;
812         id->ff_dec_c->height        = id->f_src.i_height;
813         /* id->ff_dec_c->bit_rate      = id->f_src.i_bitrate; */
814         id->ff_dec_c->extradata_size= id->f_src.i_extra_data;
815         id->ff_dec_c->extradata     = id->f_src.p_extra_data;
816         id->ff_dec_c->workaround_bugs = FF_BUG_AUTODETECT;
817         id->ff_dec_c->error_resilience= -1;
818         if( id->ff_dec->capabilities & CODEC_CAP_TRUNCATED )
819         {
820             id->ff_dec_c->flags |= CODEC_FLAG_TRUNCATED;
821         }
822
823         if( avcodec_open( id->ff_dec_c, id->ff_dec ) < 0 )
824         {
825             msg_Err( p_stream, "cannot open decoder" );
826             return VLC_EGENERIC;
827         }
828
829         if( i_ff_codec == CODEC_ID_MPEG4 && id->ff_dec_c->extradata_size > 0 )
830         {
831             int b_gotpicture;
832             AVFrame frame;
833
834             avcodec_decode_video( id->ff_dec_c, &frame,
835                                   &b_gotpicture,
836                                   id->ff_dec_c->extradata, id->ff_dec_c->extradata_size );
837         }
838     }
839
840
841     /* find encoder */
842     i_ff_codec = get_ff_codec( id->f_dst.i_fourcc );
843     if( i_ff_codec == 0 )
844     {
845         msg_Err( p_stream, "cannot find encoder" );
846         return VLC_EGENERIC;
847     }
848
849     id->ff_enc = avcodec_find_encoder( i_ff_codec );
850     if( !id->ff_enc )
851     {
852         msg_Err( p_stream, "cannot find encoder" );
853         return VLC_EGENERIC;
854     }
855
856     id->ff_enc_c = avcodec_alloc_context();
857     id->ff_enc_c->width          = id->f_dst.i_width;
858     id->ff_enc_c->height         = id->f_dst.i_height;
859     id->ff_enc_c->bit_rate       = id->f_dst.i_bitrate;
860 #if LIBAVCODEC_BUILD >= 4662
861     id->ff_enc_c->frame_rate     = 25 ; /* FIXME as it break mpeg */
862     id->ff_enc_c->frame_rate_base= 1;
863 #else
864     id->ff_enc_c->frame_rate     = 25 * FRAME_RATE_BASE;
865 #endif
866     id->ff_enc_c->gop_size       = 25;
867     id->ff_enc_c->qmin           = 2;
868     id->ff_enc_c->qmax           = 31;
869
870     if( i_ff_codec == CODEC_ID_RAWVIDEO )
871     {
872         id->ff_enc_c->pix_fmt = get_ff_chroma( id->f_dst.i_fourcc );
873     }
874     /* XXX open it only when we have the first frame */
875     id->b_enc_inited     = VLC_FALSE;
876     id->i_buffer_in      = 0;
877     id->i_buffer_in_pos  = 0;
878     id->p_buffer_in      = NULL;
879
880     id->i_buffer     = 3*1024*1024;
881     id->i_buffer_pos = 0;
882     id->p_buffer     = malloc( id->i_buffer );
883
884     id->i_buffer_out     = 0;
885     id->i_buffer_out_pos = 0;
886     id->p_buffer_out     = NULL;
887
888     id->p_ff_pic         = avcodec_alloc_frame();
889     id->p_ff_pic_tmp0    = NULL;
890     id->p_ff_pic_tmp1    = NULL;
891     id->p_ff_pic_tmp2    = NULL;
892     id->p_vresample      = NULL;
893     return VLC_SUCCESS;
894 }
895
896 static void transcode_video_ffmpeg_close ( sout_stream_t *p_stream, sout_stream_id_t *id )
897 {
898     if( id->ff_dec )
899     {
900         avcodec_close( id->ff_dec_c );
901     }
902     if( id->b_enc_inited )
903     {
904         avcodec_close( id->ff_enc_c );
905     }
906
907     if( id->p_ff_pic)
908     {
909         free( id->p_ff_pic );
910     }
911
912     if( id->p_ff_pic_tmp0 )
913     {
914         free( id->p_ff_pic_tmp0->data[0] );
915         free( id->p_ff_pic_tmp0 );
916     }
917     if( id->p_ff_pic_tmp1)
918     {
919         free( id->p_ff_pic_tmp1->data[0] );
920         free( id->p_ff_pic_tmp1 );
921     }
922     if( id->p_ff_pic_tmp2)
923     {
924         free( id->p_ff_pic_tmp2->data[0] );
925         free( id->p_ff_pic_tmp2 );
926     }
927     if( id->p_vresample )
928     {
929         free( id->p_vresample );
930     }
931
932     free( id->ff_dec_c );
933     free( id->ff_enc_c );
934
935     free( id->p_buffer );
936 }
937
938 static int transcode_video_ffmpeg_process( sout_stream_t *p_stream, sout_stream_id_t *id,
939                                            sout_buffer_t *in, sout_buffer_t **out )
940 {
941     int     i_used;
942     int     i_out;
943     int     b_gotpicture;
944     AVFrame *frame;
945
946     int     i_data;
947     uint8_t *p_data;
948
949     *out = NULL;
950
951     i_data = in->i_size;
952     p_data = in->p_buffer;
953
954     for( ;; )
955     {
956         /* decode frame */
957         frame = id->p_ff_pic;
958         if( id->ff_dec )
959         {
960             i_used = avcodec_decode_video( id->ff_dec_c, frame,
961                                            &b_gotpicture,
962                                            p_data, i_data );
963         }
964         else
965         {
966             /* raw video */
967             avpicture_fill( (AVPicture*)frame,
968                             p_data,
969                             id->ff_dec_c->pix_fmt,
970                             id->ff_dec_c->width, id->ff_dec_c->height );
971             i_used = i_data;
972             b_gotpicture = 1;
973         }
974
975         if( i_used < 0 )
976         {
977             msg_Warn( p_stream, "error");
978             return VLC_EGENERIC;
979         }
980         i_data -= i_used;
981         p_data += i_used;
982
983         if( !b_gotpicture )
984         {
985             return VLC_SUCCESS;
986         }
987
988         if( !id->b_enc_inited )
989         {
990             /* XXX hack because of copy packetizer and mpeg4video that can failed
991                detecting size */
992             if( id->ff_enc_c->width <= 0 || id->ff_enc_c->height <= 0 )
993             {
994                 id->ff_enc_c->width  = id->f_dst.i_width  = id->ff_dec_c->width;
995                 id->ff_enc_c->height = id->f_dst.i_height = id->ff_dec_c->height;
996             }
997
998             if( avcodec_open( id->ff_enc_c, id->ff_enc ) )
999             {
1000                 msg_Err( p_stream, "cannot open encoder" );
1001                 return VLC_EGENERIC;
1002             }
1003
1004             if( !( id->id = p_stream->p_sys->p_out->pf_add( p_stream->p_sys->p_out, &id->f_dst ) ) )
1005             {
1006                 msg_Err( p_stream, "cannot add this stream" );
1007                 transcode_video_ffmpeg_close( p_stream, id );
1008                 id->b_transcode = VLC_FALSE;
1009                 return VLC_EGENERIC;
1010             }
1011             id->b_enc_inited = VLC_TRUE;
1012         }
1013
1014
1015         /* deinterlace */
1016         if( p_stream->p_sys->b_deinterlace )
1017         {
1018             if( id->p_ff_pic_tmp0 == NULL )
1019             {
1020                 int     i_size;
1021                 uint8_t *buf;
1022                 id->p_ff_pic_tmp0 = avcodec_alloc_frame();
1023                 i_size = avpicture_get_size( id->ff_dec_c->pix_fmt,
1024                                              id->ff_dec_c->width, id->ff_dec_c->height );
1025
1026                 buf = malloc( i_size );
1027
1028                 avpicture_fill( (AVPicture*)id->p_ff_pic_tmp0, buf,
1029                                 id->ff_enc_c->pix_fmt,
1030                                 id->ff_dec_c->width, id->ff_dec_c->height );
1031             }
1032
1033             avpicture_deinterlace( (AVPicture*)id->p_ff_pic_tmp0, (AVPicture*)frame,
1034                                    id->ff_dec_c->pix_fmt,
1035                                    id->ff_dec_c->width, id->ff_dec_c->height );
1036
1037             frame = id->p_ff_pic_tmp0;
1038         }
1039
1040         /* convert pix format */
1041         if( id->ff_dec_c->pix_fmt != id->ff_enc_c->pix_fmt )
1042         {
1043             if( id->p_ff_pic_tmp1 == NULL )
1044             {
1045                 int     i_size;
1046                 uint8_t *buf;
1047                 id->p_ff_pic_tmp1 = avcodec_alloc_frame();
1048                 i_size = avpicture_get_size( id->ff_enc_c->pix_fmt,
1049                                              id->ff_dec_c->width, id->ff_dec_c->height );
1050
1051                 buf = malloc( i_size );
1052
1053                 avpicture_fill( (AVPicture*)id->p_ff_pic_tmp1, buf,
1054                                 id->ff_enc_c->pix_fmt,
1055                                 id->ff_dec_c->width, id->ff_dec_c->height );
1056             }
1057
1058             img_convert( (AVPicture*)id->p_ff_pic_tmp1, id->ff_enc_c->pix_fmt,
1059                          (AVPicture*)frame,             id->ff_dec_c->pix_fmt,
1060                          id->ff_dec_c->width, id->ff_dec_c->height );
1061
1062             frame = id->p_ff_pic_tmp1;
1063         }
1064
1065         /* convert size and crop */
1066         if( ( id->ff_dec_c->width  != id->ff_enc_c->width ) ||
1067             ( id->ff_dec_c->height != id->ff_enc_c->height ) )
1068         {
1069             if( id->p_ff_pic_tmp2 == NULL )
1070             {
1071                 int     i_size;
1072                 uint8_t *buf;
1073                 id->p_ff_pic_tmp2 = avcodec_alloc_frame();
1074                 i_size = avpicture_get_size( id->ff_enc_c->pix_fmt,
1075                                              id->ff_enc_c->width, id->ff_enc_c->height );
1076
1077                 buf = malloc( i_size );
1078
1079                 avpicture_fill( (AVPicture*)id->p_ff_pic_tmp2, buf,
1080                                 id->ff_enc_c->pix_fmt,
1081                                 id->ff_enc_c->width, id->ff_enc_c->height );
1082
1083                 id->p_vresample =
1084                     img_resample_full_init( id->ff_enc_c->width, id->ff_enc_c->height,
1085                                             id->ff_dec_c->width, id->ff_dec_c->height,
1086                                             p_stream->p_sys->i_crop_top,
1087                                             p_stream->p_sys->i_crop_bottom,
1088                                             p_stream->p_sys->i_crop_left,
1089                                             p_stream->p_sys->i_crop_right );
1090             }
1091
1092             img_resample( id->p_vresample, (AVPicture*)id->p_ff_pic_tmp2, (AVPicture*)frame );
1093
1094             frame = id->p_ff_pic_tmp2;
1095         }
1096
1097         i_out = avcodec_encode_video( id->ff_enc_c, id->p_buffer, id->i_buffer, frame );
1098         if( i_out > 0 )
1099         {
1100             sout_buffer_t *p_out;
1101             p_out = sout_BufferNew( p_stream->p_sout, i_out );
1102
1103             memcpy( p_out->p_buffer, id->p_buffer, i_out );
1104
1105             p_out->i_size   = i_out;
1106             p_out->i_length = in->i_length;
1107             p_out->i_dts    = in->i_dts;
1108             p_out->i_pts    = in->i_dts; /* FIXME */
1109
1110             sout_BufferChain( out, p_out );
1111         }
1112
1113         if( i_data <= 0 )
1114         {
1115             return VLC_SUCCESS;
1116         }
1117     }
1118
1119     return VLC_SUCCESS;
1120 }
1121