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