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