* video.c: with mpeg4 stream, we try to decode a picture only when we have
[vlc.git] / modules / codec / ffmpeg / video.c
1 /*****************************************************************************
2  * video.c: video decoder using ffmpeg library
3  *****************************************************************************
4  * Copyright (C) 1999-2001 VideoLAN
5  * $Id: video.c,v 1.14 2002/12/18 16:31:25 fenrir Exp $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *          Gildas Bazin <gbazin@netcourrier.com>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdlib.h>                                      /* malloc(), free() */
29
30 #include <vlc/vlc.h>
31 #include <vlc/vout.h>
32 #include <vlc/aout.h>
33 #include <vlc/decoder.h>
34 #include <vlc/input.h>
35
36 #include <string.h>
37
38 #ifdef HAVE_SYS_TIMES_H
39 #   include <sys/times.h>
40 #endif
41
42 #include "avcodec.h"                                               /* ffmpeg */
43
44 #include "postprocessing/postprocessing.h"
45
46 #include "ffmpeg.h"
47 #include "video.h"
48
49 /*****************************************************************************
50  * Local prototypes
51  *****************************************************************************/
52 #if LIBAVCODEC_BUILD >= 4641
53 static void ffmpeg_CopyPicture( picture_t *, AVFrame *, vdec_thread_t * );
54 #else
55 static void ffmpeg_CopyPicture( picture_t *, AVPicture *, vdec_thread_t * );
56 #endif
57
58 static void ffmpeg_PostProcPicture( vdec_thread_t *, picture_t * );
59
60 #if LIBAVCODEC_BUILD >= 4641
61 static int  ffmpeg_GetFrameBuf( struct AVCodecContext *, AVFrame *);
62 static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *, AVFrame *);
63 #endif
64
65 /*****************************************************************************
66  * Local Functions
67  *****************************************************************************/
68
69 static inline uint32_t ffmpeg_PixFmtToChroma( int i_ff_chroma )
70 {
71     /* FIXME FIXME some of them are wrong */
72     switch( i_ff_chroma )
73     {
74         case PIX_FMT_YUV420P:
75         case PIX_FMT_YUV422:
76             return( VLC_FOURCC('I','4','2','0') );
77         case PIX_FMT_RGB24:
78             return( VLC_FOURCC('R','V','2','4') );
79
80         case PIX_FMT_YUV422P:
81             return( VLC_FOURCC('I','4','2','2') );
82         case PIX_FMT_YUV444P:
83             return( VLC_FOURCC('I','4','4','4') );
84 #if LIBAVCODEC_BUILD >= 4615
85         case PIX_FMT_YUV410P:
86 #endif
87         case PIX_FMT_BGR24:
88         default:
89             return( 0 );
90     }
91 }
92
93 /* Return a Vout */
94 static vout_thread_t *ffmpeg_CreateVout( vdec_thread_t  *p_vdec,
95                                          AVCodecContext *p_context )
96 {
97     vout_thread_t *p_vout;
98     unsigned int   i_width = p_context->width;
99     unsigned int   i_height =p_context->height;
100     uint32_t       i_chroma = ffmpeg_PixFmtToChroma( p_context->pix_fmt );
101     unsigned int   i_aspect;
102
103     if( !i_width || !i_height )
104     {
105         return( NULL ); /* Can't create a new vout without display size */
106     }
107
108     if( !i_chroma )
109     {
110         /* we make conversion if possible*/
111         i_chroma = VLC_FOURCC('I','4','2','0');
112         msg_Warn( p_vdec->p_fifo, "Internal chroma conversion (FIXME)");
113         /* It's mainly for I410 -> I420 conversion that I've made,
114            it's buggy and very slow */
115     }
116 #if LIBAVCODEC_BUILD >= 4640
117     i_aspect = VOUT_ASPECT_FACTOR * p_context->aspect_ratio;
118     if( i_aspect == 0 )
119     {
120         i_aspect = VOUT_ASPECT_FACTOR * i_width / i_height;
121     }
122 #else
123     switch( p_context->aspect_ratio_info )
124     {
125         case( FF_ASPECT_4_3_625 ):
126         case( FF_ASPECT_4_3_525 ):
127             i_aspect = VOUT_ASPECT_FACTOR * 4 / 3;
128             break;
129         case( FF_ASPECT_16_9_625 ):
130         case( FF_ASPECT_16_9_525 ):
131             i_aspect = VOUT_ASPECT_FACTOR * 16 / 9 ;
132             break;
133         case( FF_ASPECT_SQUARE ):
134         default:
135             i_aspect = VOUT_ASPECT_FACTOR * i_width / i_height;
136             break;
137         }
138 #endif
139
140     /* Spawn a video output if there is none. First we look for our children,
141      * then we look for any other vout that might be available. */
142     p_vout = vout_Request( p_vdec->p_fifo, NULL,
143                            i_width, i_height, i_chroma, i_aspect );
144
145     return p_vout;
146 }
147
148 /* FIXME FIXME FIXME this is a big shit
149    does someone want to rewrite this function ?
150    or said to me how write a better thing
151    FIXME FIXME FIXME
152 */
153 #if LIBAVCODEC_BUILD >= 4641
154 static void ffmpeg_ConvertPictureI410toI420( picture_t *p_pic,
155                                              AVFrame *p_ff_pic,
156                                              vdec_thread_t   *p_vdec )
157 #else
158 static void ffmpeg_ConvertPictureI410toI420( picture_t *p_pic,
159                                              AVPicture *p_ff_pic,
160                                              vdec_thread_t   *p_vdec )
161 #endif
162 {
163     uint8_t *p_src, *p_dst;
164     uint8_t *p_plane[3];
165     int i_plane;
166
167     int i_stride, i_lines;
168     int i_height, i_width;
169     int i_y, i_x;
170
171     i_height = p_vdec->p_context->height;
172     i_width  = p_vdec->p_context->width;
173
174     p_dst = p_pic->p[0].p_pixels;
175     p_src  = p_ff_pic->data[0];
176
177     /* copy first plane */
178     for( i_y = 0; i_y < i_height; i_y++ )
179     {
180         p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, i_width);
181         p_dst += p_pic->p[0].i_pitch;
182         p_src += p_ff_pic->linesize[0];
183     }
184
185     /* process each plane in a temporary buffer */
186     for( i_plane = 1; i_plane < 3; i_plane++ )
187     {
188         i_stride = p_ff_pic->linesize[i_plane];
189         i_lines = i_height / 4;
190
191         p_dst = p_plane[i_plane] = malloc( i_lines * i_stride * 2 * 2 );
192         p_src  = p_ff_pic->data[i_plane];
193
194         /* for each source line */
195         for( i_y = 0; i_y < i_lines; i_y++ )
196         {
197             for( i_x = 0; i_x < i_stride - 1; i_x++ )
198             {
199                 p_dst[2 * i_x    ] = p_src[i_x];
200                 p_dst[2 * i_x + 1] = ( p_src[i_x] + p_src[i_x + 1]) / 2;
201
202             }
203             p_dst[2 * i_stride - 2] = p_src[i_x];
204             p_dst[2 * i_stride - 1] = p_src[i_x];
205
206             p_dst += 4 * i_stride; /* process the next even lines */
207             p_src += i_stride;
208         }
209     }
210
211     for( i_plane = 1; i_plane < 3; i_plane++ )
212     {
213         i_stride = p_ff_pic->linesize[i_plane];
214         i_lines = i_height / 4;
215
216         p_dst = p_plane[i_plane] + 2*i_stride;
217         p_src  = p_plane[i_plane];
218
219         for( i_y = 0; i_y < i_lines - 1; i_y++ )
220         {
221             for( i_x = 0; i_x <  2 * i_stride ; i_x++ )
222             {
223                 p_dst[i_x] = ( p_src[i_x] + p_src[i_x + 4*i_stride])/2;
224             }
225
226             p_dst += 4 * i_stride; /* process the next odd lines */
227             p_src += 4 * i_stride;
228         }
229         /* last line */
230         p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, 2*i_stride );
231     }
232     /* copy to p_pic, by block
233        if I do pixel per pixel it segfault. It's why I use
234        temporaries buffers */
235     for( i_plane = 1; i_plane < 3; i_plane++ )
236     {
237         int i_size;
238         p_src  = p_plane[i_plane];
239         p_dst = p_pic->p[i_plane].p_pixels;
240
241         i_size = __MIN( 2*i_stride, p_pic->p[i_plane].i_pitch);
242         for( i_y = 0; i_y < __MIN(p_pic->p[i_plane].i_lines, 2 * i_lines); i_y++ )
243         {
244             p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, i_size );
245             p_src += 2 * i_stride;
246             p_dst += p_pic->p[i_plane].i_pitch;
247         }
248         free( p_plane[i_plane] );
249     }
250 }
251
252 /*****************************************************************************
253  *
254  * Functions that initialize, decode and end the decoding process
255  *
256  * Functions exported for ffmpeg.c
257  *   * E_( InitThread_Video )
258  *   * E_( DecodeThread )
259  *   * E_( EndThread_Video )
260  *****************************************************************************/
261
262 /*****************************************************************************
263  * InitThread: initialize vdec output thread
264  *****************************************************************************
265  * This function is called from decoder_Run and performs the second step
266  * of the initialization. It returns 0 on success. Note that the thread's
267  * flag are not modified inside this function.
268  *
269  * ffmpeg codec will be open, some memory allocated. But Vout is not yet
270  * open (done after the first decoded frame)
271  *****************************************************************************/
272 int E_( InitThread_Video )( vdec_thread_t *p_vdec )
273 {
274     int i_tmp;
275 #if LIBAVCODEC_BUILD >= 4645
276     p_vdec->p_ff_pic = avcodec_alloc_frame();
277 #elif LIBAVCODEC_BUILD >= 4641
278     p_vdec->p_ff_pic = avcodec_alloc_picture();
279 #else
280     p_vdec->p_ff_pic = &p_vdec->ff_pic;
281 #endif
282
283     if( p_vdec->p_fifo->p_demux_data )
284     {
285         p_vdec->p_format = (BITMAPINFOHEADER *)p_vdec->p_fifo->p_demux_data;
286
287         /* ***** Fill p_context with init values ***** */
288         p_vdec->p_context->width  = p_vdec->p_format->biWidth;
289         p_vdec->p_context->height = p_vdec->p_format->biHeight;
290
291     }
292     else
293     {
294         msg_Warn( p_vdec->p_fifo, "display informations missing" );
295         p_vdec->p_format = NULL;
296     }
297
298
299     /*  ***** Get configuration of ffmpeg plugin ***** */
300 #if LIBAVCODEC_BUILD >= 4611
301     i_tmp = config_GetInt( p_vdec->p_fifo, "ffmpeg-workaround-bugs" );
302     p_vdec->p_context->workaround_bugs  = __MAX( __MIN( i_tmp, 99 ), 0 );
303
304     i_tmp = config_GetInt( p_vdec->p_fifo, "ffmpeg-error-resilience" );
305     p_vdec->p_context->error_resilience = __MAX( __MIN( i_tmp, 99 ), -1 );
306 #endif
307 #if LIBAVCODEC_BUILD >= 4614
308     if( config_GetInt( p_vdec->p_fifo, "grayscale" ) )
309     {
310         p_vdec->p_context->flags|= CODEC_FLAG_GRAY;
311     }
312 #endif
313
314     p_vdec->b_hurry_up = config_GetInt(p_vdec->p_fifo, "ffmpeg-hurry-up");
315
316     p_vdec->b_direct_rendering = 0;
317
318 #if LIBAVCODEC_BUILD >= 4641
319     if( config_GetInt( p_vdec->p_fifo, "ffmpeg-dr" ) &&
320         p_vdec->p_codec->capabilities & CODEC_CAP_DR1 &&
321         p_vdec->p_context->pix_fmt != PIX_FMT_YUV410P ) /* <- FIXME */
322     {
323         msg_Dbg( p_vdec->p_fifo, "using direct rendering" );
324         p_vdec->b_direct_rendering = 1;
325         p_vdec->p_context->flags|= CODEC_FLAG_EMU_EDGE;
326         p_vdec->p_context->get_buffer     = ffmpeg_GetFrameBuf;
327         p_vdec->p_context->release_buffer = ffmpeg_ReleaseFrameBuf;
328         p_vdec->p_context->opaque = p_vdec;
329
330     }
331 #endif
332
333 #if 0
334     /* check if codec support truncated frames */
335 //    if( p_vdec->p_codec->capabilities & CODEC_FLAG_TRUNCATED )
336     if( p_vdec->i_codec_id == CODEC_ID_MPEG1VIDEO)
337     {
338         msg_Dbg( p_vdec->p_fifo, "CODEC_FLAG_TRUNCATED supported" );
339         p_vdec->p_context->flags |= CODEC_FLAG_TRUNCATED;
340     }
341 #endif
342
343     /* ***** Open the codec ***** */
344     if( avcodec_open(p_vdec->p_context, p_vdec->p_codec) < 0 )
345     {
346         msg_Err( p_vdec->p_fifo, "cannot open codec (%s)",
347                                  p_vdec->psz_namecodec );
348         return( -1 );
349     }
350     else
351     {
352         msg_Dbg( p_vdec->p_fifo, "ffmpeg codec (%s) started",
353                                  p_vdec->psz_namecodec );
354     }
355
356     /* ***** init this codec with special data ***** */
357     if( p_vdec->p_format &&
358             p_vdec->p_format->biSize > sizeof(BITMAPINFOHEADER) )
359     {
360         int b_gotpicture;
361
362         switch( p_vdec->i_codec_id )
363         {
364             case( CODEC_ID_MPEG4 ):
365 #if 0
366                 avcodec_decode_video( p_vdec->p_context, p_vdec->p_ff_pic,
367                                       &b_gotpicture,
368                                       (void *)&p_vdec->p_format[1],
369                                       p_vdec->p_format->biSize
370                                         - sizeof(BITMAPINFOHEADER) );
371 #endif
372                 break;
373             default:
374                 if( p_vdec->p_fifo->i_fourcc == FOURCC_MP4S ||
375                     p_vdec->p_fifo->i_fourcc == FOURCC_mp4s ||
376                     p_vdec->p_fifo->i_fourcc == FOURCC_M4S2 ||
377                     p_vdec->p_fifo->i_fourcc == FOURCC_m4s2 ||
378                     p_vdec->p_fifo->i_fourcc == FOURCC_WMV2 ||
379                     p_vdec->p_fifo->i_fourcc == FOURCC_MJPG ||
380                     p_vdec->p_fifo->i_fourcc == FOURCC_mjpg ||
381                     p_vdec->p_fifo->i_fourcc == FOURCC_mjpa ||
382                     p_vdec->p_fifo->i_fourcc == FOURCC_mjpb )
383                 {
384                     p_vdec->p_context->extradata_size =
385                         p_vdec->p_format->biSize - sizeof(BITMAPINFOHEADER);
386                     p_vdec->p_context->extradata =
387                         malloc( p_vdec->p_context->extradata_size );
388                     memcpy( p_vdec->p_context->extradata,
389                             &p_vdec->p_format[1],
390                             p_vdec->p_context->extradata_size );
391                 }
392
393                 break;
394         }
395     }
396
397     /* ***** Load post processing ***** */
398
399     /* get overridding settings */
400     p_vdec->i_pp_mode = 0;
401     if( config_GetInt( p_vdec->p_fifo, "ffmpeg-db-yv" ) )
402         p_vdec->i_pp_mode |= PP_DEBLOCK_Y_V;
403     if( config_GetInt( p_vdec->p_fifo, "ffmpeg-db-yh" ) )
404         p_vdec->i_pp_mode |= PP_DEBLOCK_Y_H;
405     if( config_GetInt( p_vdec->p_fifo, "ffmpeg-db-cv" ) )
406         p_vdec->i_pp_mode |= PP_DEBLOCK_C_V;
407     if( config_GetInt( p_vdec->p_fifo, "ffmpeg-db-ch" ) )
408         p_vdec->i_pp_mode |= PP_DEBLOCK_C_H;
409     if( config_GetInt( p_vdec->p_fifo, "ffmpeg-dr-y" ) )
410         p_vdec->i_pp_mode |= PP_DERING_Y;
411     if( config_GetInt( p_vdec->p_fifo, "ffmpeg-dr-c" ) )
412         p_vdec->i_pp_mode |= PP_DERING_C;
413
414     if( ( config_GetInt( p_vdec->p_fifo, "ffmpeg-pp-q" ) > 0 )||
415         ( config_GetInt( p_vdec->p_fifo, "ffmpeg-pp-auto" )  )||
416         ( p_vdec->i_pp_mode != 0 ) )
417     {
418         /* check if the codec support postproc. */
419         switch( p_vdec->i_codec_id )
420         {
421 #if LIBAVCODEC_BUILD > 4608
422             case( CODEC_ID_MSMPEG4V1 ):
423             case( CODEC_ID_MSMPEG4V2 ):
424             case( CODEC_ID_MSMPEG4V3 ):
425 #else
426             case( CODEC_ID_MSMPEG4 ):
427 #endif
428             case( CODEC_ID_MPEG4 ):
429             case( CODEC_ID_H263 ):
430 //            case( CODEC_ID_H263P ): I don't use it up to now
431             case( CODEC_ID_H263I ):
432                 /* Ok we can make postprocessing :)) */
433                 /* first try to get a postprocess module */
434 #if LIBAVCODEC_BUILD >= 4633
435                 p_vdec->p_pp = vlc_object_create( p_vdec->p_fifo,
436                                                   sizeof( postprocessing_t ) );
437                 p_vdec->p_pp->psz_object_name = "postprocessing";
438                 p_vdec->p_pp->p_module =
439                    module_Need( p_vdec->p_pp, "postprocessing", "$ffmpeg-pp" );
440
441                 if( !p_vdec->p_pp->p_module )
442                 {
443                     msg_Warn( p_vdec->p_fifo,
444                               "no suitable postprocessing module" );
445                     vlc_object_destroy( p_vdec->p_pp );
446                     p_vdec->p_pp = NULL;
447                     p_vdec->i_pp_mode = 0;
448                 }
449                 else
450                 {
451                     /* get mode upon quality */
452                     p_vdec->i_pp_mode |=
453                         p_vdec->p_pp->pf_getmode(
454                               config_GetInt( p_vdec->p_fifo, "ffmpeg-pp-q" ),
455                               config_GetInt( p_vdec->p_fifo, "ffmpeg-pp-auto" )
456                                                 );
457                 }
458 #else
459                 p_vdec->i_pp_mode = 0;
460                 msg_Warn( p_vdec->p_fifo,
461                           "post-processing not supported, upgrade ffmpeg" );
462 #endif
463                 break;
464             default:
465                 p_vdec->i_pp_mode = 0;
466                 msg_Warn( p_vdec->p_fifo,
467                           "Post processing unsupported for this codec" );
468                 break;
469         }
470
471     }
472 //    memset( &p_vdec->statistic, 0, sizeof( statistic_t ) );
473
474     return( 0 );
475 }
476
477 /*****************************************************************************
478  * DecodeThread: Called to decode one frame
479  *****************************************************************************
480  * We have to get a frame stored in a pes, give it to ffmpeg decoder and send
481  * the image to the output.
482  *****************************************************************************/
483 void  E_( DecodeThread_Video )( vdec_thread_t *p_vdec )
484 {
485     pes_packet_t    *p_pes;
486     int     i_frame_size;
487     int     i_used;
488     int     b_drawpicture;
489     int     b_gotpicture;
490     picture_t *p_pic;                                    /* videolan picture */
491     mtime_t   i_pts;
492
493     /* TODO implement it in a better way */
494     /* A good idea could be to decode all I pictures and see for the other */
495     if( ( p_vdec->b_hurry_up )&& ( p_vdec->i_frame_late > 4 ) )
496     {
497         b_drawpicture = 0;
498         if( p_vdec->i_frame_late < 8 )
499         {
500             p_vdec->p_context->hurry_up = 2;
501         }
502         else
503         {
504             /* too much late picture, won't decode
505                but break picture until a new I, and for mpeg4 ...*/
506             p_vdec->i_frame_late--; /* needed else it will never be decrease */
507             input_ExtractPES( p_vdec->p_fifo, NULL );
508             return;
509         }
510     }
511     else
512     {
513         b_drawpicture = 1;
514         p_vdec->p_context->hurry_up = 0;
515     }
516
517     if( !p_vdec->p_context->width || !p_vdec->p_context->height )
518     {
519         p_vdec->p_context->hurry_up = 5;
520     }
521
522     do
523     {
524         input_ExtractPES( p_vdec->p_fifo, &p_pes );
525         if( !p_pes )
526         {
527             p_vdec->p_fifo->b_error = 1;
528             return;
529         }
530 #if 0
531         if( p_vdec->i_codec_id == CODEC_ID_MPEG1VIDEO )
532         {
533             if( p_pes->i_dts )
534             {
535                 p_vdec->pts = p_pes->i_dts;
536                 p_vdec->i_frame_count = 0;
537             }
538         }
539         else
540         {
541             if( p_pes->i_pts )
542             {
543                 p_vdec->pts = p_pes->i_pts;
544                 p_vdec->i_frame_count = 0;
545             }
546         }
547 #endif
548         if( p_pes->i_pts )
549         {
550             p_vdec->pts = p_pes->i_pts;
551             p_vdec->i_frame_count = 0;
552         }
553
554         i_frame_size = p_pes->i_pes_size;
555
556         if( i_frame_size > 0 )
557         {
558             uint8_t *p_last;
559             int i_need;
560             /* XXX Don't forget that ffmpeg required a little more bytes
561              * that the real frame size */
562             i_need = i_frame_size + 16 + p_vdec->i_buffer;
563             if( p_vdec->i_buffer_size < i_need)
564             {
565                 p_last = p_vdec->p_buffer;
566                 p_vdec->p_buffer = malloc( i_need );
567                 p_vdec->i_buffer_size = i_need;
568                 if( p_vdec->i_buffer > 0 )
569                 {
570                     memcpy( p_vdec->p_buffer, p_last, p_vdec->i_buffer );
571                 }
572                 FREE( p_last );
573             }
574             i_frame_size =
575                 E_( GetPESData )( p_vdec->p_buffer + p_vdec->i_buffer,
576                                   i_frame_size ,
577                                   p_pes );
578             memset( p_vdec->p_buffer + p_vdec->i_buffer + i_frame_size,
579                     0,
580                     16 );
581         }
582         input_DeletePES( p_vdec->p_fifo->p_packets_mgt, p_pes );
583     } while( i_frame_size <= 0 );
584
585     i_frame_size += p_vdec->i_buffer;
586
587 usenextdata:
588     i_used = avcodec_decode_video( p_vdec->p_context,
589                                    p_vdec->p_ff_pic,
590                                    &b_gotpicture,
591                                    p_vdec->p_buffer,
592                                    i_frame_size );
593
594 #if 0
595     msg_Dbg( p_vdec->p_fifo,
596              "used:%d framesize:%d (%s picture)",
597              i_used, i_frame_size, b_gotpicture ? "got":"no got" );
598 #endif
599     if( i_used < 0 )
600     {
601         msg_Warn( p_vdec->p_fifo, "cannot decode one frame (%d bytes)",
602                                   i_frame_size );
603         p_vdec->i_frame_error++;
604         p_vdec->i_buffer = 0;
605         return;
606     }
607     else if( i_used < i_frame_size )
608     {
609 #if 0
610         msg_Dbg( p_vdec->p_fifo,
611                  "didn't use all memory(%d  < %d)", i_used, i_frame_size );
612 #endif
613         memmove( p_vdec->p_buffer,
614                  p_vdec->p_buffer + i_used,
615                  p_vdec->i_buffer_size - i_used );
616
617         p_vdec->i_buffer = i_frame_size - i_used;
618     }
619     else
620     {
621         p_vdec->i_buffer = 0;
622     }
623
624     if( b_gotpicture )
625     {
626         p_vdec->i_frame_count++;
627     }
628
629     /* consumed bytes */
630     i_frame_size -= i_used;
631
632    /* Update frame late count*/
633     /* I don't make statistic on decoding time */
634     if( p_vdec->pts <= mdate())
635     {
636         p_vdec->i_frame_late++;
637     }
638     else
639     {
640         p_vdec->i_frame_late = 0;
641     }
642
643     if( !b_gotpicture || p_vdec->p_ff_pic->linesize[0] == 0 || !b_drawpicture )
644     {
645         return;
646     }
647
648     if( !p_vdec->b_direct_rendering )
649     {
650         p_vdec->p_vout = ffmpeg_CreateVout( p_vdec, p_vdec->p_context );
651         if( !p_vdec->p_vout )
652         {
653             msg_Err( p_vdec->p_fifo, "cannot create vout" );
654             p_vdec->p_fifo->b_error = 1; /* abort */
655             return;
656         }
657
658         /* Get a new picture */
659         while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
660         {
661             if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error )
662             {
663                 return;
664             }
665             msleep( VOUT_OUTMEM_SLEEP );
666         }
667
668         /* fill p_picture_t from AVVideoFrame, do I410->I420 if needed */
669         ffmpeg_CopyPicture( p_pic, p_vdec->p_ff_pic, p_vdec );
670     }
671     else
672     {
673 #if LIBAVCODEC_BUILD >= 4641
674         p_pic = (picture_t *)p_vdec->p_ff_pic->opaque;
675 #else
676         p_pic = NULL; /*  f**ck gcc warning */
677 #endif
678     }
679
680     /* Do post-processing if requested */
681     /* XXX: with dr it is not a good thing if the picture will be used as
682        reference... */
683     ffmpeg_PostProcPicture( p_vdec, p_pic );
684
685     /* fix date calculation */
686     if( p_vdec->pts > 0 )
687     {
688         i_pts = p_vdec->pts;
689
690         if( p_vdec->p_context->frame_rate > 0 )
691         {
692            i_pts += (uint64_t)1000000 *
693                     ( p_vdec->i_frame_count - 1) /
694                     FRAME_RATE_BASE /
695                     p_vdec->p_context->frame_rate;
696         }
697     }
698     else
699     {
700         i_pts = mdate() + DEFAULT_PTS_DELAY;  // FIXME
701     }
702
703     vout_DatePicture( p_vdec->p_vout,
704                       p_pic,
705                       i_pts );
706
707     /* Send decoded frame to vout */
708     vout_DisplayPicture( p_vdec->p_vout, p_pic );
709
710     if( i_frame_size > 0 )
711     {
712         goto usenextdata; /* try to use all data */
713     }
714 }
715
716 /*****************************************************************************
717  * EndThread: thread destruction
718  *****************************************************************************
719  * This function is called when the thread ends after a sucessful
720  * initialization.
721  *****************************************************************************/
722 void E_( EndThread_Video )( vdec_thread_t *p_vdec )
723 {
724
725     if( p_vdec->p_pp )
726     {
727         /* release postprocessing module */
728         module_Unneed( p_vdec->p_pp, p_vdec->p_pp->p_module );
729         vlc_object_destroy( p_vdec->p_pp );
730         p_vdec->p_pp = NULL;
731     }
732
733 #if LIBAVCODEC_BUILD >= 4641
734     if( p_vdec->p_ff_pic )
735     {
736         free( p_vdec->p_ff_pic );
737     }
738 #endif
739
740     /* We are about to die. Reattach video output to p_vlc. */
741     vout_Request( p_vdec->p_fifo, p_vdec->p_vout, 0, 0, 0, 0 );
742 }
743
744 /*****************************************************************************
745  * ffmpeg_CopyPicture: copy a picture from ffmpeg internal buffers to a
746  *                     picture_t structure (when not in direct rendering mode).
747  *****************************************************************************/
748 #if LIBAVCODEC_BUILD >= 4641
749 static void ffmpeg_CopyPicture( picture_t    *p_pic,
750                                 AVFrame *p_ff_pic,
751                                 vdec_thread_t *p_vdec )
752 #else
753 static void ffmpeg_CopyPicture( picture_t    *p_pic,
754                                 AVPicture *p_ff_pic,
755                                 vdec_thread_t *p_vdec )
756 #endif
757 {
758     int i_plane;
759     int i_size;
760     int i_line;
761
762     uint8_t *p_dst;
763     uint8_t *p_src;
764     int i_src_stride;
765     int i_dst_stride;
766
767     if( ffmpeg_PixFmtToChroma( p_vdec->p_context->pix_fmt ) )
768     {
769         for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
770         {
771             p_src  = p_ff_pic->data[i_plane];
772             p_dst = p_pic->p[i_plane].p_pixels;
773             i_src_stride = p_ff_pic->linesize[i_plane];
774             i_dst_stride = p_pic->p[i_plane].i_pitch;
775
776             i_size = __MIN( i_src_stride, i_dst_stride );
777             for( i_line = 0; i_line < p_pic->p[i_plane].i_lines; i_line++ )
778             {
779                 p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, i_size );
780                 p_src += i_src_stride;
781                 p_dst += i_dst_stride;
782             }
783         }
784     }
785     else
786     {
787         /* we need to convert to I420 */
788         switch( p_vdec->p_context->pix_fmt )
789         {
790 #if LIBAVCODEC_BUILD >= 4615
791             case( PIX_FMT_YUV410P ):
792                 ffmpeg_ConvertPictureI410toI420( p_pic, p_ff_pic, p_vdec );
793                 break;
794 #endif
795             default:
796                 p_vdec->p_fifo->b_error = 1;
797                 break;
798         }
799     }
800 }
801
802 /*****************************************************************************
803  * ffmpeg_PostProcPicture: Postprocessing is done here.
804  *****************************************************************************/
805 static void ffmpeg_PostProcPicture( vdec_thread_t *p_vdec, picture_t *p_pic )
806 {
807     if( ( p_vdec->i_pp_mode )&&
808         ( ( p_vdec->p_vout->render.i_chroma ==
809             VLC_FOURCC( 'I','4','2','0' ) )||
810           ( p_vdec->p_vout->render.i_chroma ==
811             VLC_FOURCC( 'Y','V','1','2' ) ) ) )
812     {
813 #if LIBAVCODEC_BUILD >= 4641
814        /* Make postproc */
815         p_vdec->p_pp->pf_postprocess( p_pic,
816                                       p_vdec->p_ff_pic->qscale_table,
817                                       p_vdec->p_ff_pic->qstride,
818                                       p_vdec->i_pp_mode );
819 #elif LIBAVCODEC_BUILD >= 4633
820         p_vdec->p_pp->pf_postprocess( p_pic,
821                                       p_vdec->p_context->display_qscale_table,
822                                       p_vdec->p_context->qstride,
823                                       p_vdec->i_pp_mode );
824 #endif
825     }
826 }
827
828 #if LIBAVCODEC_BUILD >= 4641
829 /*****************************************************************************
830  * ffmpeg_GetFrameBuf: callback used by ffmpeg to get a frame buffer.
831  *                     (used for direct rendering)
832  *****************************************************************************/
833
834 static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context,
835                                AVFrame *p_ff_pic )
836 {
837     vdec_thread_t *p_vdec = (vdec_thread_t *)p_context->opaque;
838     picture_t *p_pic;
839
840     /* Check and (re)create if needed our vout */
841     p_vdec->p_vout = ffmpeg_CreateVout( p_vdec, p_vdec->p_context );
842     if( !p_vdec->p_vout )
843     {
844         msg_Err( p_vdec->p_fifo, "cannot create vout" );
845         p_vdec->p_fifo->b_error = 1; /* abort */
846         return -1;
847     }
848     p_vdec->p_vout->render.b_allow_modify_pics = 0;
849
850     /* Get a new picture */
851     while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
852     {
853         if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error )
854         {
855             return -1;
856         }
857         msleep( VOUT_OUTMEM_SLEEP );
858     }
859     p_vdec->p_context->draw_horiz_band= NULL;
860
861     p_ff_pic->opaque = (void*)p_pic;
862 #if LIBAVCODEC_BUILD >= 4645
863     p_ff_pic->type = FF_BUFFER_TYPE_USER;
864 #endif
865     p_ff_pic->data[0] = p_pic->p[0].p_pixels;
866     p_ff_pic->data[1] = p_pic->p[1].p_pixels;
867     p_ff_pic->data[2] = p_pic->p[2].p_pixels;
868     p_ff_pic->data[3] = NULL; /* alpha channel but I'm not sure */
869
870     p_ff_pic->linesize[0] = p_pic->p[0].i_pitch;
871     p_ff_pic->linesize[1] = p_pic->p[1].i_pitch;
872     p_ff_pic->linesize[2] = p_pic->p[2].i_pitch;
873     p_ff_pic->linesize[3] = 0;
874
875     if( p_ff_pic->reference != 0 )
876     {
877         vout_LinkPicture( p_vdec->p_vout, p_pic );
878     }
879     /* FIXME what is that, should give good value */
880     p_ff_pic->age = 256*256*256*64; // FIXME FIXME from ffmpeg
881
882     return( 0 );
883 }
884
885 static void  ffmpeg_ReleaseFrameBuf( struct AVCodecContext *p_context,
886                                      AVFrame *p_ff_pic )
887 {
888     vdec_thread_t *p_vdec = (vdec_thread_t *)p_context->opaque;
889     picture_t *p_pic;
890
891     //msg_Dbg( p_vdec->p_fifo, "ffmpeg_ReleaseFrameBuf" );
892     p_pic = (picture_t*)p_ff_pic->opaque;
893
894     p_ff_pic->data[0] = NULL;
895     p_ff_pic->data[1] = NULL;
896     p_ff_pic->data[2] = NULL;
897     p_ff_pic->data[3] = NULL;
898
899     vout_UnlinkPicture( p_vdec->p_vout, p_pic );
900 }
901
902
903 #endif
904