]> git.sesse.net Git - vlc/blob - modules/codec/ffmpeg/video.c
1939c903ba346d339d411d3081318758ca2aaee5
[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.17 2003/02/18 22:33:54 gbazin 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         case PIX_FMT_YUV411P:
87 #endif
88         case PIX_FMT_BGR24:
89         default:
90             return( 0 );
91     }
92 }
93
94 /* Return a Vout */
95 static vout_thread_t *ffmpeg_CreateVout( vdec_thread_t  *p_vdec,
96                                          AVCodecContext *p_context )
97 {
98     vout_thread_t *p_vout;
99     unsigned int   i_width = p_context->width;
100     unsigned int   i_height = p_context->height;
101     uint32_t       i_chroma = ffmpeg_PixFmtToChroma( p_context->pix_fmt );
102     unsigned int   i_aspect;
103
104     if( !i_width || !i_height )
105     {
106         return( NULL ); /* Can't create a new vout without display size */
107     }
108
109     if( !i_chroma )
110     {
111         /* we make conversion if possible*/
112         i_chroma = VLC_FOURCC('I','4','2','0');
113     }
114 #if LIBAVCODEC_BUILD >= 4640
115     i_aspect = VOUT_ASPECT_FACTOR * p_context->aspect_ratio;
116     if( i_aspect == 0 )
117     {
118         i_aspect = VOUT_ASPECT_FACTOR * i_width / i_height;
119     }
120 #else
121     switch( p_context->aspect_ratio_info )
122     {
123         case( FF_ASPECT_4_3_625 ):
124         case( FF_ASPECT_4_3_525 ):
125             i_aspect = VOUT_ASPECT_FACTOR * 4 / 3;
126             break;
127         case( FF_ASPECT_16_9_625 ):
128         case( FF_ASPECT_16_9_525 ):
129             i_aspect = VOUT_ASPECT_FACTOR * 16 / 9 ;
130             break;
131         case( FF_ASPECT_SQUARE ):
132         default:
133             i_aspect = VOUT_ASPECT_FACTOR * i_width / i_height;
134             break;
135         }
136 #endif
137
138     /* Spawn a video output if there is none. First we look for our children,
139      * then we look for any other vout that might be available. */
140     p_vout = vout_Request( p_vdec->p_fifo, NULL,
141                            i_width, i_height, i_chroma, i_aspect );
142
143     return p_vout;
144 }
145
146 /*****************************************************************************
147  *
148  * Functions that initialize, decode and end the decoding process
149  *
150  * Functions exported for ffmpeg.c
151  *   * E_( InitThread_Video )
152  *   * E_( DecodeThread )
153  *   * E_( EndThread_Video )
154  *****************************************************************************/
155
156 /*****************************************************************************
157  * InitThread: initialize vdec output thread
158  *****************************************************************************
159  * This function is called from decoder_Run and performs the second step
160  * of the initialization. It returns 0 on success. Note that the thread's
161  * flag are not modified inside this function.
162  *
163  * ffmpeg codec will be open, some memory allocated. But Vout is not yet
164  * open (done after the first decoded frame)
165  *****************************************************************************/
166 int E_( InitThread_Video )( vdec_thread_t *p_vdec )
167 {
168     int i_tmp;
169 #if LIBAVCODEC_BUILD >= 4645
170     p_vdec->p_ff_pic = avcodec_alloc_frame();
171 #elif LIBAVCODEC_BUILD >= 4641
172     p_vdec->p_ff_pic = avcodec_alloc_picture();
173 #else
174     p_vdec->p_ff_pic = &p_vdec->ff_pic;
175 #endif
176
177     if( ( p_vdec->p_format = (BITMAPINFOHEADER *)p_vdec->p_fifo->p_bitmapinfoheader) != NULL )
178     {
179         /* ***** Fill p_context with init values ***** */
180         p_vdec->p_context->width  = p_vdec->p_format->biWidth;
181         p_vdec->p_context->height = p_vdec->p_format->biHeight;
182
183     }
184     else
185     {
186         msg_Warn( p_vdec->p_fifo, "display informations missing" );
187         p_vdec->p_format = NULL;
188     }
189
190
191     /*  ***** Get configuration of ffmpeg plugin ***** */
192 #if LIBAVCODEC_BUILD >= 4611
193     i_tmp = config_GetInt( p_vdec->p_fifo, "ffmpeg-workaround-bugs" );
194     p_vdec->p_context->workaround_bugs  = __MAX( __MIN( i_tmp, 99 ), 0 );
195
196     i_tmp = config_GetInt( p_vdec->p_fifo, "ffmpeg-error-resilience" );
197     p_vdec->p_context->error_resilience = __MAX( __MIN( i_tmp, 99 ), -1 );
198 #endif
199 #if LIBAVCODEC_BUILD >= 4614
200     if( config_GetInt( p_vdec->p_fifo, "grayscale" ) )
201     {
202         p_vdec->p_context->flags|= CODEC_FLAG_GRAY;
203     }
204 #endif
205
206     p_vdec->b_hurry_up = config_GetInt(p_vdec->p_fifo, "ffmpeg-hurry-up");
207
208     p_vdec->b_direct_rendering = 0;
209
210 #if 0
211     /* check if codec support truncated frames */
212 //    if( p_vdec->p_codec->capabilities & CODEC_FLAG_TRUNCATED )
213     if( p_vdec->i_codec_id == CODEC_ID_MPEG1VIDEO)
214     {
215         msg_Dbg( p_vdec->p_fifo, "CODEC_FLAG_TRUNCATED supported" );
216         p_vdec->p_context->flags |= CODEC_FLAG_TRUNCATED;
217     }
218 #endif
219
220     /* ***** Open the codec ***** */
221     if( avcodec_open(p_vdec->p_context, p_vdec->p_codec) < 0 )
222     {
223         msg_Err( p_vdec->p_fifo, "cannot open codec (%s)",
224                                  p_vdec->psz_namecodec );
225         return( -1 );
226     }
227     else
228     {
229         msg_Dbg( p_vdec->p_fifo, "ffmpeg codec (%s) started",
230                                  p_vdec->psz_namecodec );
231     }
232
233 #if LIBAVCODEC_BUILD >= 4641
234     if( config_GetInt( p_vdec->p_fifo, "ffmpeg-dr" ) &&
235         p_vdec->p_codec->capabilities & CODEC_CAP_DR1 &&
236         ffmpeg_PixFmtToChroma( p_vdec->p_context->pix_fmt ) )
237     {
238         /* FIXME: some codecs set pix_fmt only after a frame
239          * has been decoded. */
240
241         msg_Dbg( p_vdec->p_fifo, "using direct rendering" );
242         p_vdec->b_direct_rendering = 1;
243         p_vdec->p_context->flags|= CODEC_FLAG_EMU_EDGE;
244         p_vdec->p_context->get_buffer     = ffmpeg_GetFrameBuf;
245         p_vdec->p_context->release_buffer = ffmpeg_ReleaseFrameBuf;
246         p_vdec->p_context->opaque = p_vdec;
247
248     }
249 #endif
250
251     /* ***** init this codec with special data ***** */
252     if( p_vdec->p_format &&
253             p_vdec->p_format->biSize > sizeof(BITMAPINFOHEADER) )
254     {
255         int b_gotpicture;
256
257         switch( p_vdec->i_codec_id )
258         {
259             case( CODEC_ID_MPEG4 ):
260 #if 1
261                 avcodec_decode_video( p_vdec->p_context, p_vdec->p_ff_pic,
262                                       &b_gotpicture,
263                                       (void *)&p_vdec->p_format[1],
264                                       p_vdec->p_format->biSize
265                                         - sizeof(BITMAPINFOHEADER) );
266 #endif
267                 break;
268             default:
269                 if( p_vdec->p_fifo->i_fourcc == FOURCC_MP4S ||
270                     p_vdec->p_fifo->i_fourcc == FOURCC_mp4s ||
271                     p_vdec->p_fifo->i_fourcc == FOURCC_M4S2 ||
272                     p_vdec->p_fifo->i_fourcc == FOURCC_m4s2 ||
273                     p_vdec->p_fifo->i_fourcc == FOURCC_WMV2 ||
274                     p_vdec->p_fifo->i_fourcc == FOURCC_MJPG ||
275                     p_vdec->p_fifo->i_fourcc == FOURCC_mjpg ||
276                     p_vdec->p_fifo->i_fourcc == FOURCC_mjpa ||
277                     p_vdec->p_fifo->i_fourcc == FOURCC_mjpb )
278                 {
279                     p_vdec->p_context->extradata_size =
280                         p_vdec->p_format->biSize - sizeof(BITMAPINFOHEADER);
281                     p_vdec->p_context->extradata =
282                         malloc( p_vdec->p_context->extradata_size );
283                     memcpy( p_vdec->p_context->extradata,
284                             &p_vdec->p_format[1],
285                             p_vdec->p_context->extradata_size );
286                 }
287
288                 break;
289         }
290     }
291
292     /* ***** Load post processing ***** */
293
294     /* get overridding settings */
295     p_vdec->i_pp_mode = 0;
296     if( config_GetInt( p_vdec->p_fifo, "ffmpeg-db-yv" ) )
297         p_vdec->i_pp_mode |= PP_DEBLOCK_Y_V;
298     if( config_GetInt( p_vdec->p_fifo, "ffmpeg-db-yh" ) )
299         p_vdec->i_pp_mode |= PP_DEBLOCK_Y_H;
300     if( config_GetInt( p_vdec->p_fifo, "ffmpeg-db-cv" ) )
301         p_vdec->i_pp_mode |= PP_DEBLOCK_C_V;
302     if( config_GetInt( p_vdec->p_fifo, "ffmpeg-db-ch" ) )
303         p_vdec->i_pp_mode |= PP_DEBLOCK_C_H;
304     if( config_GetInt( p_vdec->p_fifo, "ffmpeg-dr-y" ) )
305         p_vdec->i_pp_mode |= PP_DERING_Y;
306     if( config_GetInt( p_vdec->p_fifo, "ffmpeg-dr-c" ) )
307         p_vdec->i_pp_mode |= PP_DERING_C;
308
309     if( ( config_GetInt( p_vdec->p_fifo, "ffmpeg-pp-q" ) > 0 )||
310         ( config_GetInt( p_vdec->p_fifo, "ffmpeg-pp-auto" )  )||
311         ( p_vdec->i_pp_mode != 0 ) )
312     {
313         /* check if the codec support postproc. */
314         switch( p_vdec->i_codec_id )
315         {
316 #if LIBAVCODEC_BUILD > 4608
317             case( CODEC_ID_MSMPEG4V1 ):
318             case( CODEC_ID_MSMPEG4V2 ):
319             case( CODEC_ID_MSMPEG4V3 ):
320 #else
321             case( CODEC_ID_MSMPEG4 ):
322 #endif
323             case( CODEC_ID_MPEG4 ):
324             case( CODEC_ID_H263 ):
325 //            case( CODEC_ID_H263P ): I don't use it up to now
326             case( CODEC_ID_H263I ):
327                 /* Ok we can make postprocessing :)) */
328                 /* first try to get a postprocess module */
329 #if LIBAVCODEC_BUILD >= 4633
330                 p_vdec->p_pp = vlc_object_create( p_vdec->p_fifo,
331                                                   sizeof( postprocessing_t ) );
332                 p_vdec->p_pp->psz_object_name = "postprocessing";
333                 p_vdec->p_pp->p_module =
334                    module_Need( p_vdec->p_pp, "postprocessing", "$ffmpeg-pp" );
335
336                 if( !p_vdec->p_pp->p_module )
337                 {
338                     msg_Warn( p_vdec->p_fifo,
339                               "no suitable postprocessing module" );
340                     vlc_object_destroy( p_vdec->p_pp );
341                     p_vdec->p_pp = NULL;
342                     p_vdec->i_pp_mode = 0;
343                 }
344                 else
345                 {
346                     /* get mode upon quality */
347                     p_vdec->i_pp_mode |=
348                         p_vdec->p_pp->pf_getmode(
349                               config_GetInt( p_vdec->p_fifo, "ffmpeg-pp-q" ),
350                               config_GetInt( p_vdec->p_fifo, "ffmpeg-pp-auto" )
351                                                 );
352                 }
353 #else
354                 p_vdec->i_pp_mode = 0;
355                 msg_Warn( p_vdec->p_fifo,
356                           "post-processing not supported, upgrade ffmpeg" );
357 #endif
358                 break;
359             default:
360                 p_vdec->i_pp_mode = 0;
361                 msg_Warn( p_vdec->p_fifo,
362                           "Post processing unsupported for this codec" );
363                 break;
364         }
365
366     }
367 //    memset( &p_vdec->statistic, 0, sizeof( statistic_t ) );
368
369     return( 0 );
370 }
371
372 /*****************************************************************************
373  * DecodeThread: Called to decode one frame
374  *****************************************************************************
375  * We have to get a frame stored in a pes, give it to ffmpeg decoder and send
376  * the image to the output.
377  *****************************************************************************/
378 void  E_( DecodeThread_Video )( vdec_thread_t *p_vdec )
379 {
380     pes_packet_t    *p_pes;
381     int     i_frame_size;
382     int     i_used;
383     int     b_drawpicture;
384     int     b_gotpicture;
385     picture_t *p_pic;                                    /* videolan picture */
386     mtime_t   i_pts;
387
388     /* TODO implement it in a better way */
389     /* A good idea could be to decode all I pictures and see for the other */
390     if( ( p_vdec->b_hurry_up )&& ( p_vdec->i_frame_late > 4 ) )
391     {
392         b_drawpicture = 0;
393         if( p_vdec->i_frame_late < 8 )
394         {
395             p_vdec->p_context->hurry_up = 2;
396         }
397         else
398         {
399             /* too much late picture, won't decode
400                but break picture until a new I, and for mpeg4 ...*/
401             p_vdec->i_frame_late--; /* needed else it will never be decrease */
402             input_ExtractPES( p_vdec->p_fifo, NULL );
403             return;
404         }
405     }
406     else
407     {
408         b_drawpicture = 1;
409         p_vdec->p_context->hurry_up = 0;
410     }
411
412     if( !p_vdec->p_context->width || !p_vdec->p_context->height )
413     {
414         p_vdec->p_context->hurry_up = 5;
415     }
416
417     do
418     {
419         input_ExtractPES( p_vdec->p_fifo, &p_pes );
420         if( !p_pes )
421         {
422             p_vdec->p_fifo->b_error = 1;
423             return;
424         }
425 #if 0
426         if( p_vdec->i_codec_id == CODEC_ID_MPEG1VIDEO )
427         {
428             if( p_pes->i_dts )
429             {
430                 p_vdec->pts = p_pes->i_dts;
431                 p_vdec->i_frame_count = 0;
432             }
433         }
434         else
435         {
436             if( p_pes->i_pts )
437             {
438                 p_vdec->pts = p_pes->i_pts;
439                 p_vdec->i_frame_count = 0;
440             }
441         }
442 #endif
443         if( p_pes->i_pts )
444         {
445             p_vdec->pts = p_pes->i_pts;
446             p_vdec->i_frame_count = 0;
447         }
448
449         i_frame_size = p_pes->i_pes_size;
450
451         if( i_frame_size > 0 )
452         {
453             uint8_t *p_last;
454             int i_need;
455             /* XXX Don't forget that ffmpeg required a little more bytes
456              * that the real frame size */
457             i_need = i_frame_size + 16 + p_vdec->i_buffer;
458             if( p_vdec->i_buffer_size < i_need)
459             {
460                 p_last = p_vdec->p_buffer;
461                 p_vdec->p_buffer = malloc( i_need );
462                 p_vdec->i_buffer_size = i_need;
463                 if( p_vdec->i_buffer > 0 )
464                 {
465                     memcpy( p_vdec->p_buffer, p_last, p_vdec->i_buffer );
466                 }
467                 FREE( p_last );
468             }
469             i_frame_size =
470                 E_( GetPESData )( p_vdec->p_buffer + p_vdec->i_buffer,
471                                   i_frame_size ,
472                                   p_pes );
473             memset( p_vdec->p_buffer + p_vdec->i_buffer + i_frame_size,
474                     0,
475                     16 );
476         }
477         input_DeletePES( p_vdec->p_fifo->p_packets_mgt, p_pes );
478     } while( i_frame_size <= 0 );
479
480     i_frame_size += p_vdec->i_buffer;
481
482 usenextdata:
483     i_used = avcodec_decode_video( p_vdec->p_context,
484                                    p_vdec->p_ff_pic,
485                                    &b_gotpicture,
486                                    p_vdec->p_buffer,
487                                    i_frame_size );
488
489 #if 0
490     msg_Dbg( p_vdec->p_fifo,
491              "used:%d framesize:%d (%s picture)",
492              i_used, i_frame_size, b_gotpicture ? "got":"no got" );
493 #endif
494     if( i_used < 0 )
495     {
496         msg_Warn( p_vdec->p_fifo, "cannot decode one frame (%d bytes)",
497                                   i_frame_size );
498         p_vdec->i_frame_error++;
499         p_vdec->i_buffer = 0;
500         return;
501     }
502     else if( i_used < i_frame_size )
503     {
504 #if 0
505         msg_Dbg( p_vdec->p_fifo,
506                  "didn't use all memory(%d  < %d)", i_used, i_frame_size );
507 #endif
508         memmove( p_vdec->p_buffer,
509                  p_vdec->p_buffer + i_used,
510                  p_vdec->i_buffer_size - i_used );
511
512         p_vdec->i_buffer = i_frame_size - i_used;
513     }
514     else
515     {
516         p_vdec->i_buffer = 0;
517     }
518
519     if( b_gotpicture )
520     {
521         p_vdec->i_frame_count++;
522     }
523
524     /* consumed bytes */
525     i_frame_size -= i_used;
526
527    /* Update frame late count*/
528     /* I don't make statistic on decoding time */
529     if( p_vdec->pts <= mdate())
530     {
531         p_vdec->i_frame_late++;
532     }
533     else
534     {
535         p_vdec->i_frame_late = 0;
536     }
537
538     if( !b_gotpicture || p_vdec->p_ff_pic->linesize[0] == 0 || !b_drawpicture )
539     {
540         return;
541     }
542
543     if( !p_vdec->b_direct_rendering )
544     {
545         p_vdec->p_vout = ffmpeg_CreateVout( p_vdec, p_vdec->p_context );
546         if( !p_vdec->p_vout )
547         {
548             msg_Err( p_vdec->p_fifo, "cannot create vout" );
549             p_vdec->p_fifo->b_error = 1; /* abort */
550             return;
551         }
552
553         /* Get a new picture */
554         while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
555         {
556             if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error )
557             {
558                 return;
559             }
560             msleep( VOUT_OUTMEM_SLEEP );
561         }
562
563         /* fill p_picture_t from AVVideoFrame and do chroma conversion
564          * if needed */
565         ffmpeg_CopyPicture( p_pic, p_vdec->p_ff_pic, p_vdec );
566     }
567     else
568     {
569 #if LIBAVCODEC_BUILD >= 4641
570         p_pic = (picture_t *)p_vdec->p_ff_pic->opaque;
571 #else
572         p_pic = NULL; /*  f**ck gcc warning */
573 #endif
574     }
575
576     /* Do post-processing if requested */
577     /* XXX: with dr it is not a good thing if the picture will be used as
578        reference... */
579     ffmpeg_PostProcPicture( p_vdec, p_pic );
580
581     /* fix date calculation */
582     if( p_vdec->pts > 0 )
583     {
584         i_pts = p_vdec->pts;
585
586         if( p_vdec->p_context->frame_rate > 0 )
587         {
588            i_pts += (uint64_t)1000000 *
589                     ( p_vdec->i_frame_count - 1) /
590                     FRAME_RATE_BASE /
591                     p_vdec->p_context->frame_rate;
592         }
593     }
594     else
595     {
596         i_pts = mdate() + DEFAULT_PTS_DELAY;  // FIXME
597     }
598
599     vout_DatePicture( p_vdec->p_vout,
600                       p_pic,
601                       i_pts );
602
603     /* Send decoded frame to vout */
604     vout_DisplayPicture( p_vdec->p_vout, p_pic );
605
606     if( i_frame_size > 0 )
607     {
608         goto usenextdata; /* try to use all data */
609     }
610 }
611
612 /*****************************************************************************
613  * EndThread: thread destruction
614  *****************************************************************************
615  * This function is called when the thread ends after a sucessful
616  * initialization.
617  *****************************************************************************/
618 void E_( EndThread_Video )( vdec_thread_t *p_vdec )
619 {
620
621     if( p_vdec->p_pp )
622     {
623         /* release postprocessing module */
624         module_Unneed( p_vdec->p_pp, p_vdec->p_pp->p_module );
625         vlc_object_destroy( p_vdec->p_pp );
626         p_vdec->p_pp = NULL;
627     }
628
629 #if LIBAVCODEC_BUILD >= 4641
630     if( p_vdec->p_ff_pic )
631     {
632         free( p_vdec->p_ff_pic );
633     }
634 #endif
635
636     /* We are about to die. Reattach video output to p_vlc. */
637     vout_Request( p_vdec->p_fifo, p_vdec->p_vout, 0, 0, 0, 0 );
638 }
639
640 /*****************************************************************************
641  * ffmpeg_CopyPicture: copy a picture from ffmpeg internal buffers to a
642  *                     picture_t structure (when not in direct rendering mode).
643  *****************************************************************************/
644 #if LIBAVCODEC_BUILD >= 4641
645 static void ffmpeg_CopyPicture( picture_t    *p_pic,
646                                 AVFrame *p_ff_pic,
647                                 vdec_thread_t *p_vdec )
648 #else
649 static void ffmpeg_CopyPicture( picture_t    *p_pic,
650                                 AVPicture *p_ff_pic,
651                                 vdec_thread_t *p_vdec )
652 #endif
653 {
654     int i_plane;
655     int i_size;
656     int i_line;
657
658     uint8_t *p_dst;
659     uint8_t *p_src;
660     int i_src_stride;
661     int i_dst_stride;
662
663     if( ffmpeg_PixFmtToChroma( p_vdec->p_context->pix_fmt ) )
664     {
665         for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
666         {
667             p_src  = p_ff_pic->data[i_plane];
668             p_dst = p_pic->p[i_plane].p_pixels;
669             i_src_stride = p_ff_pic->linesize[i_plane];
670             i_dst_stride = p_pic->p[i_plane].i_pitch;
671
672             i_size = __MIN( i_src_stride, i_dst_stride );
673             for( i_line = 0; i_line < p_pic->p[i_plane].i_lines; i_line++ )
674             {
675                 p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, i_size );
676                 p_src += i_src_stride;
677                 p_dst += i_dst_stride;
678             }
679         }
680     }
681     else
682     {
683         /* we need to convert to I420 */
684         switch( p_vdec->p_context->pix_fmt )
685         {
686             AVPicture dest_pic;
687             int i;
688
689 #if LIBAVCODEC_BUILD >= 4615
690             case( PIX_FMT_YUV410P ):
691             case( PIX_FMT_YUV411P ):
692                 for( i = 0; i < p_pic->i_planes; i++ )
693                 {
694                     dest_pic.data[i] = p_pic->p[i].p_pixels;
695                     dest_pic.linesize[i] = p_pic->p[i].i_pitch;
696                 }
697                 img_convert( &dest_pic, PIX_FMT_YUV420P,
698                              (AVPicture *)p_ff_pic,
699                              p_vdec->p_context->pix_fmt,
700                              p_vdec->p_context->width,
701                              p_vdec->p_context->height );
702                 break;
703 #endif
704             default:
705                 msg_Err( p_vdec->p_fifo, "don't know how to convert chroma %i",
706                          p_vdec->p_context->pix_fmt );
707                 p_vdec->p_fifo->b_error = 1;
708                 break;
709         }
710     }
711 }
712
713 /*****************************************************************************
714  * ffmpeg_PostProcPicture: Postprocessing is done here.
715  *****************************************************************************/
716 static void ffmpeg_PostProcPicture( vdec_thread_t *p_vdec, picture_t *p_pic )
717 {
718     if( ( p_vdec->i_pp_mode )&&
719         ( ( p_vdec->p_vout->render.i_chroma ==
720             VLC_FOURCC( 'I','4','2','0' ) )||
721           ( p_vdec->p_vout->render.i_chroma ==
722             VLC_FOURCC( 'Y','V','1','2' ) ) ) )
723     {
724 #if LIBAVCODEC_BUILD >= 4641
725        /* Make postproc */
726         p_vdec->p_pp->pf_postprocess( p_pic,
727                                       p_vdec->p_ff_pic->qscale_table,
728                                       p_vdec->p_ff_pic->qstride,
729                                       p_vdec->i_pp_mode );
730 #elif LIBAVCODEC_BUILD >= 4633
731         p_vdec->p_pp->pf_postprocess( p_pic,
732                                       p_vdec->p_context->display_qscale_table,
733                                       p_vdec->p_context->qstride,
734                                       p_vdec->i_pp_mode );
735 #endif
736     }
737 }
738
739 #if LIBAVCODEC_BUILD >= 4641
740 /*****************************************************************************
741  * ffmpeg_GetFrameBuf: callback used by ffmpeg to get a frame buffer.
742  *                     (used for direct rendering)
743  *****************************************************************************/
744
745 static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context,
746                                AVFrame *p_ff_pic )
747 {
748     vdec_thread_t *p_vdec = (vdec_thread_t *)p_context->opaque;
749     picture_t *p_pic;
750
751     /* Check and (re)create if needed our vout */
752     p_vdec->p_vout = ffmpeg_CreateVout( p_vdec, p_vdec->p_context );
753     if( !p_vdec->p_vout )
754     {
755         msg_Err( p_vdec->p_fifo, "cannot create vout" );
756         p_vdec->p_fifo->b_error = 1; /* abort */
757         return -1;
758     }
759     p_vdec->p_vout->render.b_allow_modify_pics = 0;
760
761     /* Get a new picture */
762     while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
763     {
764         if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error )
765         {
766             return -1;
767         }
768         msleep( VOUT_OUTMEM_SLEEP );
769     }
770     p_vdec->p_context->draw_horiz_band= NULL;
771
772     p_ff_pic->opaque = (void*)p_pic;
773 #if LIBAVCODEC_BUILD >= 4645
774     p_ff_pic->type = FF_BUFFER_TYPE_USER;
775 #endif
776     p_ff_pic->data[0] = p_pic->p[0].p_pixels;
777     p_ff_pic->data[1] = p_pic->p[1].p_pixels;
778     p_ff_pic->data[2] = p_pic->p[2].p_pixels;
779     p_ff_pic->data[3] = NULL; /* alpha channel but I'm not sure */
780
781     p_ff_pic->linesize[0] = p_pic->p[0].i_pitch;
782     p_ff_pic->linesize[1] = p_pic->p[1].i_pitch;
783     p_ff_pic->linesize[2] = p_pic->p[2].i_pitch;
784     p_ff_pic->linesize[3] = 0;
785
786     if( p_ff_pic->reference != 0 )
787     {
788         vout_LinkPicture( p_vdec->p_vout, p_pic );
789     }
790     /* FIXME what is that, should give good value */
791     p_ff_pic->age = 256*256*256*64; // FIXME FIXME from ffmpeg
792
793     return( 0 );
794 }
795
796 static void  ffmpeg_ReleaseFrameBuf( struct AVCodecContext *p_context,
797                                      AVFrame *p_ff_pic )
798 {
799     vdec_thread_t *p_vdec = (vdec_thread_t *)p_context->opaque;
800     picture_t *p_pic;
801
802     //msg_Dbg( p_vdec->p_fifo, "ffmpeg_ReleaseFrameBuf" );
803     p_pic = (picture_t*)p_ff_pic->opaque;
804
805     p_ff_pic->data[0] = NULL;
806     p_ff_pic->data[1] = NULL;
807     p_ff_pic->data[2] = NULL;
808     p_ff_pic->data[3] = NULL;
809
810     vout_UnlinkPicture( p_vdec->p_vout, p_pic );
811 }
812
813 #endif