]> git.sesse.net Git - vlc/blob - modules/stream_out/transcode.c
1eeb2235cc53dcbaa80a3c38a6fedb6de0bf6da3
[vlc] / modules / stream_out / transcode.c
1 /*****************************************************************************
2  * transcode.c
3  *****************************************************************************
4  * Copyright (C) 2001, 2002 VideoLAN
5  * $Id: transcode.c,v 1.5 2003/04/29 22:44:08 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
333         /* open output stream */
334         id->id = p_sys->p_out->pf_add( p_sys->p_out, &id->f_dst );
335         id->b_transcode = VLC_TRUE;
336     }
337     else
338     {
339         msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')", (char*)&p_fmt->i_fourcc );
340         id->id = p_sys->p_out->pf_add( p_sys->p_out, p_fmt );
341         id->b_transcode = VLC_FALSE;
342
343         if( id->id == NULL )
344         {
345             free( id );
346             return NULL;
347         }
348     }
349
350     return id;
351 }
352
353 static int     Del      ( sout_stream_t *p_stream, sout_stream_id_t *id )
354 {
355     sout_stream_sys_t   *p_sys = p_stream->p_sys;
356
357     if( id->b_transcode )
358     {
359         if( id->f_src.i_cat == AUDIO_ES )
360         {
361             transcode_audio_ffmpeg_close( p_stream, id );
362         }
363         else if( id->f_src.i_cat == VIDEO_ES )
364         {
365             transcode_video_ffmpeg_close( p_stream, id );
366         }
367     }
368
369     p_sys->p_out->pf_del( p_sys->p_out, id->id );
370     free( id );
371
372     return VLC_SUCCESS;
373 }
374
375 static int     Send     ( sout_stream_t *p_stream, sout_stream_id_t *id, sout_buffer_t *p_buffer )
376 {
377     sout_stream_sys_t   *p_sys = p_stream->p_sys;
378
379     if( id->b_transcode )
380     {
381         sout_buffer_t *p_buffer_out;
382         if( id->f_src.i_cat == AUDIO_ES )
383         {
384             transcode_audio_ffmpeg_process( p_stream, id, p_buffer, &p_buffer_out );
385         }
386         else if( id->f_src.i_cat == VIDEO_ES )
387         {
388             transcode_video_ffmpeg_process( p_stream, id, p_buffer, &p_buffer_out );
389         }
390         sout_BufferDelete( p_stream->p_sout, p_buffer );
391
392         if( p_buffer_out )
393         {
394             return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_buffer_out );
395         }
396         return VLC_SUCCESS;
397     }
398     else
399     {
400         return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_buffer );
401     }
402 }
403
404 /****************************************************************************
405  * ffmpeg decoder reencocdr part
406  ****************************************************************************/
407
408 static struct
409 {
410     vlc_fourcc_t i_fcc;
411     int          i_ff_codec;
412 } fourcc_to_ff_code[] =
413 {
414     /* audio */
415     { VLC_FOURCC( 'm', 'p', 'g', 'a' ), CODEC_ID_MP2 },
416     { VLC_FOURCC( 'a', '5', '2', ' ' ), CODEC_ID_AC3 },
417     { VLC_FOURCC( 'a', 'c', '3', ' ' ), CODEC_ID_AC3 },
418     { VLC_FOURCC( 'w', 'm', 'a', '1' ), CODEC_ID_WMAV1 },
419     { VLC_FOURCC( 'w', 'm', 'a', '2' ), CODEC_ID_WMAV2 },
420
421     /* video */
422     { VLC_FOURCC( 'm', 'p', '4', 'v'),  CODEC_ID_MPEG4 },
423     { VLC_FOURCC( 'm', 'p', 'g', 'v' ), CODEC_ID_MPEG1VIDEO },
424     { VLC_FOURCC( 'D', 'I', 'V', '1' ), CODEC_ID_MSMPEG4V1 },
425     { VLC_FOURCC( 'D', 'I', 'V', '2' ), CODEC_ID_MSMPEG4V2 },
426     { VLC_FOURCC( 'D', 'I', 'V', '3' ), CODEC_ID_MSMPEG4V3 },
427     { VLC_FOURCC( 'H', '2', '6', '3' ), CODEC_ID_H263 },
428     { VLC_FOURCC( 'I', '2', '6', '3' ), CODEC_ID_H263I },
429     { VLC_FOURCC( 'W', 'M', 'V', '1' ), CODEC_ID_WMV1 },
430     { VLC_FOURCC( 'W', 'M', 'V', '2' ), CODEC_ID_WMV2 },
431     { VLC_FOURCC( 'M', 'J', 'P', 'G' ), CODEC_ID_MJPEG },
432     { VLC_FOURCC( 'm', 'j', 'p', 'b' ), CODEC_ID_MJPEGB },
433     { VLC_FOURCC( 'd', 'v', 's', 'l' ), CODEC_ID_DVVIDEO },
434     { VLC_FOURCC( 'S', 'V', 'Q', '1' ), CODEC_ID_SVQ1 },
435
436     { VLC_FOURCC(   0,   0,   0,   0 ), 0 }
437 };
438
439 static inline int get_ff_codec( vlc_fourcc_t i_fcc )
440 {
441     int i;
442
443     for( i = 0; fourcc_to_ff_code[i].i_fcc != 0; i++ )
444     {
445         if( fourcc_to_ff_code[i].i_fcc == i_fcc )
446         {
447             return fourcc_to_ff_code[i].i_ff_codec;
448         }
449     }
450
451     return 0;
452 }
453
454 static int transcode_audio_ffmpeg_new   ( sout_stream_t *p_stream, sout_stream_id_t *id )
455 {
456     int i_ff_codec;
457
458     /* find decoder */
459
460     i_ff_codec = get_ff_codec( id->f_src.i_fourcc );
461     if( i_ff_codec == 0 )
462     {
463         msg_Err( p_stream, "cannot find decoder" );
464         return VLC_EGENERIC;
465     }
466
467     id->ff_dec = avcodec_find_decoder( i_ff_codec );
468     if( !id->ff_dec )
469     {
470         msg_Err( p_stream, "cannot find decoder" );
471         return VLC_EGENERIC;
472     }
473
474     id->ff_dec_c = avcodec_alloc_context();
475     id->ff_dec_c->sample_rate = id->f_src.i_sample_rate;
476     id->ff_dec_c->channels    = id->f_src.i_channels;
477     id->ff_dec_c->block_align = id->f_src.i_block_align;
478     id->ff_dec_c->bit_rate    = id->f_src.i_bitrate;
479
480     id->ff_dec_c->extradata_size = id->f_src.i_extra_data;
481     id->ff_dec_c->extradata      = id->f_src.p_extra_data;
482     if( avcodec_open( id->ff_dec_c, id->ff_dec ) )
483     {
484         msg_Err( p_stream, "cannot open decoder" );
485         return VLC_EGENERIC;
486     }
487
488     /* find encoder */
489     i_ff_codec = get_ff_codec( id->f_dst.i_fourcc );
490     if( i_ff_codec == 0 )
491     {
492         msg_Err( p_stream, "cannot find encoder" );
493         return VLC_EGENERIC;
494     }
495
496     id->ff_enc = avcodec_find_encoder( i_ff_codec );
497     if( !id->ff_enc )
498     {
499         msg_Err( p_stream, "cannot find encoder" );
500         return VLC_EGENERIC;
501     }
502
503     id->ff_enc_c = avcodec_alloc_context();
504     id->ff_enc_c->bit_rate    = id->f_dst.i_bitrate;
505     id->ff_enc_c->sample_rate = id->f_dst.i_sample_rate;
506     id->ff_enc_c->channels    = id->f_dst.i_channels;
507
508     if( avcodec_open( id->ff_enc_c, id->ff_enc ) )
509     {
510         msg_Err( p_stream, "cannot open encoder" );
511         return VLC_EGENERIC;
512     }
513
514
515     id->i_buffer_in      = AVCODEC_MAX_AUDIO_FRAME_SIZE;
516     id->i_buffer_in_pos = 0;
517     id->p_buffer_in      = malloc( id->i_buffer_in );
518
519     id->i_buffer     = AVCODEC_MAX_AUDIO_FRAME_SIZE;
520     id->i_buffer_pos = 0;
521     id->p_buffer     = malloc( id->i_buffer );
522
523     id->i_buffer_out     = AVCODEC_MAX_AUDIO_FRAME_SIZE;
524     id->i_buffer_out_pos = 0;
525     id->p_buffer_out     = malloc( id->i_buffer_out );
526
527     return VLC_SUCCESS;
528 }
529
530 static void transcode_audio_ffmpeg_close ( sout_stream_t *p_stream, sout_stream_id_t *id )
531 {
532     avcodec_close( id->ff_dec_c );
533     avcodec_close( id->ff_enc_c );
534
535     free( id->ff_dec_c );
536     free( id->ff_enc_c );
537
538     free( id->p_buffer );
539 }
540
541 static int transcode_audio_ffmpeg_process( sout_stream_t *p_stream, sout_stream_id_t *id,
542                                            sout_buffer_t *in, sout_buffer_t **out )
543 {
544     *out = NULL;
545
546     /* gather data into p_buffer_in */
547     id->i_dts = in->i_dts -
548                 (mtime_t)1000000 *
549                 (mtime_t)(id->i_buffer_pos / 2 / id->ff_enc_c->channels )/
550                 (mtime_t)id->ff_enc_c->sample_rate;
551
552     memcpy( &id->p_buffer_in[id->i_buffer_in_pos],
553             in->p_buffer,
554             in->i_size );
555     id->i_buffer_in_pos += in->i_size;
556
557     /* decode as many data as possible */
558     for( ;; )
559     {
560         int i_buffer_size;
561         int i_used;
562
563         i_buffer_size = id->i_buffer - id->i_buffer_pos;
564
565         i_used = avcodec_decode_audio( id->ff_dec_c,
566                                        (int16_t*)&id->p_buffer[id->i_buffer_pos], &i_buffer_size,
567                                        id->p_buffer_in, id->i_buffer_in_pos );
568
569         /* msg_Warn( p_stream, "avcodec_decode_audio: %d used", i_used ); */
570         id->i_buffer_pos += i_buffer_size;
571
572         if( i_used < 0 )
573         {
574             msg_Warn( p_stream, "error");
575             id->i_buffer_in_pos = 0;
576             break;
577         }
578         else if( i_used < id->i_buffer_in_pos )
579         {
580             memmove( id->p_buffer_in,
581                      &id->p_buffer_in[i_used],
582                      id->i_buffer_in - i_used );
583             id->i_buffer_in_pos -= i_used;
584         }
585         else
586         {
587             id->i_buffer_in_pos = 0;
588             break;
589         }
590     }
591
592     /* encode as many data as possible */
593     for( ;; )
594     {
595         int i_frame_size = id->ff_enc_c->frame_size * 2 * id->ff_enc_c->channels;
596         int i_out_size;
597         sout_buffer_t *p_out;
598
599         if( id->i_buffer_pos < i_frame_size )
600         {
601             break;
602         }
603
604         /* msg_Warn( p_stream, "avcodec_encode_audio: frame size%d", i_frame_size); */
605         i_out_size = avcodec_encode_audio( id->ff_enc_c,
606                                            id->p_buffer_out, id->i_buffer_out,
607                                            (int16_t*)id->p_buffer );
608
609         if( i_out_size <= 0 )
610         {
611             break;
612         }
613         memmove( id->p_buffer,
614                  &id->p_buffer[i_frame_size],
615                  id->i_buffer - i_frame_size );
616         id->i_buffer_pos -= i_frame_size;
617
618         p_out = sout_BufferNew( p_stream->p_sout, i_out_size );
619         memcpy( p_out->p_buffer, id->p_buffer_out, i_out_size );
620         p_out->i_size = i_out_size;
621         p_out->i_length = (mtime_t)1000000 * (mtime_t)id->ff_enc_c->frame_size / (mtime_t)id->ff_enc_c->sample_rate;
622         /* FIXME */
623         p_out->i_dts = id->i_dts;
624         p_out->i_pts = id->i_dts;
625
626         /* update dts */
627         id->i_dts += p_out->i_length;
628
629        /* msg_Warn( p_stream, "frame dts=%lld len %lld out=%d", p_out->i_dts, p_out->i_length, i_out_size ); */
630         sout_BufferChain( out, p_out );
631     }
632
633     return VLC_SUCCESS;
634 }
635
636
637 /*
638  * video
639  */
640 static int transcode_video_ffmpeg_new   ( sout_stream_t *p_stream, sout_stream_id_t *id )
641 {
642     int i_ff_codec;
643
644     /* find decoder */
645     i_ff_codec = get_ff_codec( id->f_src.i_fourcc );
646     if( i_ff_codec == 0 )
647     {
648         msg_Err( p_stream, "cannot find decoder" );
649         return VLC_EGENERIC;
650     }
651
652     id->ff_dec = avcodec_find_decoder( i_ff_codec );
653     if( !id->ff_dec )
654     {
655         msg_Err( p_stream, "cannot find decoder" );
656         return VLC_EGENERIC;
657     }
658
659     id->ff_dec_c = avcodec_alloc_context();
660     id->ff_dec_c->width         = id->f_src.i_width;
661     id->ff_dec_c->height        = id->f_src.i_height;
662     /* id->ff_dec_c->bit_rate      = id->f_src.i_bitrate; */
663     id->ff_dec_c->extradata_size= id->f_src.i_extra_data;
664     id->ff_dec_c->extradata     = id->f_src.p_extra_data;
665     id->ff_dec_c->workaround_bugs = FF_BUG_AUTODETECT;
666     id->ff_dec_c->error_resilience= -1;
667     if( id->ff_dec->capabilities & CODEC_CAP_TRUNCATED )
668     {
669         id->ff_dec_c->flags |= CODEC_FLAG_TRUNCATED;
670     }
671
672     if( avcodec_open( id->ff_dec_c, id->ff_dec ) < 0 )
673     {
674         msg_Err( p_stream, "cannot open decoder" );
675         return VLC_EGENERIC;
676     }
677 #if 1
678     if( i_ff_codec == CODEC_ID_MPEG4 && id->ff_dec_c->extradata_size > 0 )
679     {
680         int b_gotpicture;
681         AVFrame frame;
682
683         avcodec_decode_video( id->ff_dec_c, &frame,
684                               &b_gotpicture,
685                               id->ff_dec_c->extradata, id->ff_dec_c->extradata_size );
686     }
687 #endif
688
689     /* find encoder */
690     i_ff_codec = get_ff_codec( id->f_dst.i_fourcc );
691     if( i_ff_codec == 0 )
692     {
693         msg_Err( p_stream, "cannot find encoder" );
694         return VLC_EGENERIC;
695     }
696
697     id->ff_enc = avcodec_find_encoder( i_ff_codec );
698     if( !id->ff_enc )
699     {
700         msg_Err( p_stream, "cannot find encoder" );
701         return VLC_EGENERIC;
702     }
703
704     id->ff_enc_c = avcodec_alloc_context();
705     id->ff_enc_c->width          = id->f_dst.i_width;
706     id->ff_enc_c->height         = id->f_dst.i_height;
707     id->ff_enc_c->bit_rate       = id->f_dst.i_bitrate;
708 #if LIBAVCODEC_BUILD >= 4662
709     id->ff_enc_c->frame_rate     = 25 ; /* FIXME as it break mpeg */
710     id->ff_enc_c->frame_rate_base= 1;
711 #else
712     id->ff_enc_c->frame_rate     = 25 * FRAME_RATE_BASE;
713 #endif
714     id->ff_enc_c->gop_size       = 25;
715     id->ff_enc_c->qmin           = 2;
716     id->ff_enc_c->qmax           = 31;
717 #if 0
718     /* XXX open it when we have the first frame */
719     if( avcodec_open( id->ff_enc_c, id->ff_enc ) )
720     {
721         msg_Err( p_stream, "cannot open encoder" );
722         return VLC_EGENERIC;
723     }
724 #endif
725     id->b_enc_inited     = VLC_FALSE;
726     id->i_buffer_in      = 0;
727     id->i_buffer_in_pos  = 0;
728     id->p_buffer_in      = NULL;
729
730     id->i_buffer     = 3*1024*1024;
731     id->i_buffer_pos = 0;
732     id->p_buffer     = malloc( id->i_buffer );
733
734     id->i_buffer_out     = 0;
735     id->i_buffer_out_pos = 0;
736     id->p_buffer_out     = NULL;
737
738     id->p_ff_pic         = avcodec_alloc_frame();
739     id->p_ff_pic_tmp0    = NULL;
740     id->p_ff_pic_tmp1    = NULL;
741     id->p_ff_pic_tmp2    = NULL;
742     id->p_vresample      = NULL;
743     return VLC_SUCCESS;
744 }
745
746 static void transcode_video_ffmpeg_close ( sout_stream_t *p_stream, sout_stream_id_t *id )
747 {
748     avcodec_close( id->ff_dec_c );
749     if( id->b_enc_inited )
750     {
751         avcodec_close( id->ff_enc_c );
752     }
753
754     if( id->p_ff_pic)
755     {
756         free( id->p_ff_pic );
757     }
758
759     if( id->p_ff_pic_tmp0 )
760     {
761         free( id->p_ff_pic_tmp0->data[0] );
762         free( id->p_ff_pic_tmp0 );
763     }
764     if( id->p_ff_pic_tmp1)
765     {
766         free( id->p_ff_pic_tmp1->data[0] );
767         free( id->p_ff_pic_tmp1 );
768     }
769     if( id->p_ff_pic_tmp2)
770     {
771         free( id->p_ff_pic_tmp2->data[0] );
772         free( id->p_ff_pic_tmp2 );
773     }
774     if( id->p_vresample )
775     {
776         free( id->p_vresample );
777     }
778
779     free( id->ff_dec_c );
780     free( id->ff_enc_c );
781
782     free( id->p_buffer );
783 }
784
785 static int transcode_video_ffmpeg_process( sout_stream_t *p_stream, sout_stream_id_t *id,
786                                            sout_buffer_t *in, sout_buffer_t **out )
787 {
788     int     i_used;
789     int     i_out;
790     int     b_gotpicture;
791     AVFrame *frame;
792
793     int     i_data;
794     uint8_t *p_data;
795
796     *out = NULL;
797
798     i_data = in->i_size;
799     p_data = in->p_buffer;
800
801     for( ;; )
802     {
803         /* decode frame */
804         frame = id->p_ff_pic;
805         i_used = avcodec_decode_video( id->ff_dec_c, frame,
806                                        &b_gotpicture,
807                                        p_data, i_data );
808
809         if( i_used < 0 )
810         {
811             msg_Warn( p_stream, "error");
812             return VLC_EGENERIC;
813         }
814         i_data -= i_used;
815         p_data += i_used;
816
817         if( !b_gotpicture )
818         {
819             return VLC_SUCCESS;
820         }
821
822         if( !id->b_enc_inited )
823         {
824             /* XXX hack because of copy packetizer and mpeg4video that can failed
825                detecting size */
826             if( id->ff_enc_c->width == 0 || id->ff_enc_c->height == 0 )
827             {
828                 id->ff_enc_c->width          = id->ff_dec_c->width;
829                 id->ff_enc_c->height         = id->ff_dec_c->height;
830             }
831
832             if( avcodec_open( id->ff_enc_c, id->ff_enc ) )
833             {
834                 msg_Err( p_stream, "cannot open encoder" );
835                 return VLC_EGENERIC;
836             }
837             id->b_enc_inited = VLC_TRUE;
838         }
839
840
841         /* deinterlace */
842         if( p_stream->p_sys->b_deinterlace )
843         {
844             if( id->p_ff_pic_tmp0 == NULL )
845             {
846                 int     i_size;
847                 uint8_t *buf;
848                 id->p_ff_pic_tmp0 = avcodec_alloc_frame();
849                 i_size = avpicture_get_size( id->ff_dec_c->pix_fmt,
850                                              id->ff_dec_c->width, id->ff_dec_c->height );
851
852                 buf = malloc( i_size );
853
854                 avpicture_fill( (AVPicture*)id->p_ff_pic_tmp0, buf,
855                                 id->ff_enc_c->pix_fmt,
856                                 id->ff_dec_c->width, id->ff_dec_c->height );
857             }
858
859             avpicture_deinterlace( (AVPicture*)id->p_ff_pic_tmp0, (AVPicture*)frame,
860                                    id->ff_dec_c->pix_fmt,
861                                    id->ff_dec_c->width, id->ff_dec_c->height );
862
863             frame = id->p_ff_pic_tmp0;
864         }
865
866         /* convert pix format */
867         if( id->ff_dec_c->pix_fmt != id->ff_enc_c->pix_fmt )
868         {
869             if( id->p_ff_pic_tmp1 == NULL )
870             {
871                 int     i_size;
872                 uint8_t *buf;
873                 id->p_ff_pic_tmp1 = avcodec_alloc_frame();
874                 i_size = avpicture_get_size( id->ff_enc_c->pix_fmt,
875                                              id->ff_dec_c->width, id->ff_dec_c->height );
876
877                 buf = malloc( i_size );
878
879                 avpicture_fill( (AVPicture*)id->p_ff_pic_tmp1, buf,
880                                 id->ff_enc_c->pix_fmt,
881                                 id->ff_dec_c->width, id->ff_dec_c->height );
882             }
883
884             img_convert( (AVPicture*)id->p_ff_pic_tmp1, id->ff_enc_c->pix_fmt,
885                          (AVPicture*)frame,             id->ff_dec_c->pix_fmt,
886                          id->ff_dec_c->width, id->ff_dec_c->height );
887
888             frame = id->p_ff_pic_tmp1;
889         }
890
891         /* convert size and crop */
892         if( ( id->ff_dec_c->width  != id->ff_enc_c->width ) ||
893             ( id->ff_dec_c->height != id->ff_enc_c->height ) )
894         {
895             if( id->p_ff_pic_tmp2 == NULL )
896             {
897                 int     i_size;
898                 uint8_t *buf;
899                 id->p_ff_pic_tmp2 = avcodec_alloc_frame();
900                 i_size = avpicture_get_size( id->ff_enc_c->pix_fmt,
901                                              id->ff_enc_c->width, id->ff_enc_c->height );
902
903                 buf = malloc( i_size );
904
905                 avpicture_fill( (AVPicture*)id->p_ff_pic_tmp2, buf,
906                                 id->ff_enc_c->pix_fmt,
907                                 id->ff_enc_c->width, id->ff_enc_c->height );
908
909                 id->p_vresample =
910                     img_resample_full_init( id->ff_enc_c->width, id->ff_enc_c->height,
911                                             id->ff_dec_c->width, id->ff_dec_c->height,
912                                             p_stream->p_sys->i_crop_top,
913                                             p_stream->p_sys->i_crop_bottom,
914                                             p_stream->p_sys->i_crop_left,
915                                             p_stream->p_sys->i_crop_right );
916             }
917
918             img_resample( id->p_vresample, (AVPicture*)id->p_ff_pic_tmp2, (AVPicture*)frame );
919
920             frame = id->p_ff_pic_tmp2;
921         }
922
923         /* encode frame */
924         i_out = avcodec_encode_video( id->ff_enc_c, id->p_buffer, id->i_buffer, frame );
925
926         if( i_out > 0 )
927         {
928             sout_buffer_t *p_out;
929             p_out = sout_BufferNew( p_stream->p_sout, i_out );
930
931             memcpy( p_out->p_buffer, id->p_buffer, i_out );
932
933             p_out->i_size   = i_out;
934             p_out->i_length = in->i_length;
935             p_out->i_dts    = in->i_dts;
936             p_out->i_pts    = in->i_dts; /* FIXME */
937
938             sout_BufferChain( out, p_out );
939         }
940
941         if( i_data <= 0 )
942         {
943             return VLC_SUCCESS;
944         }
945     }
946
947     return VLC_SUCCESS;
948 }
949