* cinepak: add a new fourcc
[vlc.git] / plugins / ffmpeg / ffmpeg.c
1 /*****************************************************************************
2  * ffmpeg.c: video decoder using ffmpeg library
3  *****************************************************************************
4  * Copyright (C) 1999-2001 VideoLAN
5  * $Id: ffmpeg.c,v 1.20 2002/07/23 17:19:02 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>                                      /* malloc(), free() */
28
29 #include <vlc/vlc.h>
30 #include <vlc/vout.h>
31 #include <vlc/decoder.h>
32 #include <vlc/input.h>
33
34 #ifdef HAVE_UNISTD_H
35 #include <unistd.h>                                              /* getpid() */
36 #endif
37
38 #include <errno.h>
39 #include <string.h>
40
41 #ifdef HAVE_SYS_TIMES_H
42 #   include <sys/times.h>
43 #endif
44
45 #include "vdec_ext-plugins.h"
46 #include "avcodec.h"                                            /* ffmpeg */
47 #include "ffmpeg.h"
48
49 /*
50  * Local prototypes
51  */
52 static int      decoder_Probe   ( vlc_fourcc_t * );
53 static int      decoder_Run     ( decoder_fifo_t * );
54 static int      InitThread      ( videodec_thread_t * );
55 static void     EndThread       ( videodec_thread_t * );
56 static void     DecodeThread    ( videodec_thread_t * );
57
58
59 static int      b_ffmpeginit = 0;
60
61 /*****************************************************************************
62  * Capabilities
63  *****************************************************************************/
64 void _M( vdec_getfunctions )( function_list_t * p_function_list )
65 {
66     p_function_list->functions.dec.pf_probe = decoder_Probe;
67     p_function_list->functions.dec.pf_run   = decoder_Run;
68 }
69
70 /*****************************************************************************
71  * Build configuration tree.
72  *****************************************************************************/
73
74 #define ERROR_RESILIENCE_LONGTEXT \
75     "ffmpeg can make errors resiliences.          \n"\
76     "Nevertheless, with buggy encoder (like ISO MPEG-4 encoder from M$) " \
77     "this will produce a lot of errors.\n" \
78     "Valid range is -1 to 99 (-1 disable all errors resiliences)."
79
80 #define HURRY_UP_LONGTEXT \
81     "Allow the decoder to partially decode or skip frame(s) " \
82     "when there not enough time.\n It's usefull with low CPU power " \
83     "but it could produce broken pictures."
84     
85 MODULE_CONFIG_START
86 ADD_CATEGORY_HINT( N_("Miscellaneous"), NULL )
87 #if LIBAVCODEC_BUILD >= 4611
88   ADD_INTEGER ( "ffmpeg-error-resilience", 0, NULL, 
89                 "error resilience", ERROR_RESILIENCE_LONGTEXT )
90   ADD_INTEGER ( "ffmpeg-workaround-bugs", 0, NULL, 
91                 "workaround bugs", "0-99, seems to be for msmpeg v3\n"  )
92 #endif
93   ADD_BOOL( "ffmpeg-hurry-up", 0, NULL, "hurry up", HURRY_UP_LONGTEXT ) 
94
95 MODULE_CONFIG_STOP
96
97 MODULE_INIT_START
98     SET_DESCRIPTION( "ffmpeg video decoder((MS)MPEG4,SVQ1,H263)" )
99     ADD_CAPABILITY( DECODER, 70 )
100 MODULE_INIT_STOP
101
102 MODULE_ACTIVATE_START
103     _M( vdec_getfunctions )( &p_module->p_functions->dec );
104 MODULE_ACTIVATE_STOP
105
106 MODULE_DEACTIVATE_START
107 MODULE_DEACTIVATE_STOP
108
109
110 /*****************************************************************************
111  * decoder_Probe: probe the decoder and return score
112  *****************************************************************************
113  * Tries to launch a decoder and return score so that the interface is able 
114  * to chose.
115  *****************************************************************************/
116 static int decoder_Probe( vlc_fourcc_t *pi_type )
117 {
118     return( ffmpeg_GetFfmpegCodec( *pi_type, NULL, NULL ) ? 0 : -1 );
119 }
120
121 /*****************************************************************************
122  * decoder_Run: this function is called just after the thread is created
123  *****************************************************************************/
124 static int decoder_Run ( decoder_fifo_t * p_fifo )
125 {
126     videodec_thread_t   *p_vdec;
127     int b_error;
128     
129     if ( !(p_vdec = (videodec_thread_t*)malloc( sizeof(videodec_thread_t))) )
130     {
131         msg_Err( p_fifo, "out of memory" );
132         DecoderError( p_fifo );
133         return( -1 );
134     }
135     memset( p_vdec, 0, sizeof( videodec_thread_t ) );
136
137     p_vdec->p_fifo = p_fifo;
138
139     if( InitThread( p_vdec ) != 0 )
140     {
141         DecoderError( p_fifo );
142         return( -1 );
143     }
144      
145     while( (!p_vdec->p_fifo->b_die) && (!p_vdec->p_fifo->b_error) )
146     {
147         DecodeThread( p_vdec );
148     }
149
150     if( ( b_error = p_vdec->p_fifo->b_error ) )
151     {
152         DecoderError( p_vdec->p_fifo );
153     }
154
155     EndThread( p_vdec );
156
157     if( b_error )
158     {
159         return( -1 );
160     }
161    
162     return( 0 );
163
164
165
166 /*****************************************************************************
167  * locales Functions
168  *****************************************************************************/
169
170 #define GetWLE( p ) \
171     ( *(u8*)(p) + ( *((u8*)(p)+1) << 8 ) )
172
173 #define GetDWLE( p ) \
174     (  *(u8*)(p) + ( *((u8*)(p)+1) << 8 ) + \
175       ( *((u8*)(p)+2) << 16 ) + ( *((u8*)(p)+3) << 24 ) )
176
177 static void ffmpeg_ParseBitMapInfoHeader( bitmapinfoheader_t *p_bh, 
178                                           u8 *p_data )
179 {
180     p_bh->i_size          = GetDWLE( p_data );
181     p_bh->i_width         = GetDWLE( p_data + 4 );
182     p_bh->i_height        = GetDWLE( p_data + 8 );
183     p_bh->i_planes        = GetWLE( p_data + 12 );
184     p_bh->i_bitcount      = GetWLE( p_data + 14 );
185     p_bh->i_compression   = GetDWLE( p_data + 16 );
186     p_bh->i_sizeimage     = GetDWLE( p_data + 20 );
187     p_bh->i_xpelspermeter = GetDWLE( p_data + 24 );
188     p_bh->i_ypelspermeter = GetDWLE( p_data + 28 );
189     p_bh->i_clrused       = GetDWLE( p_data + 32 );
190     p_bh->i_clrimportant  = GetDWLE( p_data + 36 );
191
192     if( p_bh->i_size > 40 )
193     {
194         p_bh->i_data = p_bh->i_size - 40;
195         p_bh->p_data = malloc( p_bh->i_data ); 
196         memcpy( p_bh->p_data, p_data + 40, p_bh->i_data );
197     }
198     else
199     {
200         p_bh->i_data = 0;
201         p_bh->p_data = NULL;
202     } 
203
204 }
205 /* get the first pes from fifo */
206 static pes_packet_t *__PES_GET( decoder_fifo_t *p_fifo )
207 {
208     pes_packet_t *p_pes;
209
210     vlc_mutex_lock( &p_fifo->data_lock );
211
212     /* if fifo is emty wait */
213     while( !p_fifo->p_first )
214     {
215         if( p_fifo->b_die )
216         {
217             vlc_mutex_unlock( &p_fifo->data_lock );
218             return( NULL );
219         }
220         vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
221     }
222     p_pes = p_fifo->p_first;
223
224     vlc_mutex_unlock( &p_fifo->data_lock );
225
226     return( p_pes );
227 }
228
229 /* free the first pes and go to next */
230 static void __PES_NEXT( decoder_fifo_t *p_fifo )
231 {
232     pes_packet_t *p_next;
233
234     vlc_mutex_lock( &p_fifo->data_lock );
235     
236     p_next = p_fifo->p_first->p_next;
237     p_fifo->p_first->p_next = NULL;
238     input_DeletePES( p_fifo->p_packets_mgt, p_fifo->p_first );
239     p_fifo->p_first = p_next;
240     p_fifo->i_depth--;
241
242     if( !p_fifo->p_first )
243     {
244         /* No PES in the fifo */
245         /* pp_last no longer valid */
246         p_fifo->pp_last = &p_fifo->p_first;
247         while( !p_fifo->p_first )
248         {
249             vlc_cond_signal( &p_fifo->data_wait );
250             vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
251         }
252     }
253     vlc_mutex_unlock( &p_fifo->data_lock );
254 }
255
256 static inline void __GetFrame( videodec_thread_t *p_vdec )
257 {
258     pes_packet_t  *p_pes;
259     data_packet_t *p_data;
260     byte_t        *p_buffer;
261
262     p_pes = __PES_GET( p_vdec->p_fifo );
263     p_vdec->i_pts = p_pes->i_pts;
264
265     while( ( !p_pes->i_nb_data )||( !p_pes->i_pes_size ) )
266     {
267         __PES_NEXT( p_vdec->p_fifo );
268         p_pes = __PES_GET( p_vdec->p_fifo );
269     }
270     p_vdec->i_framesize = p_pes->i_pes_size;
271     if( p_pes->i_nb_data == 1 )
272     {
273         p_vdec->p_framedata = p_pes->p_first->p_payload_start;
274         return;    
275     }
276     /* get a buffer and gather all data packet */
277     p_vdec->p_framedata = p_buffer = malloc( p_pes->i_pes_size );
278     p_data = p_pes->p_first;
279     do
280     {
281         p_vdec->p_fifo->p_vlc->pf_memcpy( p_buffer, p_data->p_payload_start, 
282                      p_data->p_payload_end - p_data->p_payload_start );
283         p_buffer += p_data->p_payload_end - p_data->p_payload_start;
284         p_data = p_data->p_next;
285     } while( p_data );
286 }
287
288 static inline void __NextFrame( videodec_thread_t *p_vdec )
289 {
290     pes_packet_t  *p_pes;
291
292     p_pes = __PES_GET( p_vdec->p_fifo );
293     if( p_pes->i_nb_data != 1 )
294     {
295         free( p_vdec->p_framedata ); /* FIXME keep this buffer */
296     }
297     __PES_NEXT( p_vdec->p_fifo );
298 }
299
300 /* FIXME FIXME some of them are wrong */
301 static int i_ffmpeg_PixFmtToChroma[] = 
302 {
303 /* PIX_FMT_ANY = -1,PIX_FMT_YUV420P, PIX_FMT_YUV422,
304    PIX_FMT_RGB24, PIX_FMT_BGR24, PIX_FMT_YUV422P, 
305    PIX_FMT_YUV444P, PIX_FMT_YUV410P */
306
307     0, VLC_FOURCC('I','4','2','0'), VLC_FOURCC('I','4','2','0'), 
308     VLC_FOURCC('R','V','2','4'), 0, VLC_FOURCC('Y','4','2','2'), 
309     VLC_FOURCC('I','4','4','4'), 0 
310 };
311
312 static inline u32 ffmpeg_PixFmtToChroma( int i_ffmpegchroma )
313 {
314     if( ++i_ffmpegchroma > 7 )
315     {
316         return( 0 );
317     }
318     else
319     {
320         return( i_ffmpeg_PixFmtToChroma[i_ffmpegchroma] );
321     }
322 }
323
324 static inline int ffmpeg_FfAspect( int i_width, int i_height, int i_ffaspect )
325 {
326     switch( i_ffaspect )
327     {
328         case( FF_ASPECT_4_3_625 ):
329         case( FF_ASPECT_4_3_525 ):
330             return( VOUT_ASPECT_FACTOR * 4 / 3);
331         case( FF_ASPECT_16_9_625 ):
332         case( FF_ASPECT_16_9_525 ):
333             return( VOUT_ASPECT_FACTOR * 16 / 9 );
334         case( FF_ASPECT_SQUARE ):
335         default:
336             return( VOUT_ASPECT_FACTOR * i_width / i_height );
337     }
338 }
339
340 static int ffmpeg_CheckVout( vout_thread_t *p_vout,
341                              int i_width,
342                              int i_height,
343                              int i_aspect,
344                              int i_chroma )
345 {
346     if( !p_vout )
347     {
348         return( 0 );
349     }
350     if( !i_chroma )
351     {
352         /* we will try to make conversion */
353         i_chroma = VLC_FOURCC('I','4','2','0');
354     } 
355     
356     if( ( p_vout->render.i_width != i_width )||
357         ( p_vout->render.i_height != i_height )||
358         ( p_vout->render.i_chroma != i_chroma )||
359         ( p_vout->render.i_aspect != 
360                 ffmpeg_FfAspect( i_width, i_height, i_aspect ) ) )
361     {
362         return( 0 );
363     }
364     else
365     {
366         return( 1 );
367     }
368 }
369
370 /* Return a Vout */
371
372 static vout_thread_t *ffmpeg_CreateVout( videodec_thread_t *p_vdec,
373                                          int i_width,
374                                          int i_height,
375                                          int i_aspect,
376                                          int i_chroma )
377 {
378     vout_thread_t *p_vout;
379
380     if( (!i_width)||(!i_height) )
381     {
382         return( NULL ); /* Can't create a new vout without display size */
383     }
384
385     if( !i_chroma )
386     {
387         /* we make conversion if possible*/
388         i_chroma = VLC_FOURCC('I','4','2','0');
389         msg_Warn( p_vdec->p_fifo, "Internal chroma conversion (FIXME)");
390         /* It's mainly for I410 -> I420 conversion that I've made,
391            it's buggy and very slow */
392     } 
393
394     i_aspect = ffmpeg_FfAspect( i_width, i_height, i_aspect );
395     
396     /* Spawn a video output if there is none. First we look for our children,
397      * then we look for any other vout that might be available. */
398     p_vout = vlc_object_find( p_vdec->p_fifo, VLC_OBJECT_VOUT,
399                                               FIND_CHILD );
400     if( !p_vout )
401     {
402         p_vout = vlc_object_find( p_vdec->p_fifo, VLC_OBJECT_VOUT,
403                                                   FIND_ANYWHERE );
404     }
405
406     if( p_vout )
407     {
408         if( !ffmpeg_CheckVout( p_vout, 
409                                i_width, i_height, i_aspect,i_chroma ) )
410         {
411             /* We are not interested in this format, close this vout */
412             vlc_object_detach_all( p_vout );
413             vlc_object_release( p_vout );
414             vout_DestroyThread( p_vout );
415             p_vout = NULL;
416         }
417         else
418         {
419             /* This video output is cool! Hijack it. */
420             vlc_object_detach_all( p_vout );
421             vlc_object_attach( p_vout, p_vdec->p_fifo );
422             vlc_object_release( p_vout );
423         }
424     }
425
426     if( p_vout == NULL )
427     {
428         msg_Dbg( p_vdec->p_fifo, "no vout present, spawning one" );
429     
430         p_vout = vout_CreateThread( p_vdec->p_fifo,
431                                     i_width,
432                                     i_height,
433                                     i_chroma,
434                                     i_aspect );
435     }
436
437     return( p_vout );
438 }
439
440 /* FIXME FIXME FIXME this is a big shit
441    does someone want to rewrite this function ? 
442    or said to me how write a better thing
443    FIXME FIXME FIXME
444 */
445
446 static void ffmpeg_ConvertPictureI410toI420( picture_t *p_pic,
447                                              AVPicture *p_avpicture,
448                                              videodec_thread_t   *p_vdec )
449 {
450     u8 *p_src, *p_dst;
451     u8 *p_plane[3];
452     int i_plane;
453     
454     int i_stride, i_lines;
455     int i_height, i_width;
456     int i_y, i_x;
457     
458     i_height = p_vdec->p_context->height;
459     i_width  = p_vdec->p_context->width;
460     
461     p_dst = p_pic->p[0].p_pixels;
462     p_src  = p_avpicture->data[0];
463
464     /* copy first plane */
465     for( i_y = 0; i_y < i_height; i_y++ )
466     {
467         p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, i_width);
468         p_dst += p_pic->p[0].i_pitch;
469         p_src += p_avpicture->linesize[0];
470     }
471     
472     /* process each plane in a temporary buffer */
473     for( i_plane = 1; i_plane < 3; i_plane++ )
474     {
475         i_stride = p_avpicture->linesize[i_plane];
476         i_lines = i_height / 4;
477
478         p_dst = p_plane[i_plane] = malloc( i_lines * i_stride * 2 * 2 );
479         p_src  = p_avpicture->data[i_plane];
480
481         /* for each source line */
482         for( i_y = 0; i_y < i_lines; i_y++ )
483         {
484             for( i_x = 0; i_x < i_stride - 1; i_x++ )
485             {
486                 p_dst[2 * i_x    ] = p_src[i_x];
487                 p_dst[2 * i_x + 1] = ( p_src[i_x] + p_src[i_x + 1]) / 2;
488
489             }
490             p_dst[2 * i_stride - 2] = p_src[i_x];
491             p_dst[2 * i_stride - 1] = p_src[i_x];
492                            
493             p_dst += 4 * i_stride; /* process the next even lines */
494             p_src += i_stride;
495         }
496
497
498     }
499
500     for( i_plane = 1; i_plane < 3; i_plane++ )
501     {
502         i_stride = p_avpicture->linesize[i_plane];
503         i_lines = i_height / 4;
504
505         p_dst = p_plane[i_plane] + 2*i_stride;
506         p_src  = p_plane[i_plane];
507
508         for( i_y = 0; i_y < i_lines - 1; i_y++ )
509         {
510             for( i_x = 0; i_x <  2 * i_stride ; i_x++ )
511             {
512                 p_dst[i_x] = ( p_src[i_x] + p_src[i_x + 4*i_stride])/2;
513             }
514                            
515             p_dst += 4 * i_stride; /* process the next odd lines */
516             p_src += 4 * i_stride;
517         }
518         /* last line */
519         p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, 2*i_stride );
520     }
521     /* copy to p_pic, by block
522        if I do pixel per pixel it segfault. It's why I use 
523        temporaries buffers */
524     for( i_plane = 1; i_plane < 3; i_plane++ )
525     {
526
527         int i_size; 
528         p_src  = p_plane[i_plane];
529         p_dst = p_pic->p[i_plane].p_pixels;
530
531         i_size = __MIN( 2*i_stride, p_pic->p[i_plane].i_pitch);
532         for( i_y = 0; i_y < __MIN(p_pic->p[i_plane].i_lines, 2 * i_lines); i_y++ )
533         {
534             p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, i_size );
535             p_src += 2 * i_stride;
536             p_dst += p_pic->p[i_plane].i_pitch;
537         }
538         free( p_plane[i_plane] );
539     }
540
541 }
542
543 static void ffmpeg_ConvertPicture( picture_t *p_pic,
544                                    AVPicture *p_avpicture,
545                                    videodec_thread_t   *p_vdec )
546 {
547     int i_plane; 
548     int i_size;
549     int i_line;
550
551     u8  *p_dst;
552     u8  *p_src;
553     int i_src_stride;
554     int i_dst_stride;
555     
556     if( ffmpeg_PixFmtToChroma( p_vdec->p_context->pix_fmt ) )
557     {
558         /* convert ffmpeg picture to our format */
559         for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
560         {
561             p_src  = p_avpicture->data[i_plane];
562             p_dst = p_pic->p[i_plane].p_pixels;
563             i_src_stride = p_avpicture->linesize[i_plane];
564             i_dst_stride = p_pic->p[i_plane].i_pitch;
565             
566             i_size = __MIN( i_src_stride, i_dst_stride );
567             for( i_line = 0; i_line < p_pic->p[i_plane].i_lines; i_line++ )
568             {
569                 p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, i_size );
570                 p_src += i_src_stride;
571                 p_dst += i_dst_stride;
572             }
573         }
574         return;
575     }
576
577     /* we need to convert to I420 */
578     switch( p_vdec->p_context->pix_fmt )
579     {
580 #if LIBAVCODEC_BUILD >= 4615
581         case( PIX_FMT_YUV410P ):
582             ffmpeg_ConvertPictureI410toI420( p_pic, p_avpicture, p_vdec );
583             break;
584 #endif            
585         default:
586             p_vdec->p_fifo->b_error =1;
587             break;
588     }
589 }
590
591
592 /*****************************************************************************
593  *
594  * Functions that initialize, decode and end the decoding process
595  *
596  *****************************************************************************/
597
598 /*****************************************************************************
599  * InitThread: initialize vdec output thread
600  *****************************************************************************
601  * This function is called from decoder_Run and performs the second step 
602  * of the initialization. It returns 0 on success. Note that the thread's 
603  * flag are not modified inside this function.
604  *****************************************************************************/
605
606 static int InitThread( videodec_thread_t *p_vdec )
607 {
608     int i_ffmpeg_codec; 
609     int i_tmp;
610     
611     if( p_vdec->p_fifo->p_demux_data )
612     {
613         ffmpeg_ParseBitMapInfoHeader( &p_vdec->format, 
614                                       (u8*)p_vdec->p_fifo->p_demux_data );
615     }
616     else
617     {
618         msg_Warn( p_vdec->p_fifo, "display informations missing" );
619     }
620
621     /*init ffmpeg */
622     if( !b_ffmpeginit )
623     {
624         avcodec_init();
625         avcodec_register_all();
626         b_ffmpeginit = 1;
627         msg_Dbg( p_vdec->p_fifo, "library ffmpeg initialized" );
628     }
629     else
630     {
631         msg_Dbg( p_vdec->p_fifo, "library ffmpeg already initialized" );
632     }
633     ffmpeg_GetFfmpegCodec( p_vdec->p_fifo->i_fourcc,
634                            &i_ffmpeg_codec,
635                            &p_vdec->psz_namecodec );
636     p_vdec->p_codec = 
637         avcodec_find_decoder( i_ffmpeg_codec );
638     
639     if( !p_vdec->p_codec )
640     {
641         msg_Err( p_vdec->p_fifo, "codec not found (%s)",
642                                  p_vdec->psz_namecodec );
643         return( -1 );
644     }
645
646     p_vdec->p_context = &p_vdec->context;
647     memset( p_vdec->p_context, 0, sizeof( AVCodecContext ) );
648
649     p_vdec->p_context->width  = p_vdec->format.i_width;
650     p_vdec->p_context->height = p_vdec->format.i_height;
651     
652 /*  XXX
653     p_vdec->p_context->workaround_bugs 
654       --> seems to be for msmpeg 3 but can't know what is supposed to do
655
656     p_vdec->p_context->strict_std_compliance
657       --> strictly follow mpeg4 standard for decoder or encoder ??
658       
659     p_vdec->p_context->error_resilience
660       --> don't make error resilience, because of some ms encoder witch 
661       use some wrong VLC code.
662 */
663
664 #if LIBAVCODEC_BUILD >= 4611
665     i_tmp = config_GetInt( p_vdec->p_fifo, "ffmpeg-workaround-bugs" );
666     p_vdec->p_context->workaround_bugs  = __MAX( __MIN( i_tmp, 99 ), 0 );
667
668     i_tmp = config_GetInt( p_vdec->p_fifo, "ffmpeg-error-resilience" );
669     p_vdec->p_context->error_resilience = __MAX( __MIN( i_tmp, 99 ), -1 );
670 #endif
671 #if LIBAVCODEC_BUILD >= 4614
672     if( config_GetInt( p_vdec->p_fifo, "grayscale" ) )
673     {
674         p_vdec->p_context->flags|= CODEC_FLAG_GRAY;
675     }
676 #endif
677     
678     if (avcodec_open(p_vdec->p_context, p_vdec->p_codec) < 0)
679     {
680         msg_Err( p_vdec->p_fifo, "cannot open codec (%s)",
681                                  p_vdec->psz_namecodec );
682         return( -1 );
683     }
684     else
685     {
686         msg_Dbg( p_vdec->p_fifo, "ffmpeg codec (%s) started",
687                                  p_vdec->psz_namecodec );
688     }
689     
690     /* first give init data */
691     if( p_vdec->format.i_data )
692     {
693         AVPicture avpicture;
694         int b_gotpicture;
695         
696         switch( i_ffmpeg_codec )
697         {
698             case( CODEC_ID_MPEG4 ):
699                 avcodec_decode_video( p_vdec->p_context, &avpicture, 
700                                       &b_gotpicture,
701                                       p_vdec->format.p_data,
702                                       p_vdec->format.i_data );
703                 break;
704             default:
705                 break;
706         }
707     }
708     
709     /* This will be created after the first decoded frame */
710     p_vdec->p_vout = NULL;
711     
712     return( 0 );
713 }
714
715 /*****************************************************************************
716  * DecodeThread: Called for decode one frame
717  *****************************************************************************/
718 static void  DecodeThread( videodec_thread_t *p_vdec )
719 {
720     int     i_status;
721     int     b_drawpicture;
722     int     b_gotpicture;
723     AVPicture avpicture;  /* ffmpeg picture */
724     picture_t *p_pic; /* videolan picture */
725     /* we have to get a frame stored in a pes 
726        give it to ffmpeg decoder 
727        and send the image to the output */ 
728
729     /* TODO implement it in a better way */
730
731     if( ( config_GetInt(p_vdec->p_fifo, "ffmpeg-hurry-up") )&&
732         ( p_vdec->i_frame_late > 4 ) )
733     {
734 #if LIBAVCODEC_BUILD > 4603
735         b_drawpicture = 0;
736         if( p_vdec->i_frame_late < 8 )
737         {
738             p_vdec->p_context->hurry_up = 2;
739         }
740         else
741         {
742             /* too much late picture, won't decode 
743                but break picture until a new I, and for mpeg4 ...*/
744             p_vdec->i_frame_late--; /* needed else it will never be decrease */
745             __PES_NEXT( p_vdec->p_fifo );
746             return;
747         }
748 #else
749         if( p_vdec->i_frame_late < 8 )
750         {
751             b_drawpicture = 0; /* not really good but .. */
752         }
753         else
754         {
755             /* too much late picture, won't decode 
756                but break picture until a new I, and for mpeg4 ...*/
757             p_vdec->i_frame_late--; /* needed else it will never be decrease */
758             __PES_NEXT( p_vdec->p_fifo );
759             return;
760         }
761 #endif
762     }
763     else
764     {
765         b_drawpicture = 1;
766 #if LIBAVCODEC_BUILD > 4603
767         p_vdec->p_context->hurry_up = 0;
768 #endif
769     }
770
771     __GetFrame( p_vdec );
772
773     i_status = avcodec_decode_video( p_vdec->p_context,
774                                      &avpicture,
775                                      &b_gotpicture,
776                                      p_vdec->p_framedata,
777                                      p_vdec->i_framesize);
778
779     __NextFrame( p_vdec );
780
781     if( i_status < 0 )
782     {
783         msg_Warn( p_vdec->p_fifo, "cannot decode one frame (%d bytes)",
784                                   p_vdec->i_framesize );
785         p_vdec->i_frame_error++;
786         return;
787     }
788     /* Update frame late count*/
789     /* I don't make statistic on decoding time */
790     if( p_vdec->i_pts <= mdate()) 
791     {
792         p_vdec->i_frame_late++;
793     }
794     else
795     {
796         p_vdec->i_frame_late = 0;
797     }
798
799     if( !b_gotpicture || avpicture.linesize[0] == 0 || !b_drawpicture)
800     {
801         return;
802     }
803     
804     /* Check our vout */
805     if( !ffmpeg_CheckVout( p_vdec->p_vout,
806                            p_vdec->p_context->width,
807                            p_vdec->p_context->height,
808                            p_vdec->p_context->aspect_ratio_info,
809                            ffmpeg_PixFmtToChroma(p_vdec->p_context->pix_fmt)) )
810     {
811         p_vdec->p_vout = 
812           ffmpeg_CreateVout( p_vdec,
813                              p_vdec->p_context->width,
814                              p_vdec->p_context->height,
815                              p_vdec->p_context->aspect_ratio_info,
816                              ffmpeg_PixFmtToChroma(p_vdec->p_context->pix_fmt));
817         if( !p_vdec->p_vout )
818         {
819             msg_Err( p_vdec->p_fifo, "cannot create vout" );
820             p_vdec->p_fifo->b_error = 1; /* abort */
821             return;
822         }
823     }
824
825     /* Send decoded frame to vout */
826     while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
827     {
828         if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error )
829         {
830             return;
831         }
832         msleep( VOUT_OUTMEM_SLEEP );
833     }
834     
835     ffmpeg_ConvertPicture( p_pic, 
836                            &avpicture, 
837                            p_vdec );
838     
839
840     /* FIXME correct avi and use i_dts */
841     vout_DatePicture( p_vdec->p_vout, p_pic, p_vdec->i_pts);
842     vout_DisplayPicture( p_vdec->p_vout, p_pic );
843     
844     return;
845 }
846
847
848 /*****************************************************************************
849  * EndThread: thread destruction
850  *****************************************************************************
851  * This function is called when the thread ends after a sucessful
852  * initialization.
853  *****************************************************************************/
854 static void EndThread( videodec_thread_t *p_vdec )
855 {
856     if( !p_vdec )
857     {
858         return;
859     }
860
861     if( p_vdec->p_context != NULL)
862     {
863         avcodec_close( p_vdec->p_context );
864         msg_Dbg( p_vdec->p_fifo, "ffmpeg codec (%s) stopped",
865                                  p_vdec->psz_namecodec );
866     }
867
868     if( p_vdec->p_vout != NULL )
869     {
870         /* We are about to die. Reattach video output to p_vlc. */
871         vlc_object_detach( p_vdec->p_vout, p_vdec->p_fifo );
872         vlc_object_attach( p_vdec->p_vout, p_vdec->p_fifo->p_vlc );
873     }
874
875     if( p_vdec->format.p_data != NULL)
876     {
877         free( p_vdec->format.p_data );
878     }
879     
880     free( p_vdec );
881 }