1ea72b09738e28e3bd9419bb5baf798a23759fd1
[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.19 2002/07/23 00:39:17 sam 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 __ParseBitMapInfoHeader( bitmapinfoheader_t *h, byte_t *p_data )
178 {
179     h->i_size          = GetDWLE( p_data );
180     h->i_width         = GetDWLE( p_data + 4 );
181     h->i_height        = GetDWLE( p_data + 8 );
182     h->i_planes        = GetWLE( p_data + 12 );
183     h->i_bitcount      = GetWLE( p_data + 14 );
184     h->i_compression   = GetDWLE( p_data + 16 );
185     h->i_sizeimage     = GetDWLE( p_data + 20 );
186     h->i_xpelspermeter = GetDWLE( p_data + 24 );
187     h->i_ypelspermeter = GetDWLE( p_data + 28 );
188     h->i_clrused       = GetDWLE( p_data + 32 );
189     h->i_clrimportant  = GetDWLE( p_data + 36 );
190 }
191 /* get the first pes from fifo */
192 static pes_packet_t *__PES_GET( decoder_fifo_t *p_fifo )
193 {
194     pes_packet_t *p_pes;
195
196     vlc_mutex_lock( &p_fifo->data_lock );
197
198     /* if fifo is emty wait */
199     while( !p_fifo->p_first )
200     {
201         if( p_fifo->b_die )
202         {
203             vlc_mutex_unlock( &p_fifo->data_lock );
204             return( NULL );
205         }
206         vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
207     }
208     p_pes = p_fifo->p_first;
209
210     vlc_mutex_unlock( &p_fifo->data_lock );
211
212     return( p_pes );
213 }
214
215 /* free the first pes and go to next */
216 static void __PES_NEXT( decoder_fifo_t *p_fifo )
217 {
218     pes_packet_t *p_next;
219
220     vlc_mutex_lock( &p_fifo->data_lock );
221     
222     p_next = p_fifo->p_first->p_next;
223     p_fifo->p_first->p_next = NULL;
224     input_DeletePES( p_fifo->p_packets_mgt, p_fifo->p_first );
225     p_fifo->p_first = p_next;
226     p_fifo->i_depth--;
227
228     if( !p_fifo->p_first )
229     {
230         /* No PES in the fifo */
231         /* pp_last no longer valid */
232         p_fifo->pp_last = &p_fifo->p_first;
233         while( !p_fifo->p_first )
234         {
235             vlc_cond_signal( &p_fifo->data_wait );
236             vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
237         }
238     }
239     vlc_mutex_unlock( &p_fifo->data_lock );
240 }
241
242 static inline void __GetFrame( videodec_thread_t *p_vdec )
243 {
244     pes_packet_t  *p_pes;
245     data_packet_t *p_data;
246     byte_t        *p_buffer;
247
248     p_pes = __PES_GET( p_vdec->p_fifo );
249     p_vdec->i_pts = p_pes->i_pts;
250
251     while( ( !p_pes->i_nb_data )||( !p_pes->i_pes_size ) )
252     {
253         __PES_NEXT( p_vdec->p_fifo );
254         p_pes = __PES_GET( p_vdec->p_fifo );
255     }
256     p_vdec->i_framesize = p_pes->i_pes_size;
257     if( p_pes->i_nb_data == 1 )
258     {
259         p_vdec->p_framedata = p_pes->p_first->p_payload_start;
260         return;    
261     }
262     /* get a buffer and gather all data packet */
263     p_vdec->p_framedata = p_buffer = malloc( p_pes->i_pes_size );
264     p_data = p_pes->p_first;
265     do
266     {
267         p_vdec->p_fifo->p_vlc->pf_memcpy( p_buffer, p_data->p_payload_start, 
268                      p_data->p_payload_end - p_data->p_payload_start );
269         p_buffer += p_data->p_payload_end - p_data->p_payload_start;
270         p_data = p_data->p_next;
271     } while( p_data );
272 }
273
274 static inline void __NextFrame( videodec_thread_t *p_vdec )
275 {
276     pes_packet_t  *p_pes;
277
278     p_pes = __PES_GET( p_vdec->p_fifo );
279     if( p_pes->i_nb_data != 1 )
280     {
281         free( p_vdec->p_framedata ); /* FIXME keep this buffer */
282     }
283     __PES_NEXT( p_vdec->p_fifo );
284 }
285
286 /* FIXME FIXME some of them are wrong */
287 static int i_ffmpeg_PixFmtToChroma[] = 
288 {
289 /* PIX_FMT_ANY = -1,PIX_FMT_YUV420P, PIX_FMT_YUV422,
290    PIX_FMT_RGB24, PIX_FMT_BGR24, PIX_FMT_YUV422P, 
291    PIX_FMT_YUV444P, PIX_FMT_YUV410P */
292
293     0, VLC_FOURCC('I','4','2','0'), VLC_FOURCC('I','4','2','0'), 
294     VLC_FOURCC('R','V','2','4'), 0, VLC_FOURCC('Y','4','2','2'), 
295     VLC_FOURCC('I','4','4','4'), 0 
296 };
297
298 static inline u32 ffmpeg_PixFmtToChroma( int i_ffmpegchroma )
299 {
300     if( ++i_ffmpegchroma > 7 )
301     {
302         return( 0 );
303     }
304     else
305     {
306         return( i_ffmpeg_PixFmtToChroma[i_ffmpegchroma] );
307     }
308 }
309
310 static inline int ffmpeg_FfAspect( int i_width, int i_height, int i_ffaspect )
311 {
312     switch( i_ffaspect )
313     {
314         case( FF_ASPECT_4_3_625 ):
315         case( FF_ASPECT_4_3_525 ):
316             return( VOUT_ASPECT_FACTOR * 4 / 3);
317         case( FF_ASPECT_16_9_625 ):
318         case( FF_ASPECT_16_9_525 ):
319             return( VOUT_ASPECT_FACTOR * 16 / 9 );
320         case( FF_ASPECT_SQUARE ):
321         default:
322             return( VOUT_ASPECT_FACTOR * i_width / i_height );
323     }
324 }
325
326 static int ffmpeg_CheckVout( vout_thread_t *p_vout,
327                              int i_width,
328                              int i_height,
329                              int i_aspect,
330                              int i_chroma )
331 {
332     if( !p_vout )
333     {
334         return( 0 );
335     }
336     if( !i_chroma )
337     {
338         /* we will try to make conversion */
339         i_chroma = VLC_FOURCC('I','4','2','0');
340     } 
341     
342     if( ( p_vout->render.i_width != i_width )||
343         ( p_vout->render.i_height != i_height )||
344         ( p_vout->render.i_chroma != i_chroma )||
345         ( p_vout->render.i_aspect != 
346                 ffmpeg_FfAspect( i_width, i_height, i_aspect ) ) )
347     {
348         return( 0 );
349     }
350     else
351     {
352         return( 1 );
353     }
354 }
355
356 /* Return a Vout */
357
358 static vout_thread_t *ffmpeg_CreateVout( videodec_thread_t *p_vdec,
359                                          int i_width,
360                                          int i_height,
361                                          int i_aspect,
362                                          int i_chroma )
363 {
364     vout_thread_t *p_vout;
365
366     if( (!i_width)||(!i_height) )
367     {
368         return( NULL ); /* Can't create a new vout without display size */
369     }
370
371     if( !i_chroma )
372     {
373         /* we make conversion if possible*/
374         i_chroma = VLC_FOURCC('I','4','2','0');
375         msg_Warn( p_vdec->p_fifo, "Internal chroma conversion (FIXME)");
376         /* It's mainly for I410 -> I420 conversion that I've made,
377            it's buggy and very slow */
378     } 
379
380     i_aspect = ffmpeg_FfAspect( i_width, i_height, i_aspect );
381     
382     /* Spawn a video output if there is none. First we look for our children,
383      * then we look for any other vout that might be available. */
384     p_vout = vlc_object_find( p_vdec->p_fifo, VLC_OBJECT_VOUT,
385                                               FIND_CHILD );
386     if( !p_vout )
387     {
388         p_vout = vlc_object_find( p_vdec->p_fifo, VLC_OBJECT_VOUT,
389                                                   FIND_ANYWHERE );
390     }
391
392     if( p_vout )
393     {
394         if( !ffmpeg_CheckVout( p_vout, 
395                                i_width, i_height, i_aspect,i_chroma ) )
396         {
397             /* We are not interested in this format, close this vout */
398             vlc_object_detach_all( p_vout );
399             vlc_object_release( p_vout );
400             vout_DestroyThread( p_vout );
401             p_vout = NULL;
402         }
403         else
404         {
405             /* This video output is cool! Hijack it. */
406             vlc_object_detach_all( p_vout );
407             vlc_object_attach( p_vout, p_vdec->p_fifo );
408             vlc_object_release( p_vout );
409         }
410     }
411
412     if( p_vout == NULL )
413     {
414         msg_Dbg( p_vdec->p_fifo, "no vout present, spawning one" );
415     
416         p_vout = vout_CreateThread( p_vdec->p_fifo,
417                                     i_width,
418                                     i_height,
419                                     i_chroma,
420                                     i_aspect );
421     }
422
423     return( p_vout );
424 }
425
426 #if 0
427 /* segfault some^Wevery times*/
428 static void ffmpeg_ConvertPictureI410toI420( picture_t *p_pic,
429                                              AVPicture *p_avpicture,
430                                              videodec_thread_t   *p_vdec )
431 {
432     int i_plane; 
433     
434     int i_x, i_y;
435     int i_x_max, i_y_max;
436
437     int i_width;
438     int i_height; 
439
440     int i_dst_stride;
441     int i_src_stride;
442     
443     u8  *p_dest;
444     u8  *p_src;
445
446     i_width = p_vdec->p_context->width;
447     i_height= p_vdec->p_context->height;
448     
449
450     p_dest = p_pic->p[0].p_pixels;
451     p_src  = p_avpicture->data[0];
452
453     i_src_stride = p_avpicture->linesize[0];
454     i_dst_stride = p_pic->p[0].i_pitch;
455     
456     if( i_src_stride == i_dst_stride )
457     {
458         p_vdec->p_fifo->p_vlc->pf_memcpy( p_dest, p_src, i_src_stride * i_height  );
459     }
460     else
461     {
462         for( i_y = 0; i_y < i_height; i_y++ )
463         {
464             p_vdec->p_fifo->p_vlc->pf_memcpy( p_dest, p_src, i_width );
465             p_dest += i_dst_stride;
466             p_src  += i_src_stride;
467         }
468     }
469
470     for( i_plane = 1; i_plane < 3; i_plane++ )
471     {
472         i_y_max = p_pic->p[i_plane].i_lines;
473         
474         p_src  = p_avpicture->data[i_plane];
475         p_dest = p_pic->p[i_plane].p_pixels;
476         i_dst_stride = p_pic->p[i_plane].i_pitch;
477         i_src_stride = p_avpicture->linesize[i_plane];
478
479         i_x_max = __MIN( i_dst_stride / 2, i_src_stride );
480
481         for( i_y = 0; i_y <( i_y_max + 1 ) / 2 ; i_y++ )
482         {
483             for( i_x = 0; i_x < i_x_max - 1; i_x++ )
484             {
485                 p_dest[2 * i_x    ] = p_src[i_x];
486                 p_dest[2 * i_x + 1] = ( p_src[i_x] + p_src[i_x + 1] ) / 2;
487             }
488             p_dest[2 * i_x_max - 2] = p_src[i_x];
489             p_dest[2 * i_x_max - 1] = p_src[i_x];
490
491             p_dest += 2 * i_dst_stride;
492             p_src  += i_src_stride;
493         }
494         
495         p_src  = p_pic->p[i_plane].p_pixels;
496         p_dest = p_src + i_dst_stride;
497
498         for( i_y = 0; i_y < ( i_y_max + 1 ) / 2 ; i_y++ )
499         {
500             p_vdec->p_fifo->p_vlc->pf_memcpy( p_dest, p_src, i_dst_stride ); 
501             p_dest += 2*i_dst_stride;
502             p_src  += 2*i_dst_stride;
503         }
504
505     }
506 }
507 #endif
508
509 /* FIXME FIXME FIXME this is a big shit
510    does someone want to rewrite this function ? 
511    or said to me how write a better thing
512    FIXME FIXME FIXME
513 */
514
515 static void ffmpeg_ConvertPictureI410toI420( picture_t *p_pic,
516                                              AVPicture *p_avpicture,
517                                              videodec_thread_t   *p_vdec )
518 {
519     u8 *p_src, *p_dst;
520     u8 *p_plane[3];
521     int i_plane;
522     
523     int i_stride, i_lines;
524     int i_height, i_width;
525     int i_y, i_x;
526     
527     i_height = p_vdec->p_context->height;
528     i_width  = p_vdec->p_context->width;
529     
530     p_dst = p_pic->p[0].p_pixels;
531     p_src  = p_avpicture->data[0];
532
533     /* copy first plane */
534     for( i_y = 0; i_y < i_height; i_y++ )
535     {
536         p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, i_width);
537         p_dst += p_pic->p[0].i_pitch;
538         p_src += p_avpicture->linesize[0];
539     }
540     
541     /* process each plane in a temporary buffer */
542     for( i_plane = 1; i_plane < 3; i_plane++ )
543     {
544         i_stride = p_avpicture->linesize[i_plane];
545         i_lines = i_height / 4;
546
547         p_dst = p_plane[i_plane] = malloc( i_lines * i_stride * 2 * 2 );
548         p_src  = p_avpicture->data[i_plane];
549
550         /* for each source line */
551         for( i_y = 0; i_y < i_lines; i_y++ )
552         {
553             for( i_x = 0; i_x < i_stride - 1; i_x++ )
554             {
555                 p_dst[2 * i_x    ] = p_src[i_x];
556                 p_dst[2 * i_x + 1] = ( p_src[i_x] + p_src[i_x + 1]) / 2;
557
558             }
559             p_dst[2 * i_stride - 2] = p_src[i_x];
560             p_dst[2 * i_stride - 1] = p_src[i_x];
561                            
562             p_dst += 4 * i_stride; /* process the next even lines */
563             p_src += i_stride;
564         }
565
566
567     }
568
569     for( i_plane = 1; i_plane < 3; i_plane++ )
570     {
571         i_stride = p_avpicture->linesize[i_plane];
572         i_lines = i_height / 4;
573
574         p_dst = p_plane[i_plane] + 2*i_stride;
575         p_src  = p_plane[i_plane];
576
577         for( i_y = 0; i_y < i_lines - 1; i_y++ )
578         {
579             for( i_x = 0; i_x <  2 * i_stride ; i_x++ )
580             {
581                 p_dst[i_x] = ( p_src[i_x] + p_src[i_x + 4*i_stride])/2;
582             }
583                            
584             p_dst += 4 * i_stride; /* process the next odd lines */
585             p_src += 4 * i_stride;
586         }
587         /* last line */
588         p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, 2*i_stride );
589     }
590     /* copy to p_pic, by block
591        if I do pixel per pixel it segfault. It's why I use 
592        temporaries buffers */
593     for( i_plane = 1; i_plane < 3; i_plane++ )
594     {
595
596         int i_size; 
597         p_src  = p_plane[i_plane];
598         p_dst = p_pic->p[i_plane].p_pixels;
599
600         i_size = __MIN( 2*i_stride, p_pic->p[i_plane].i_pitch);
601         for( i_y = 0; i_y < __MIN(p_pic->p[i_plane].i_lines, 2 * i_lines); i_y++ )
602         {
603             p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, i_size );
604             p_src += 2 * i_stride;
605             p_dst += p_pic->p[i_plane].i_pitch;
606         }
607         free( p_plane[i_plane] );
608     }
609
610 }
611
612 static void ffmpeg_ConvertPicture( picture_t *p_pic,
613                                    AVPicture *p_avpicture,
614                                    videodec_thread_t   *p_vdec )
615 {
616     int i_plane; 
617     int i_size;
618     int i_line;
619
620     u8  *p_dst;
621     u8  *p_src;
622     int i_src_stride;
623     int i_dst_stride;
624     
625     if( ffmpeg_PixFmtToChroma( p_vdec->p_context->pix_fmt ) )
626     {
627         /* convert ffmpeg picture to our format */
628         for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
629         {
630             p_src  = p_avpicture->data[i_plane];
631             p_dst = p_pic->p[i_plane].p_pixels;
632             i_src_stride = p_avpicture->linesize[i_plane];
633             i_dst_stride = p_pic->p[i_plane].i_pitch;
634             
635             i_size = __MIN( i_src_stride, i_dst_stride );
636             for( i_line = 0; i_line < p_pic->p[i_plane].i_lines; i_line++ )
637             {
638                 p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, i_size );
639                 p_src += i_src_stride;
640                 p_dst += i_dst_stride;
641             }
642         }
643         return;
644     }
645
646     /* we need to convert to I420 */
647     switch( p_vdec->p_context->pix_fmt )
648     {
649 #if LIBAVCODEC_BUILD >= 4615
650         case( PIX_FMT_YUV410P ):
651             ffmpeg_ConvertPictureI410toI420( p_pic, p_avpicture, p_vdec );
652             break;
653 #endif            
654         default:
655             p_vdec->p_fifo->b_error =1;
656             break;
657     }
658 }
659
660
661 /*****************************************************************************
662  *
663  * Functions that initialize, decode and end the decoding process
664  *
665  *****************************************************************************/
666
667 /*****************************************************************************
668  * InitThread: initialize vdec output thread
669  *****************************************************************************
670  * This function is called from decoder_Run and performs the second step 
671  * of the initialization. It returns 0 on success. Note that the thread's 
672  * flag are not modified inside this function.
673  *****************************************************************************/
674
675 static int InitThread( videodec_thread_t *p_vdec )
676 {
677     int i_ffmpeg_codec; 
678     int i_tmp;
679     
680     if( p_vdec->p_fifo->p_demux_data )
681     {
682         __ParseBitMapInfoHeader( &p_vdec->format, 
683                                 (byte_t*)p_vdec->p_fifo->p_demux_data );
684     }
685     else
686     {
687         msg_Warn( p_vdec->p_fifo, "display informations missing" );
688     }
689
690     /*init ffmpeg */
691     if( !b_ffmpeginit )
692     {
693         avcodec_init();
694         avcodec_register_all();
695         b_ffmpeginit = 1;
696         msg_Dbg( p_vdec->p_fifo, "library ffmpeg initialized" );
697     }
698     else
699     {
700         msg_Dbg( p_vdec->p_fifo, "library ffmpeg already initialized" );
701     }
702     ffmpeg_GetFfmpegCodec( p_vdec->p_fifo->i_fourcc,
703                            &i_ffmpeg_codec,
704                            &p_vdec->psz_namecodec );
705     p_vdec->p_codec = 
706         avcodec_find_decoder( i_ffmpeg_codec );
707     
708     if( !p_vdec->p_codec )
709     {
710         msg_Err( p_vdec->p_fifo, "codec not found (%s)",
711                                  p_vdec->psz_namecodec );
712         return( -1 );
713     }
714
715     p_vdec->p_context = &p_vdec->context;
716     memset( p_vdec->p_context, 0, sizeof( AVCodecContext ) );
717
718     p_vdec->p_context->width  = p_vdec->format.i_width;
719     p_vdec->p_context->height = p_vdec->format.i_height;
720     
721 /*  XXX
722     p_vdec->p_context->workaround_bugs 
723       --> seems to be for msmpeg 3 but can't know what is supposed to do
724
725     p_vdec->p_context->strict_std_compliance
726       --> strictly follow mpeg4 standard for decoder or encoder ??
727       
728     p_vdec->p_context->error_resilience
729       --> don't make error resilience, because of some ms encoder witch 
730       use some wrong VLC code.
731 */
732
733 #if LIBAVCODEC_BUILD >= 4611
734     i_tmp = config_GetInt( p_vdec->p_fifo, "ffmpeg-workaround-bugs" );
735     p_vdec->p_context->workaround_bugs  = __MAX( __MIN( i_tmp, 99 ), 0 );
736
737     i_tmp = config_GetInt( p_vdec->p_fifo, "ffmpeg-error-resilience" );
738     p_vdec->p_context->error_resilience = __MAX( __MIN( i_tmp, 99 ), -1 );
739 #endif
740 #if LIBAVCODEC_BUILD >= 4614
741     if( config_GetInt( p_vdec->p_fifo, "grayscale" ) )
742     {
743         p_vdec->p_context->flags|= CODEC_FLAG_GRAY;
744     }
745 #endif
746     
747     if (avcodec_open(p_vdec->p_context, p_vdec->p_codec) < 0)
748     {
749         msg_Err( p_vdec->p_fifo, "cannot open codec (%s)",
750                                  p_vdec->psz_namecodec );
751         return( -1 );
752     }
753     else
754     {
755         msg_Dbg( p_vdec->p_fifo, "ffmpeg codec (%s) started",
756                                  p_vdec->psz_namecodec );
757     }
758
759     /* This will be created after the first decoded frame */
760     p_vdec->p_vout = NULL;
761
762     return( 0 );
763 }
764
765 /*****************************************************************************
766  * DecodeThread: Called for decode one frame
767  *****************************************************************************/
768 static void  DecodeThread( videodec_thread_t *p_vdec )
769 {
770     int     i_status;
771     int     b_drawpicture;
772     int     b_gotpicture;
773     AVPicture avpicture;  /* ffmpeg picture */
774     picture_t *p_pic; /* videolan picture */
775     /* we have to get a frame stored in a pes 
776        give it to ffmpeg decoder 
777        and send the image to the output */ 
778
779     /* TODO implement it in a better way */
780
781     if( ( config_GetInt(p_vdec->p_fifo, "ffmpeg-hurry-up") )&&
782         ( p_vdec->i_frame_late > 4 ) )
783     {
784 #if LIBAVCODEC_BUILD > 4603
785         b_drawpicture = 0;
786         if( p_vdec->i_frame_late < 8 )
787         {
788             p_vdec->p_context->hurry_up = 2;
789         }
790         else
791         {
792             /* too much late picture, won't decode 
793                but break picture until a new I, and for mpeg4 ...*/
794             p_vdec->i_frame_late--; /* needed else it will never be decrease */
795             __PES_NEXT( p_vdec->p_fifo );
796             return;
797         }
798 #else
799         if( p_vdec->i_frame_late < 8 )
800         {
801             b_drawpicture = 0; /* not really good but .. */
802         }
803         else
804         {
805             /* too much late picture, won't decode 
806                but break picture until a new I, and for mpeg4 ...*/
807             p_vdec->i_frame_late--; /* needed else it will never be decrease */
808             __PES_NEXT( p_vdec->p_fifo );
809             return;
810         }
811 #endif
812     }
813     else
814     {
815         b_drawpicture = 1;
816 #if LIBAVCODEC_BUILD > 4603
817         p_vdec->p_context->hurry_up = 0;
818 #endif
819     }
820
821     __GetFrame( p_vdec );
822
823     i_status = avcodec_decode_video( p_vdec->p_context,
824                                      &avpicture,
825                                      &b_gotpicture,
826                                      p_vdec->p_framedata,
827                                      p_vdec->i_framesize);
828
829     __NextFrame( p_vdec );
830
831     if( i_status < 0 )
832     {
833         msg_Warn( p_vdec->p_fifo, "cannot decode one frame (%d bytes)",
834                                   p_vdec->i_framesize );
835         p_vdec->i_frame_error++;
836         return;
837     }
838     /* Update frame late count*/
839     /* I don't make statistic on decoding time */
840     if( p_vdec->i_pts <= mdate()) 
841     {
842         p_vdec->i_frame_late++;
843     }
844     else
845     {
846         p_vdec->i_frame_late = 0;
847     }
848
849     if( !b_gotpicture || avpicture.linesize[0] == 0 || !b_drawpicture)
850     {
851         return;
852     }
853     
854     /* Check our vout */
855     if( !ffmpeg_CheckVout( p_vdec->p_vout,
856                            p_vdec->p_context->width,
857                            p_vdec->p_context->height,
858                            p_vdec->p_context->aspect_ratio_info,
859                            ffmpeg_PixFmtToChroma(p_vdec->p_context->pix_fmt)) )
860     {
861         p_vdec->p_vout = 
862           ffmpeg_CreateVout( p_vdec,
863                              p_vdec->p_context->width,
864                              p_vdec->p_context->height,
865                              p_vdec->p_context->aspect_ratio_info,
866                              ffmpeg_PixFmtToChroma(p_vdec->p_context->pix_fmt));
867         if( !p_vdec->p_vout )
868         {
869             msg_Err( p_vdec->p_fifo, "cannot create vout" );
870             p_vdec->p_fifo->b_error = 1; /* abort */
871             return;
872         }
873     }
874
875     /* Send decoded frame to vout */
876     while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
877     {
878         if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error )
879         {
880             return;
881         }
882         msleep( VOUT_OUTMEM_SLEEP );
883     }
884     
885     ffmpeg_ConvertPicture( p_pic, 
886                            &avpicture, 
887                            p_vdec );
888     
889
890     /* FIXME correct avi and use i_dts */
891     vout_DatePicture( p_vdec->p_vout, p_pic, p_vdec->i_pts);
892     vout_DisplayPicture( p_vdec->p_vout, p_pic );
893     
894     return;
895 }
896
897
898 /*****************************************************************************
899  * EndThread: thread destruction
900  *****************************************************************************
901  * This function is called when the thread ends after a sucessful
902  * initialization.
903  *****************************************************************************/
904 static void EndThread( videodec_thread_t *p_vdec )
905 {
906     if( !p_vdec )
907     {
908         return;
909     }
910
911     if( p_vdec->p_context != NULL)
912     {
913         avcodec_close( p_vdec->p_context );
914         msg_Dbg( p_vdec->p_fifo, "ffmpeg codec (%s) stopped",
915                                  p_vdec->psz_namecodec );
916     }
917
918     if( p_vdec->p_vout != NULL )
919     {
920         /* We are about to die. Reattach video output to p_vlc. */
921         vlc_object_detach( p_vdec->p_vout, p_vdec->p_fifo );
922         vlc_object_attach( p_vdec->p_vout, p_vdec->p_fifo->p_vlc );
923     }
924     
925     free( p_vdec );
926 }