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