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