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