]> git.sesse.net Git - vlc/blob - modules/codec/ffmpeg/video.c
* ./configure.ac.in: removed -W in favour of -Wtraditional.
[vlc] / 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.11 2002/12/06 16:34:05 sam 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 *, AVVideoFrame *, 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 *, AVVideoFrame *);
62 static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *, AVVideoFrame *);
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                                              AVVideoFrame *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 >= 4641
276     p_vdec->p_ff_pic = avcodec_alloc_picture();
277 #else
278     p_vdec->p_ff_pic = &p_vdec->ff_pic;
279 #endif
280
281     if( p_vdec->p_fifo->p_demux_data )
282     {
283         p_vdec->p_format = (BITMAPINFOHEADER *)p_vdec->p_fifo->p_demux_data;
284
285         /* ***** Fill p_context with init values ***** */
286         p_vdec->p_context->width  = p_vdec->p_format->biWidth;
287         p_vdec->p_context->height = p_vdec->p_format->biHeight;
288
289     }
290     else
291     {
292         msg_Warn( p_vdec->p_fifo, "display informations missing" );
293         p_vdec->p_format = NULL;
294     }
295
296
297     /*  ***** Get configuration of ffmpeg plugin ***** */
298 #if LIBAVCODEC_BUILD >= 4611
299     i_tmp = config_GetInt( p_vdec->p_fifo, "ffmpeg-workaround-bugs" );
300     p_vdec->p_context->workaround_bugs  = __MAX( __MIN( i_tmp, 99 ), 0 );
301
302     i_tmp = config_GetInt( p_vdec->p_fifo, "ffmpeg-error-resilience" );
303     p_vdec->p_context->error_resilience = __MAX( __MIN( i_tmp, 99 ), -1 );
304 #endif
305 #if LIBAVCODEC_BUILD >= 4614
306     if( config_GetInt( p_vdec->p_fifo, "grayscale" ) )
307     {
308         p_vdec->p_context->flags|= CODEC_FLAG_GRAY;
309     }
310 #endif
311
312     p_vdec->b_hurry_up = config_GetInt(p_vdec->p_fifo, "ffmpeg-hurry-up");
313
314     p_vdec->b_direct_rendering = 0;
315
316 #if LIBAVCODEC_BUILD >= 4641
317     if( config_GetInt( p_vdec->p_fifo, "ffmpeg-dr" ) &&
318         p_vdec->p_codec->capabilities & CODEC_CAP_DR1 &&
319         p_vdec->p_context->pix_fmt != PIX_FMT_YUV410P ) /* <- FIXME */
320     {
321         msg_Dbg( p_vdec->p_fifo, "using direct rendering" );
322         p_vdec->b_direct_rendering = 1;
323         p_vdec->p_context->flags|= CODEC_FLAG_EMU_EDGE;
324         p_vdec->p_context->get_buffer     = ffmpeg_GetFrameBuf;
325         p_vdec->p_context->release_buffer = ffmpeg_ReleaseFrameBuf;
326         p_vdec->p_context->opaque = p_vdec;
327
328     }
329 #endif
330
331 #if 0
332     /* check if codec support truncated frames */
333 //    if( p_vdec->p_codec->capabilities & CODEC_FLAG_TRUNCATED )
334     if( p_vdec->i_codec_id == CODEC_ID_MPEG1VIDEO)
335     {
336         msg_Dbg( p_vdec->p_fifo, "CODEC_FLAG_TRUNCATED supported" );
337         p_vdec->p_context->flags |= CODEC_FLAG_TRUNCATED;
338     }
339 #endif
340
341     /* ***** Open the codec ***** */
342     if( avcodec_open(p_vdec->p_context, p_vdec->p_codec) < 0 )
343     {
344         msg_Err( p_vdec->p_fifo, "cannot open codec (%s)",
345                                  p_vdec->psz_namecodec );
346         return( -1 );
347     }
348     else
349     {
350         msg_Dbg( p_vdec->p_fifo, "ffmpeg codec (%s) started",
351                                  p_vdec->psz_namecodec );
352     }
353
354     /* ***** init this codec with special data ***** */
355     if( p_vdec->p_format &&
356             p_vdec->p_format->biSize > sizeof(BITMAPINFOHEADER) )
357     {
358         int b_gotpicture;
359
360         switch( p_vdec->i_codec_id )
361         {
362             case( CODEC_ID_MPEG4 ):
363                 avcodec_decode_video( p_vdec->p_context, p_vdec->p_ff_pic,
364                                       &b_gotpicture,
365                                       (void *)&p_vdec->p_format[1],
366                                       p_vdec->p_format->biSize
367                                         - sizeof(BITMAPINFOHEADER) );
368                 break;
369             default:
370                 if( p_vdec->p_fifo->i_fourcc == FOURCC_MP4S ||
371                     p_vdec->p_fifo->i_fourcc == FOURCC_mp4s ||
372                     p_vdec->p_fifo->i_fourcc == FOURCC_M4S2 ||
373                     p_vdec->p_fifo->i_fourcc == FOURCC_m4s2 ||
374                     p_vdec->p_fifo->i_fourcc == FOURCC_WMV2 ||
375                     p_vdec->p_fifo->i_fourcc == FOURCC_MJPG ||
376                     p_vdec->p_fifo->i_fourcc == FOURCC_mjpg ||
377                     p_vdec->p_fifo->i_fourcc == FOURCC_mjpa ||
378                     p_vdec->p_fifo->i_fourcc == FOURCC_mjpb )
379                 {
380                     p_vdec->p_context->extradata_size =
381                         p_vdec->p_format->biSize - sizeof(BITMAPINFOHEADER);
382                     p_vdec->p_context->extradata =
383                         malloc( p_vdec->p_context->extradata_size );
384                     memcpy( p_vdec->p_context->extradata,
385                             &p_vdec->p_format[1],
386                             p_vdec->p_context->extradata_size );
387                 }
388
389                 break;
390         }
391     }
392
393     /* ***** Load post processing ***** */
394
395     /* get overridding settings */
396     p_vdec->i_pp_mode = 0;
397     if( config_GetInt( p_vdec->p_fifo, "ffmpeg-db-yv" ) )
398         p_vdec->i_pp_mode |= PP_DEBLOCK_Y_V;
399     if( config_GetInt( p_vdec->p_fifo, "ffmpeg-db-yh" ) )
400         p_vdec->i_pp_mode |= PP_DEBLOCK_Y_H;
401     if( config_GetInt( p_vdec->p_fifo, "ffmpeg-db-cv" ) )
402         p_vdec->i_pp_mode |= PP_DEBLOCK_C_V;
403     if( config_GetInt( p_vdec->p_fifo, "ffmpeg-db-ch" ) )
404         p_vdec->i_pp_mode |= PP_DEBLOCK_C_H;
405     if( config_GetInt( p_vdec->p_fifo, "ffmpeg-dr-y" ) )
406         p_vdec->i_pp_mode |= PP_DERING_Y;
407     if( config_GetInt( p_vdec->p_fifo, "ffmpeg-dr-c" ) )
408         p_vdec->i_pp_mode |= PP_DERING_C;
409
410     if( ( config_GetInt( p_vdec->p_fifo, "ffmpeg-pp-q" ) > 0 )||
411         ( config_GetInt( p_vdec->p_fifo, "ffmpeg-pp-auto" )  )||
412         ( p_vdec->i_pp_mode != 0 ) )
413     {
414         /* check if the codec support postproc. */
415         switch( p_vdec->i_codec_id )
416         {
417 #if LIBAVCODEC_BUILD > 4608
418             case( CODEC_ID_MSMPEG4V1 ):
419             case( CODEC_ID_MSMPEG4V2 ):
420             case( CODEC_ID_MSMPEG4V3 ):
421 #else
422             case( CODEC_ID_MSMPEG4 ):
423 #endif
424             case( CODEC_ID_MPEG4 ):
425             case( CODEC_ID_H263 ):
426 //            case( CODEC_ID_H263P ): I don't use it up to now
427             case( CODEC_ID_H263I ):
428                 /* Ok we can make postprocessing :)) */
429                 /* first try to get a postprocess module */
430 #if LIBAVCODEC_BUILD >= 4633
431                 p_vdec->p_pp = vlc_object_create( p_vdec->p_fifo,
432                                                   sizeof( postprocessing_t ) );
433                 p_vdec->p_pp->psz_object_name = "postprocessing";
434                 p_vdec->p_pp->p_module =
435                    module_Need( p_vdec->p_pp, "postprocessing", "$ffmpeg-pp" );
436
437                 if( !p_vdec->p_pp->p_module )
438                 {
439                     msg_Warn( p_vdec->p_fifo,
440                               "no suitable postprocessing module" );
441                     vlc_object_destroy( p_vdec->p_pp );
442                     p_vdec->p_pp = NULL;
443                     p_vdec->i_pp_mode = 0;
444                 }
445                 else
446                 {
447                     /* get mode upon quality */
448                     p_vdec->i_pp_mode |=
449                         p_vdec->p_pp->pf_getmode(
450                               config_GetInt( p_vdec->p_fifo, "ffmpeg-pp-q" ),
451                               config_GetInt( p_vdec->p_fifo, "ffmpeg-pp-auto" )
452                                                 );
453                 }
454 #else
455                 p_vdec->i_pp_mode = 0;
456                 msg_Warn( p_vdec->p_fifo,
457                           "post-processing not supported, upgrade ffmpeg" );
458 #endif
459                 break;
460             default:
461                 p_vdec->i_pp_mode = 0;
462                 msg_Warn( p_vdec->p_fifo,
463                           "Post processing unsupported for this codec" );
464                 break;
465         }
466
467     }
468 //    memset( &p_vdec->statistic, 0, sizeof( statistic_t ) );
469
470     return( 0 );
471 }
472
473 /*****************************************************************************
474  * DecodeThread: Called to decode one frame
475  *****************************************************************************
476  * We have to get a frame stored in a pes, give it to ffmpeg decoder and send
477  * the image to the output.
478  *****************************************************************************/
479 void  E_( DecodeThread_Video )( vdec_thread_t *p_vdec )
480 {
481     pes_packet_t    *p_pes;
482     int     i_frame_size;
483     int     i_used;
484     int     b_drawpicture;
485     int     b_gotpicture;
486     picture_t *p_pic;                                    /* videolan picture */
487     mtime_t   i_pts;
488
489     /* TODO implement it in a better way */
490     /* A good idea could be to decode all I pictures and see for the other */
491     if( ( p_vdec->b_hurry_up )&& ( p_vdec->i_frame_late > 4 ) )
492     {
493         b_drawpicture = 0;
494         if( p_vdec->i_frame_late < 8 )
495         {
496             p_vdec->p_context->hurry_up = 2;
497         }
498         else
499         {
500             /* too much late picture, won't decode
501                but break picture until a new I, and for mpeg4 ...*/
502             p_vdec->i_frame_late--; /* needed else it will never be decrease */
503             input_ExtractPES( p_vdec->p_fifo, NULL );
504             return;
505         }
506     }
507     else
508     {
509         b_drawpicture = 1;
510         p_vdec->p_context->hurry_up = 0;
511     }
512
513     do
514     {
515         input_ExtractPES( p_vdec->p_fifo, &p_pes );
516         if( !p_pes )
517         {
518             p_vdec->p_fifo->b_error = 1;
519             return;
520         }
521 #if 0
522         if( p_vdec->i_codec_id == CODEC_ID_MPEG1VIDEO )
523         {
524             if( p_pes->i_dts )
525             {
526                 p_vdec->pts = p_pes->i_dts;
527                 p_vdec->i_frame_count = 0;
528             }
529         }
530         else
531         {
532             if( p_pes->i_pts )
533             {
534                 p_vdec->pts = p_pes->i_pts;
535                 p_vdec->i_frame_count = 0;
536             }
537         }
538 #endif
539         if( p_pes->i_pts )
540         {
541             p_vdec->pts = p_pes->i_pts;
542             p_vdec->i_frame_count = 0;
543         }
544
545         i_frame_size = p_pes->i_pes_size;
546
547         if( i_frame_size > 0 )
548         {
549             uint8_t *p_last;
550             int i_need;
551             /* XXX Don't forget that ffmpeg required a little more bytes
552              * that the real frame size */
553             i_need = i_frame_size + 16 + p_vdec->i_buffer;
554             if( p_vdec->i_buffer_size < i_need)
555             {
556                 p_last = p_vdec->p_buffer;
557                 p_vdec->p_buffer = malloc( i_need );
558                 p_vdec->i_buffer_size = i_need;
559                 if( p_vdec->i_buffer > 0 )
560                 {
561                     memcpy( p_vdec->p_buffer, p_last, p_vdec->i_buffer );
562                 }
563                 FREE( p_last );
564             }
565             i_frame_size =
566                 E_( GetPESData )( p_vdec->p_buffer + p_vdec->i_buffer,
567                                   i_frame_size ,
568                                   p_pes );
569             memset( p_vdec->p_buffer + p_vdec->i_buffer + i_frame_size,
570                     0,
571                     16 );
572         }
573         input_DeletePES( p_vdec->p_fifo->p_packets_mgt, p_pes );
574     } while( i_frame_size <= 0 );
575
576     i_frame_size += p_vdec->i_buffer;
577
578 usenextdata:
579     i_used = avcodec_decode_video( p_vdec->p_context,
580                                    p_vdec->p_ff_pic,
581                                    &b_gotpicture,
582                                    p_vdec->p_buffer,
583                                    i_frame_size );
584
585 #if 0
586     msg_Dbg( p_vdec->p_fifo,
587              "used:%d framesize:%d (%s picture)",
588              i_used, i_frame_size, b_gotpicture ? "got":"no got" );
589 #endif
590     if( i_used < 0 )
591     {
592         msg_Warn( p_vdec->p_fifo, "cannot decode one frame (%d bytes)",
593                                   i_frame_size );
594         p_vdec->i_frame_error++;
595         p_vdec->i_buffer = 0;
596         return;
597     }
598     else if( i_used < i_frame_size )
599     {
600 #if 0
601         msg_Dbg( p_vdec->p_fifo,
602                  "didn't use all memory(%d  < %d)", i_used, i_frame_size );
603 #endif
604         memmove( p_vdec->p_buffer,
605                  p_vdec->p_buffer + i_used,
606                  p_vdec->i_buffer_size - i_used );
607
608         p_vdec->i_buffer = i_frame_size - i_used;
609     }
610     else
611     {
612         p_vdec->i_buffer = 0;
613     }
614
615     if( b_gotpicture )
616     {
617         p_vdec->i_frame_count++;
618     }
619
620     /* consumed bytes */
621     i_frame_size -= i_used;
622
623    /* Update frame late count*/
624     /* I don't make statistic on decoding time */
625     if( p_vdec->pts <= mdate())
626     {
627         p_vdec->i_frame_late++;
628     }
629     else
630     {
631         p_vdec->i_frame_late = 0;
632     }
633
634     if( !b_gotpicture || p_vdec->p_ff_pic->linesize[0] == 0 || !b_drawpicture )
635     {
636         return;
637     }
638
639     if( !p_vdec->b_direct_rendering )
640     {
641         p_vdec->p_vout = ffmpeg_CreateVout( p_vdec, p_vdec->p_context );
642         if( !p_vdec->p_vout )
643         {
644             msg_Err( p_vdec->p_fifo, "cannot create vout" );
645             p_vdec->p_fifo->b_error = 1; /* abort */
646             return;
647         }
648
649         /* Get a new picture */
650         while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
651         {
652             if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error )
653             {
654                 return;
655             }
656             msleep( VOUT_OUTMEM_SLEEP );
657         }
658
659         /* fill p_picture_t from AVVideoFrame, do I410->I420 if needed */
660         ffmpeg_CopyPicture( p_pic, p_vdec->p_ff_pic, p_vdec );
661     }
662     else
663     {
664 #if LIBAVCODEC_BUILD >= 4641
665         p_pic = (picture_t *)p_vdec->p_ff_pic->opaque;
666 #else
667         p_pic = NULL; /*  f**ck gcc warning */
668 #endif
669     }
670
671     /* Do post-processing if requested */
672     /* XXX: with dr it is not a good thing if the picture will be used as
673        reference... */
674     ffmpeg_PostProcPicture( p_vdec, p_pic );
675
676     /* fix date calculation */
677     if( p_vdec->pts > 0 )
678     {
679         i_pts = p_vdec->pts;
680
681         if( p_vdec->p_context->frame_rate > 0 )
682         {
683            i_pts += (uint64_t)1000000 *
684                     ( p_vdec->i_frame_count - 1) /
685                     FRAME_RATE_BASE /
686                     p_vdec->p_context->frame_rate;
687         }
688     }
689     else
690     {
691         i_pts = mdate() + DEFAULT_PTS_DELAY;  // FIXME
692     }
693
694     vout_DatePicture( p_vdec->p_vout,
695                       p_pic,
696                       i_pts );
697
698     /* Send decoded frame to vout */
699     vout_DisplayPicture( p_vdec->p_vout, p_pic );
700
701     if( i_frame_size > 0 )
702     {
703         goto usenextdata; /* try to use all data */
704     }
705 }
706
707 /*****************************************************************************
708  * EndThread: thread destruction
709  *****************************************************************************
710  * This function is called when the thread ends after a sucessful
711  * initialization.
712  *****************************************************************************/
713 void E_( EndThread_Video )( vdec_thread_t *p_vdec )
714 {
715
716     if( p_vdec->p_pp )
717     {
718         /* release postprocessing module */
719         module_Unneed( p_vdec->p_pp, p_vdec->p_pp->p_module );
720         vlc_object_destroy( p_vdec->p_pp );
721         p_vdec->p_pp = NULL;
722     }
723
724 #if LIBAVCODEC_BUILD >= 4641
725     if( p_vdec->p_ff_pic )
726     {
727         free( p_vdec->p_ff_pic );
728     }
729 #endif
730
731     /* We are about to die. Reattach video output to p_vlc. */
732     vout_Request( p_vdec->p_fifo, p_vdec->p_vout, 0, 0, 0, 0 );
733 }
734
735 /*****************************************************************************
736  * ffmpeg_CopyPicture: copy a picture from ffmpeg internal buffers to a
737  *                     picture_t structure (when not in direct rendering mode).
738  *****************************************************************************/
739 #if LIBAVCODEC_BUILD >= 4641
740 static void ffmpeg_CopyPicture( picture_t    *p_pic,
741                                 AVVideoFrame *p_ff_pic,
742                                 vdec_thread_t *p_vdec )
743 #else
744 static void ffmpeg_CopyPicture( picture_t    *p_pic,
745                                 AVPicture *p_ff_pic,
746                                 vdec_thread_t *p_vdec )
747 #endif
748 {
749     int i_plane;
750     int i_size;
751     int i_line;
752
753     uint8_t *p_dst;
754     uint8_t *p_src;
755     int i_src_stride;
756     int i_dst_stride;
757
758     if( ffmpeg_PixFmtToChroma( p_vdec->p_context->pix_fmt ) )
759     {
760         for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
761         {
762             p_src  = p_ff_pic->data[i_plane];
763             p_dst = p_pic->p[i_plane].p_pixels;
764             i_src_stride = p_ff_pic->linesize[i_plane];
765             i_dst_stride = p_pic->p[i_plane].i_pitch;
766
767             i_size = __MIN( i_src_stride, i_dst_stride );
768             for( i_line = 0; i_line < p_pic->p[i_plane].i_lines; i_line++ )
769             {
770                 p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, i_size );
771                 p_src += i_src_stride;
772                 p_dst += i_dst_stride;
773             }
774         }
775     }
776     else
777     {
778         /* we need to convert to I420 */
779         switch( p_vdec->p_context->pix_fmt )
780         {
781 #if LIBAVCODEC_BUILD >= 4615
782             case( PIX_FMT_YUV410P ):
783                 ffmpeg_ConvertPictureI410toI420( p_pic, p_ff_pic, p_vdec );
784                 break;
785 #endif
786             default:
787                 p_vdec->p_fifo->b_error = 1;
788                 break;
789         }
790     }
791 }
792
793 /*****************************************************************************
794  * ffmpeg_PostProcPicture: Postprocessing is done here.
795  *****************************************************************************/
796 static void ffmpeg_PostProcPicture( vdec_thread_t *p_vdec, picture_t *p_pic )
797 {
798     if( ( p_vdec->i_pp_mode )&&
799         ( ( p_vdec->p_vout->render.i_chroma ==
800             VLC_FOURCC( 'I','4','2','0' ) )||
801           ( p_vdec->p_vout->render.i_chroma ==
802             VLC_FOURCC( 'Y','V','1','2' ) ) ) )
803     {
804 #if LIBAVCODEC_BUILD >= 4641
805        /* Make postproc */
806         p_vdec->p_pp->pf_postprocess( p_pic,
807                                       p_vdec->p_ff_pic->qscale_table,
808                                       p_vdec->p_ff_pic->qstride,
809                                       p_vdec->i_pp_mode );
810 #elif LIBAVCODEC_BUILD >= 4633
811         p_vdec->p_pp->pf_postprocess( p_pic,
812                                       p_vdec->p_context->display_qscale_table,
813                                       p_vdec->p_context->qstride,
814                                       p_vdec->i_pp_mode );
815 #endif
816     }
817 }
818
819 #if LIBAVCODEC_BUILD >= 4641
820 /*****************************************************************************
821  * ffmpeg_GetFrameBuf: callback used by ffmpeg to get a frame buffer.
822  *                     (used for direct rendering)
823  *****************************************************************************/
824
825 static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context,
826                                AVVideoFrame *p_ff_pic )
827 {
828     vdec_thread_t *p_vdec = (vdec_thread_t *)p_context->opaque;
829     picture_t *p_pic;
830
831     /* Check and (re)create if needed our vout */
832     p_vdec->p_vout = ffmpeg_CreateVout( p_vdec, p_vdec->p_context );
833     if( !p_vdec->p_vout )
834     {
835         msg_Err( p_vdec->p_fifo, "cannot create vout" );
836         p_vdec->p_fifo->b_error = 1; /* abort */
837         return -1;
838     }
839     p_vdec->p_vout->render.b_allow_modify_pics = 0;
840
841     /* Get a new picture */
842     while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
843     {
844         if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error )
845         {
846             return -1;
847         }
848         msleep( VOUT_OUTMEM_SLEEP );
849     }
850     p_vdec->p_context->draw_horiz_band= NULL;
851
852     p_ff_pic->opaque = (void*)p_pic;
853
854     p_ff_pic->data[0] = p_pic->p[0].p_pixels;
855     p_ff_pic->data[1] = p_pic->p[1].p_pixels;
856     p_ff_pic->data[2] = p_pic->p[2].p_pixels;
857     p_ff_pic->data[3] = NULL; /* alpha channel but I'm not sure */
858
859     p_ff_pic->linesize[0] = p_pic->p[0].i_pitch;
860     p_ff_pic->linesize[1] = p_pic->p[1].i_pitch;
861     p_ff_pic->linesize[2] = p_pic->p[2].i_pitch;
862     p_ff_pic->linesize[3] = 0;
863
864     if( p_ff_pic->reference != 0 )
865     {
866         vout_LinkPicture( p_vdec->p_vout, p_pic );
867     }
868     /* FIXME what is that, should give good value */
869     p_ff_pic->age = 256*256*256*64; // FIXME FIXME from ffmpeg
870
871     return( 0 );
872 }
873
874 static void  ffmpeg_ReleaseFrameBuf( struct AVCodecContext *p_context,
875                                      AVVideoFrame *p_ff_pic )
876 {
877     vdec_thread_t *p_vdec = (vdec_thread_t *)p_context->opaque;
878     picture_t *p_pic;
879
880     //msg_Dbg( p_vdec->p_fifo, "ffmpeg_ReleaseFrameBuf" );
881     p_pic = (picture_t*)p_ff_pic->opaque;
882
883     p_ff_pic->data[0] = NULL;
884     p_ff_pic->data[1] = NULL;
885     p_ff_pic->data[2] = NULL;
886     p_ff_pic->data[3] = NULL;
887
888     vout_UnlinkPicture( p_vdec->p_vout, p_pic );
889 }
890
891
892 #endif
893