* add post processing modules.( As defined in MPEG4 ISO) There are C,
[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.3 2002/08/04 22:13:05 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_("Miscellaneous"), NULL );
90 #if LIBAVCODEC_BUILD >= 4611
91     add_integer ( "ffmpeg-error-resilience", 0, 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_all( 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_all( 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         if( !( p_vout = vout_CreateThread( p_vdec->p_fifo,
435                                          i_width,
436                                          i_height,
437                                          i_chroma,
438                                          i_aspect ) ) )
439         {
440             return( NULL ); /* everythings have failed */
441         }
442     }
443     /* up to now, all this stuff is used for post-processing */
444     
445     return( p_vout );
446 }
447
448 /* FIXME FIXME FIXME this is a big shit
449    does someone want to rewrite this function ? 
450    or said to me how write a better thing
451    FIXME FIXME FIXME
452 */
453 static void ffmpeg_ConvertPictureI410toI420( picture_t *p_pic,
454                                              AVPicture *p_avpicture,
455                                              videodec_thread_t   *p_vdec )
456 {
457     u8 *p_src, *p_dst;
458     u8 *p_plane[3];
459     int i_plane;
460     
461     int i_stride, i_lines;
462     int i_height, i_width;
463     int i_y, i_x;
464     
465     i_height = p_vdec->p_context->height;
466     i_width  = p_vdec->p_context->width;
467     
468     p_dst = p_pic->p[0].p_pixels;
469     p_src  = p_avpicture->data[0];
470
471     /* copy first plane */
472     for( i_y = 0; i_y < i_height; i_y++ )
473     {
474         p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, i_width);
475         p_dst += p_pic->p[0].i_pitch;
476         p_src += p_avpicture->linesize[0];
477     }
478     
479     /* process each plane in a temporary buffer */
480     for( i_plane = 1; i_plane < 3; i_plane++ )
481     {
482         i_stride = p_avpicture->linesize[i_plane];
483         i_lines = i_height / 4;
484
485         p_dst = p_plane[i_plane] = malloc( i_lines * i_stride * 2 * 2 );
486         p_src  = p_avpicture->data[i_plane];
487
488         /* for each source line */
489         for( i_y = 0; i_y < i_lines; i_y++ )
490         {
491             for( i_x = 0; i_x < i_stride - 1; i_x++ )
492             {
493                 p_dst[2 * i_x    ] = p_src[i_x];
494                 p_dst[2 * i_x + 1] = ( p_src[i_x] + p_src[i_x + 1]) / 2;
495
496             }
497             p_dst[2 * i_stride - 2] = p_src[i_x];
498             p_dst[2 * i_stride - 1] = p_src[i_x];
499                            
500             p_dst += 4 * i_stride; /* process the next even lines */
501             p_src += i_stride;
502         }
503
504
505     }
506
507     for( i_plane = 1; i_plane < 3; i_plane++ )
508     {
509         i_stride = p_avpicture->linesize[i_plane];
510         i_lines = i_height / 4;
511
512         p_dst = p_plane[i_plane] + 2*i_stride;
513         p_src  = p_plane[i_plane];
514
515         for( i_y = 0; i_y < i_lines - 1; i_y++ )
516         {
517             for( i_x = 0; i_x <  2 * i_stride ; i_x++ )
518             {
519                 p_dst[i_x] = ( p_src[i_x] + p_src[i_x + 4*i_stride])/2;
520             }
521                            
522             p_dst += 4 * i_stride; /* process the next odd lines */
523             p_src += 4 * i_stride;
524         }
525         /* last line */
526         p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, 2*i_stride );
527     }
528     /* copy to p_pic, by block
529        if I do pixel per pixel it segfault. It's why I use 
530        temporaries buffers */
531     for( i_plane = 1; i_plane < 3; i_plane++ )
532     {
533
534         int i_size; 
535         p_src  = p_plane[i_plane];
536         p_dst = p_pic->p[i_plane].p_pixels;
537
538         i_size = __MIN( 2*i_stride, p_pic->p[i_plane].i_pitch);
539         for( i_y = 0; i_y < __MIN(p_pic->p[i_plane].i_lines, 2 * i_lines); i_y++ )
540         {
541             p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, i_size );
542             p_src += 2 * i_stride;
543             p_dst += p_pic->p[i_plane].i_pitch;
544         }
545         free( p_plane[i_plane] );
546     }
547
548 }
549
550 static void ffmpeg_GetPicture( picture_t *p_pic,
551                                AVPicture *p_avpicture,
552                                videodec_thread_t   *p_vdec )
553 {
554     int i_plane; 
555     int i_size;
556     int i_line;
557
558     u8  *p_dst;
559     u8  *p_src;
560     int i_src_stride;
561     int i_dst_stride;
562
563     if( ffmpeg_PixFmtToChroma( p_vdec->p_context->pix_fmt ) )
564     {
565         for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
566         {
567             p_src  = p_avpicture->data[i_plane];
568             p_dst = p_pic->p[i_plane].p_pixels;
569             i_src_stride = p_avpicture->linesize[i_plane];
570             i_dst_stride = p_pic->p[i_plane].i_pitch;
571             
572             i_size = __MIN( i_src_stride, i_dst_stride );
573             for( i_line = 0; i_line < p_pic->p[i_plane].i_lines; i_line++ )
574             {
575                 p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, i_size );
576                 p_src += i_src_stride;
577                 p_dst += i_dst_stride;
578             }
579         }
580         if( ( p_vdec->i_pp_mode )&&
581             ( ( p_vdec->p_vout->render.i_chroma == 
582                     VLC_FOURCC( 'I','4','2','0' ) )||
583               ( p_vdec->p_vout->render.i_chroma == 
584                     VLC_FOURCC( 'Y','V','1','2' ) ) ) )
585         {
586             /* Make postproc */
587 #if LIBAVCODEC_BUILD > 4313
588             p_vdec->p_pp->pf_postprocess( p_pic,
589                                           p_vdec->p_context->quant_store, 
590                                           p_vdec->p_context->qstride,
591                                           p_vdec->i_pp_mode );
592 #endif
593         }
594     }
595     else
596     {
597         /* we need to convert to I420 */
598         switch( p_vdec->p_context->pix_fmt )
599         {
600 #if LIBAVCODEC_BUILD >= 4615
601             case( PIX_FMT_YUV410P ):
602                 ffmpeg_ConvertPictureI410toI420( p_pic, p_avpicture, p_vdec );
603                 break;
604 #endif            
605             default:
606                 p_vdec->p_fifo->b_error = 1;
607                 break;
608         }
609
610     }
611   
612 }
613
614
615
616 /*****************************************************************************
617  *
618  * Functions that initialize, decode and end the decoding process
619  *
620  *****************************************************************************/
621
622 /*****************************************************************************
623  * InitThread: initialize vdec output thread
624  *****************************************************************************
625  * This function is called from decoder_Run and performs the second step 
626  * of the initialization. It returns 0 on success. Note that the thread's 
627  * flag are not modified inside this function.
628  *
629  * ffmpeg codec will be open, some memory allocated. But Vout is not yet
630  *   open (done after the first decoded frame)
631  *****************************************************************************/
632 static int InitThread( videodec_thread_t *p_vdec )
633 {
634     int i_ffmpeg_codec; 
635     int i_tmp;
636     int i_use_pp;
637     
638     
639     if( p_vdec->p_fifo->p_demux_data )
640     {
641         ffmpeg_ParseBitMapInfoHeader( &p_vdec->format, 
642                                       (u8*)p_vdec->p_fifo->p_demux_data );
643     }
644     else
645     {
646         msg_Warn( p_vdec->p_fifo, "display informations missing" );
647     }
648
649     /* **** init ffmpeg library (libavcodec) ***** */
650     if( !b_ffmpeginit )
651     {
652         avcodec_init();
653         avcodec_register_all();
654         b_ffmpeginit = 1;
655         msg_Dbg( p_vdec->p_fifo, "library ffmpeg initialized" );
656     }
657     else
658     {
659         msg_Dbg( p_vdec->p_fifo, "library ffmpeg already initialized" );
660     }
661
662     /* ***** Search for codec ***** */
663     ffmpeg_GetFfmpegCodec( p_vdec->p_fifo->i_fourcc,
664                            &i_ffmpeg_codec,
665                            &p_vdec->psz_namecodec );
666     p_vdec->p_codec = 
667         avcodec_find_decoder( i_ffmpeg_codec );
668     
669     if( !p_vdec->p_codec )
670     {
671         msg_Err( p_vdec->p_fifo, "codec not found (%s)",
672                                  p_vdec->psz_namecodec );
673         return( -1 );
674     }
675
676     /* ***** Fill p_context with init values ***** */
677     p_vdec->p_context = &p_vdec->context;
678     memset( p_vdec->p_context, 0, sizeof( AVCodecContext ) );
679
680     p_vdec->p_context->width  = p_vdec->format.i_width;
681     p_vdec->p_context->height = p_vdec->format.i_height;
682     
683     /*  ***** Get configuration of ffmpeg plugin ***** */
684 #if LIBAVCODEC_BUILD >= 4611
685     i_tmp = config_GetInt( p_vdec->p_fifo, "ffmpeg-workaround-bugs" );
686     p_vdec->p_context->workaround_bugs  = __MAX( __MIN( i_tmp, 99 ), 0 );
687
688     i_tmp = config_GetInt( p_vdec->p_fifo, "ffmpeg-error-resilience" );
689     p_vdec->p_context->error_resilience = __MAX( __MIN( i_tmp, 99 ), -1 );
690 #endif
691 #if LIBAVCODEC_BUILD >= 4614
692     if( config_GetInt( p_vdec->p_fifo, "grayscale" ) )
693     {
694         p_vdec->p_context->flags|= CODEC_FLAG_GRAY;
695     }
696 #endif
697     p_vdec->b_hurry_up = config_GetInt(p_vdec->p_fifo, "ffmpeg-hurry-up");
698     
699     /* ***** Load for post processing ***** */
700
701     /* get overridden settings */
702     p_vdec->i_pp_mode = 0;
703     if( config_GetInt( p_vdec->p_fifo, "ffmpeg-db-yv" ) )
704         p_vdec->i_pp_mode |= PP_DEBLOCK_Y_V;
705     if( config_GetInt( p_vdec->p_fifo, "ffmpeg-db-yh" ) )
706         p_vdec->i_pp_mode |= PP_DEBLOCK_Y_H;
707     if( config_GetInt( p_vdec->p_fifo, "ffmpeg-db-cv" ) )
708         p_vdec->i_pp_mode |= PP_DEBLOCK_C_V;
709     if( config_GetInt( p_vdec->p_fifo, "ffmpeg-db-ch" ) )
710         p_vdec->i_pp_mode |= PP_DEBLOCK_C_H;
711     if( config_GetInt( p_vdec->p_fifo, "ffmpeg-dr-y" ) )
712         p_vdec->i_pp_mode |= PP_DERING_Y;
713     if( config_GetInt( p_vdec->p_fifo, "ffmpeg-dr-c" ) )
714         p_vdec->i_pp_mode |= PP_DERING_C;
715     
716     if( ( config_GetInt( p_vdec->p_fifo, "ffmpeg-pp-q" ) > 0 )||
717         ( p_vdec->i_pp_mode != 0 ) )
718     {
719         i_use_pp = 1;
720     }
721     else
722     {
723         i_use_pp = 0;
724     }
725
726     if( i_use_pp )
727     {
728         switch( i_ffmpeg_codec )
729         {
730 #if LIBAVCODEC_BUILD > 4608
731             case( CODEC_ID_MSMPEG4V1 ):
732             case( CODEC_ID_MSMPEG4V2 ):
733             case( CODEC_ID_MSMPEG4V3 ):
734 #else
735             case( CODEC_ID_MSMPEG4 ):
736 #endif
737             case( CODEC_ID_MPEG4 ):
738             case( CODEC_ID_H263 ):
739 //            case( CODEC_ID_H263P ): I don't use it up to now
740             case( CODEC_ID_H263I ):
741                 /* Ok we can make postprocessing :)) */
742                 break;
743             default:
744                 p_vdec->i_pp_mode = 0;
745                 i_use_pp = 0;
746                 msg_Warn( p_vdec->p_fifo, 
747                           "Post processing unsupported for this codec" );
748                 break;
749
750         }
751     }
752         
753     if( i_use_pp )
754     {
755 #if LIBAVCODEC_BUILD > 4613
756         char *psz_name;
757
758         /* first try to get a postprocess module */
759         p_vdec->p_pp = vlc_object_create( p_vdec->p_fifo,
760                                           sizeof( postprocessing_t ) );
761         p_vdec->p_pp->psz_object_name = "postprocessing";
762
763         psz_name = config_GetPsz( p_vdec->p_pp, "ffmpeg-pp" );
764         p_vdec->p_pp->p_module = 
765             module_Need( p_vdec->p_pp, "postprocessing", psz_name );
766         FREE( psz_name );
767         if( !p_vdec->p_pp->p_module )
768         {
769             msg_Warn( p_vdec->p_fifo, "no suitable postprocessing module" );
770             vlc_object_destroy( p_vdec->p_pp );
771             p_vdec->p_pp = NULL;
772             p_vdec->i_pp_mode = 0;
773         }
774         else
775         {
776             /* get mode upon quality */
777             p_vdec->i_pp_mode |= 
778                 p_vdec->p_pp->pf_getmode( config_GetInt( p_vdec->p_fifo, 
779                                                          "ffmpeg-pp-q" ),
780                                           config_GetInt( p_vdec->p_fifo,
781                                                          "ffmpeg-pp-auto" ) );
782                     
783             /* allocate table for postprocess */
784             p_vdec->p_context->quant_store = 
785                 malloc( sizeof( int ) * ( MBR + 1 ) * ( MBC + 1 ) );
786             p_vdec->p_context->qstride = MBC + 1;
787         }
788 #else
789         msg_Warn( p_vdec->p_fifo, 
790                   "post-processing not supported, upgrade ffmpeg" );
791         p_vdec->i_pp_mode = 0;
792 #endif
793     }
794     
795     /* ***** Open the codec ***** */ 
796     if (avcodec_open(p_vdec->p_context, p_vdec->p_codec) < 0)
797     {
798         msg_Err( p_vdec->p_fifo, "cannot open codec (%s)",
799                                  p_vdec->psz_namecodec );
800         return( -1 );
801     }
802     else
803     {
804         msg_Dbg( p_vdec->p_fifo, "ffmpeg codec (%s) started",
805                                  p_vdec->psz_namecodec );
806     }
807     
808     /* ***** init this codec with special data(up to now MPEG4 only) ***** */
809     if( p_vdec->format.i_data )
810     {
811         AVPicture avpicture;
812         int b_gotpicture;
813         
814         switch( i_ffmpeg_codec )
815         {
816             case( CODEC_ID_MPEG4 ):
817                 avcodec_decode_video( p_vdec->p_context, &avpicture, 
818                                       &b_gotpicture,
819                                       p_vdec->format.p_data,
820                                       p_vdec->format.i_data );
821                 break;
822             default:
823                 break;
824         }
825     }
826     
827     return( 0 );
828 }
829
830 /*****************************************************************************
831  * DecodeThread: Called for decode one frame
832  *****************************************************************************/
833 static void  DecodeThread( videodec_thread_t *p_vdec )
834 {
835     int     i_status;
836     int     b_drawpicture;
837     int     b_gotpicture;
838     AVPicture avpicture;  /* ffmpeg picture */
839     picture_t *p_pic; /* videolan picture */
840     /* we have to get a frame stored in a pes 
841        give it to ffmpeg decoder 
842        and send the image to the output */ 
843
844     /* TODO implement it in a better way */
845     /* A good idea could be to decode all I pictures and see for the other */
846     if( ( p_vdec->b_hurry_up )&&
847         ( p_vdec->i_frame_late > 4 ) )
848     {
849 #if LIBAVCODEC_BUILD > 4603
850         b_drawpicture = 0;
851         if( p_vdec->i_frame_late < 8 )
852         {
853             p_vdec->p_context->hurry_up = 2;
854         }
855         else
856         {
857             /* too much late picture, won't decode 
858                but break picture until a new I, and for mpeg4 ...*/
859             p_vdec->i_frame_late--; /* needed else it will never be decrease */
860             __PES_NEXT( p_vdec->p_fifo );
861             return;
862         }
863 #else
864         if( p_vdec->i_frame_late < 8 )
865         {
866             b_drawpicture = 0; /* not really good but .. UPGRADE FFMPEG !! */
867         }
868         else
869         {
870             /* too much late picture, won't decode 
871                but break picture until a new I, and for mpeg4 ...*/
872             p_vdec->i_frame_late--; /* needed else it will never be decrease */
873             __PES_NEXT( p_vdec->p_fifo );
874             return;
875         }
876 #endif
877     }
878     else
879     {
880         b_drawpicture = 1;
881 #if LIBAVCODEC_BUILD > 4603
882         p_vdec->p_context->hurry_up = 0;
883 #endif
884     }
885
886     __GetFrame( p_vdec );
887
888     i_status = avcodec_decode_video( p_vdec->p_context,
889                                      &avpicture,
890                                      &b_gotpicture,
891                                      p_vdec->p_framedata,
892                                      p_vdec->i_framesize);
893
894     __NextFrame( p_vdec );
895
896     if( i_status < 0 )
897     {
898         msg_Warn( p_vdec->p_fifo, "cannot decode one frame (%d bytes)",
899                                   p_vdec->i_framesize );
900         p_vdec->i_frame_error++;
901         return;
902     }
903     /* Update frame late count*/
904     /* I don't make statistic on decoding time */
905     if( p_vdec->i_pts <= mdate()) 
906     {
907         p_vdec->i_frame_late++;
908     }
909     else
910     {
911         p_vdec->i_frame_late = 0;
912     }
913
914     if( !b_gotpicture || avpicture.linesize[0] == 0 || !b_drawpicture)
915     {
916         return;
917     }
918     
919     /* Check our vout */
920     if( !ffmpeg_CheckVout( p_vdec->p_vout,
921                            p_vdec->p_context->width,
922                            p_vdec->p_context->height,
923                            p_vdec->p_context->aspect_ratio_info,
924                            ffmpeg_PixFmtToChroma(p_vdec->p_context->pix_fmt)) )
925     {
926         p_vdec->p_vout = 
927           ffmpeg_CreateVout( p_vdec,
928                              p_vdec->p_context->width,
929                              p_vdec->p_context->height,
930                              p_vdec->p_context->aspect_ratio_info,
931                              ffmpeg_PixFmtToChroma(p_vdec->p_context->pix_fmt));
932         if( !p_vdec->p_vout )
933         {
934             msg_Err( p_vdec->p_fifo, "cannot create vout" );
935             p_vdec->p_fifo->b_error = 1; /* abort */
936             return;
937         }
938     }
939
940     /* Get a new picture */
941     while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
942     {
943         if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error )
944         {
945             return;
946         }
947         msleep( VOUT_OUTMEM_SLEEP );
948     }
949     /* fill p_picture_t from avpicture, do I410->I420 if needed
950        and do post-processing if requested */    
951     ffmpeg_GetPicture( p_pic, &avpicture, p_vdec );
952
953     /* FIXME correct avi and use i_dts */
954
955     /* Send decoded frame to vout */
956     vout_DatePicture( p_vdec->p_vout, p_pic, p_vdec->i_pts);
957     vout_DisplayPicture( p_vdec->p_vout, p_pic );
958     
959     return;
960 }
961
962
963 /*****************************************************************************
964  * EndThread: thread destruction
965  *****************************************************************************
966  * This function is called when the thread ends after a sucessful
967  * initialization.
968  *****************************************************************************/
969 static void EndThread( videodec_thread_t *p_vdec )
970 {
971     
972     if( !p_vdec )
973     {
974         return;
975     }
976     if( p_vdec->p_pp )
977     {
978         /* release postprocessing module */
979         module_Unneed( p_vdec->p_pp, p_vdec->p_pp->p_module );
980         vlc_object_destroy( p_vdec->p_pp );
981         p_vdec->p_pp = NULL;
982     }
983
984     if( p_vdec->p_context != NULL)
985     {
986         FREE( p_vdec->p_context->quant_store );
987         avcodec_close( p_vdec->p_context );
988         msg_Dbg( p_vdec->p_fifo, "ffmpeg codec (%s) stopped",
989                                  p_vdec->psz_namecodec );
990     }
991
992     if( p_vdec->p_vout != NULL )
993     {
994         /* We are about to die. Reattach video output to p_vlc. */
995         vlc_object_detach( p_vdec->p_vout, p_vdec->p_fifo );
996         vlc_object_attach( p_vdec->p_vout, p_vdec->p_fifo->p_vlc );
997     }
998
999     FREE( p_vdec->format.p_data );
1000     FREE( p_vdec->p_buffer );
1001
1002     free( p_vdec );
1003 }
1004