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