]> git.sesse.net Git - vlc/blob - modules/codec/ffmpeg/video.c
a6fccdda5f30fabb93c8e759c385140ff7cf21f6
[vlc] / modules / codec / ffmpeg / video.c
1 /*****************************************************************************\r
2  * video.c: video decoder using the ffmpeg library\r
3  *****************************************************************************\r
4  * Copyright (C) 1999-2001 VideoLAN\r
5  * $Id$\r
6  *\r
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>\r
8  *          Gildas Bazin <gbazin@videolan.org>\r
9  *\r
10  * This program is free software; you can redistribute it and/or modify\r
11  * it under the terms of the GNU General Public License as published by\r
12  * the Free Software Foundation; either version 2 of the License, or\r
13  * (at your option) any later version.\r
14  *\r
15  * This program is distributed in the hope that it will be useful,\r
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
18  * GNU General Public License for more details.\r
19  *\r
20  * You should have received a copy of the GNU General Public License\r
21  * along with this program; if not, write to the Free Software\r
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.\r
23  *****************************************************************************/\r
24 \r
25 /*****************************************************************************\r
26  * Preamble\r
27  *****************************************************************************/\r
28 #include <vlc/vlc.h>\r
29 #include <vlc/decoder.h>\r
30 \r
31 /* ffmpeg header */\r
32 #ifdef HAVE_FFMPEG_AVCODEC_H\r
33 #   include <ffmpeg/avcodec.h>\r
34 #else\r
35 #   include <avcodec.h>\r
36 #endif\r
37 \r
38 #include "ffmpeg.h"\r
39 \r
40 /*****************************************************************************\r
41  * decoder_sys_t : decoder descriptor\r
42  *****************************************************************************/\r
43 struct decoder_sys_t\r
44 {\r
45     /* Common part between video and audio decoder */\r
46     int i_cat;\r
47     int i_codec_id;\r
48     char *psz_namecodec;\r
49 \r
50     AVCodecContext      *p_context;\r
51     AVCodec             *p_codec;\r
52 \r
53     /* Video decoder specific part */\r
54     mtime_t input_pts;\r
55     mtime_t input_dts;\r
56     mtime_t i_pts;\r
57 \r
58     AVFrame          *p_ff_pic;\r
59     BITMAPINFOHEADER *p_format;\r
60 \r
61     /* for frame skipping algo */\r
62     int b_hurry_up;\r
63     int i_frame_skip;\r
64 \r
65     /* how many decoded frames are late */\r
66     int     i_late_frames;\r
67     mtime_t i_late_frames_start;\r
68 \r
69     /* for direct rendering */\r
70     int b_direct_rendering;\r
71 \r
72     vlc_bool_t b_has_b_frames;\r
73 \r
74     /* Hack to force display of still pictures */\r
75     vlc_bool_t b_first_frame;\r
76 \r
77     int i_buffer_orig, i_buffer;\r
78     char *p_buffer_orig, *p_buffer;\r
79 \r
80     /* Postprocessing handle */\r
81     void *p_pp;\r
82     vlc_bool_t b_pp;\r
83     vlc_bool_t b_pp_async;\r
84     vlc_bool_t b_pp_init;\r
85 };\r
86 \r
87 /* FIXME (dummy palette for now) */\r
88 static AVPaletteControl palette_control;\r
89 \r
90 /*****************************************************************************\r
91  * Local prototypes\r
92  *****************************************************************************/\r
93 static void ffmpeg_CopyPicture    ( decoder_t *, picture_t *, AVFrame * );\r
94 static int  ffmpeg_GetFrameBuf    ( struct AVCodecContext *, AVFrame * );\r
95 static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *, AVFrame * );\r
96 \r
97 static uint32_t ffmpeg_CodecTag( vlc_fourcc_t fcc )\r
98 {\r
99     uint8_t *p = (uint8_t*)&fcc;\r
100     return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);\r
101 }\r
102 \r
103 /*****************************************************************************\r
104  * Local Functions\r
105  *****************************************************************************/\r
106 static uint32_t ffmpeg_PixFmtToChroma( int i_ff_chroma )\r
107 {\r
108     switch( i_ff_chroma )\r
109     {\r
110     case PIX_FMT_YUV420P:\r
111         return VLC_FOURCC('I','4','2','0');\r
112     case PIX_FMT_YUV422P:\r
113         return VLC_FOURCC('I','4','2','2');\r
114     case PIX_FMT_YUV444P:\r
115         return VLC_FOURCC('I','4','4','4');\r
116 \r
117     case PIX_FMT_YUV422:\r
118         return VLC_FOURCC('Y','U','Y','2');\r
119 \r
120     case PIX_FMT_RGB555:\r
121         return VLC_FOURCC('R','V','1','5');\r
122     case PIX_FMT_RGB565:\r
123         return VLC_FOURCC('R','V','1','6');\r
124     case PIX_FMT_RGB24:\r
125         return VLC_FOURCC('R','V','2','4');\r
126     case PIX_FMT_RGBA32:\r
127         return VLC_FOURCC('R','V','3','2');\r
128     case PIX_FMT_GRAY8:\r
129         return VLC_FOURCC('G','R','E','Y');\r
130 \r
131     case PIX_FMT_YUV410P:\r
132     case PIX_FMT_YUV411P:\r
133     case PIX_FMT_BGR24:\r
134     default:\r
135         return 0;\r
136     }\r
137 }\r
138 \r
139 /* Returns a new picture buffer */\r
140 static inline picture_t *ffmpeg_NewPictBuf( decoder_t *p_dec,\r
141                                             AVCodecContext *p_context )\r
142 {\r
143     decoder_sys_t *p_sys = p_dec->p_sys;\r
144     picture_t *p_pic;\r
145 \r
146     p_dec->fmt_out.video.i_width = p_context->width;\r
147     p_dec->fmt_out.video.i_height = p_context->height;\r
148     p_dec->fmt_out.i_codec = ffmpeg_PixFmtToChroma( p_context->pix_fmt );\r
149 \r
150     if( !p_context->width || !p_context->height )\r
151     {\r
152         return NULL; /* invalid display size */\r
153     }\r
154 \r
155     if( !p_dec->fmt_out.i_codec )\r
156     {\r
157         /* we make conversion if possible*/\r
158         p_dec->fmt_out.i_codec = VLC_FOURCC('I','4','2','0');\r
159     }\r
160 \r
161     /* If an aspect-ratio was specified in the input format then force it */\r
162     if( p_dec->fmt_in.video.i_aspect )\r
163     {\r
164         p_dec->fmt_out.video.i_aspect = p_dec->fmt_in.video.i_aspect;\r
165     }\r
166     else\r
167     {\r
168 #if LIBAVCODEC_BUILD >= 4687\r
169         p_dec->fmt_out.video.i_aspect =\r
170             VOUT_ASPECT_FACTOR * ( av_q2d(p_context->sample_aspect_ratio) *\r
171                 p_context->width / p_context->height );\r
172 #else\r
173         p_dec->fmt_out.video.i_aspect =\r
174             VOUT_ASPECT_FACTOR * p_context->aspect_ratio;\r
175 #endif\r
176         if( p_dec->fmt_out.video.i_aspect == 0 )\r
177         {\r
178             p_dec->fmt_out.video.i_aspect =\r
179                 VOUT_ASPECT_FACTOR * p_context->width / p_context->height;\r
180         }\r
181     }\r
182 \r
183     if( p_context->frame_rate > 0 && p_context->frame_rate_base > 0 )\r
184     {\r
185         p_dec->fmt_out.video.i_frame_rate = p_context->frame_rate;\r
186         p_dec->fmt_out.video.i_frame_rate_base = p_context->frame_rate_base;\r
187     }\r
188 \r
189     p_pic = p_dec->pf_vout_buffer_new( p_dec );\r
190 \r
191 #ifdef LIBAVCODEC_PP\r
192     if( p_sys->p_pp && p_sys->b_pp && !p_sys->b_pp_init )\r
193     {\r
194         E_(InitPostproc)( p_dec, p_sys->p_pp, p_context->width,\r
195                           p_context->height, p_context->pix_fmt );\r
196         p_sys->b_pp_init = VLC_TRUE;\r
197     }\r
198 #endif\r
199 \r
200     return p_pic;\r
201 }\r
202 \r
203 /*****************************************************************************\r
204  * InitVideo: initialize the video decoder\r
205  *****************************************************************************\r
206  * the ffmpeg codec will be opened, some memory allocated. The vout is not yet\r
207  * opened (done after the first decoded frame).\r
208  *****************************************************************************/\r
209 int E_(InitVideoDec)( decoder_t *p_dec, AVCodecContext *p_context,\r
210                       AVCodec *p_codec, int i_codec_id, char *psz_namecodec )\r
211 {\r
212     decoder_sys_t *p_sys;\r
213     vlc_value_t lockval;\r
214     vlc_value_t val;\r
215 \r
216     var_Get( p_dec->p_libvlc, "avcodec", &lockval );\r
217 \r
218     /* Allocate the memory needed to store the decoder's structure */\r
219     if( ( p_dec->p_sys = p_sys =\r
220           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )\r
221     {\r
222         msg_Err( p_dec, "out of memory" );\r
223         return VLC_EGENERIC;\r
224     }\r
225 \r
226     p_dec->p_sys->p_context = p_context;\r
227     p_dec->p_sys->p_codec = p_codec;\r
228     p_dec->p_sys->i_codec_id = i_codec_id;\r
229     p_dec->p_sys->psz_namecodec = psz_namecodec;\r
230     p_sys->p_ff_pic = avcodec_alloc_frame();\r
231 \r
232     /* ***** Fill p_context with init values ***** */\r
233     /* FIXME: remove when ffmpeg deals properly with avc1 */\r
234     if( p_dec->fmt_in.i_codec != VLC_FOURCC('a','v','c','1') )\r
235     /* End FIXME */\r
236     p_sys->p_context->codec_tag = ffmpeg_CodecTag( p_dec->fmt_in.i_codec );\r
237     p_sys->p_context->width  = p_dec->fmt_in.video.i_width;\r
238     p_sys->p_context->height = p_dec->fmt_in.video.i_height;\r
239     p_sys->p_context->bits_per_sample = p_dec->fmt_in.video.i_bits_per_pixel;\r
240 \r
241     /*  ***** Get configuration of ffmpeg plugin ***** */\r
242     p_sys->p_context->workaround_bugs =\r
243         config_GetInt( p_dec, "ffmpeg-workaround-bugs" );\r
244     p_sys->p_context->error_resilience =\r
245         config_GetInt( p_dec, "ffmpeg-error-resilience" );\r
246 \r
247     var_Create( p_dec, "grayscale", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );\r
248     var_Get( p_dec, "grayscale", &val );\r
249     if( val.b_bool ) p_sys->p_context->flags |= CODEC_FLAG_GRAY;\r
250 \r
251     var_Create( p_dec, "ffmpeg-vismv", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );\r
252     var_Get( p_dec, "ffmpeg-vismv", &val );\r
253 #if LIBAVCODEC_BUILD >= 4698\r
254     if( val.i_int ) p_sys->p_context->debug_mv = val.i_int;\r
255 #endif\r
256 \r
257     var_Create( p_dec, "ffmpeg-lowres", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );\r
258     var_Get( p_dec, "ffmpeg-lowres", &val );\r
259 #if LIBAVCODEC_BUILD >= 4723\r
260     if( val.i_int > 0 && val.i_int <= 2 ) p_sys->p_context->lowres = val.i_int;\r
261 #endif\r
262 \r
263     /* ***** ffmpeg frame skipping ***** */\r
264     var_Create( p_dec, "ffmpeg-hurry-up", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );\r
265     var_Get( p_dec, "ffmpeg-hurry-up", &val );\r
266     p_sys->b_hurry_up = val.b_bool;\r
267 \r
268     /* ***** ffmpeg direct rendering ***** */\r
269     p_sys->b_direct_rendering = 0;\r
270     var_Create( p_dec, "ffmpeg-dr", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );\r
271     var_Get( p_dec, "ffmpeg-dr", &val );\r
272     if( val.b_bool && (p_sys->p_codec->capabilities & CODEC_CAP_DR1) &&\r
273         ffmpeg_PixFmtToChroma( p_sys->p_context->pix_fmt ) &&\r
274         /* Apparently direct rendering doesn't work with YUV422P */\r
275         p_sys->p_context->pix_fmt != PIX_FMT_YUV422P &&\r
276         /* H264 uses too many reference frames */\r
277         p_sys->i_codec_id != CODEC_ID_H264 &&\r
278         !(p_sys->p_context->width % 16) && !(p_sys->p_context->height % 16) &&\r
279 #if LIBAVCODEC_BUILD >= 4698\r
280         !p_sys->p_context->debug_mv )\r
281 #else\r
282         1 )\r
283 #endif\r
284     {\r
285         /* Some codecs set pix_fmt only after the 1st frame has been decoded,\r
286          * so we need to do another check in ffmpeg_GetFrameBuf() */\r
287         p_sys->b_direct_rendering = 1;\r
288     }\r
289 \r
290 #ifdef LIBAVCODEC_PP\r
291     p_sys->p_pp = NULL;\r
292     p_sys->b_pp = p_sys->b_pp_async = p_sys->b_pp_init = VLC_FALSE;\r
293     p_sys->p_pp = E_(OpenPostproc)( p_dec, &p_sys->b_pp_async );\r
294 #endif\r
295 \r
296     /* ffmpeg doesn't properly release old pictures when frames are skipped */\r
297     //if( p_sys->b_hurry_up ) p_sys->b_direct_rendering = 0;\r
298     if( p_sys->b_direct_rendering )\r
299     {\r
300         msg_Dbg( p_dec, "using direct rendering" );\r
301         p_sys->p_context->flags |= CODEC_FLAG_EMU_EDGE;\r
302     }\r
303 \r
304     /* Always use our get_buffer wrapper so we can calculate the\r
305      * PTS correctly */\r
306     p_sys->p_context->get_buffer = ffmpeg_GetFrameBuf;\r
307     p_sys->p_context->release_buffer = ffmpeg_ReleaseFrameBuf;\r
308     p_sys->p_context->opaque = p_dec;\r
309 \r
310     /* ***** init this codec with special data ***** */\r
311     if( p_dec->fmt_in.i_extra )\r
312     {\r
313         int i_size = p_dec->fmt_in.i_extra;\r
314 \r
315         if( p_sys->i_codec_id == CODEC_ID_SVQ3 )\r
316         {\r
317             uint8_t *p;\r
318 \r
319             p_sys->p_context->extradata_size = i_size + 12;\r
320             p = p_sys->p_context->extradata  =\r
321                 malloc( p_sys->p_context->extradata_size );\r
322 \r
323             memcpy( &p[0],  "SVQ3", 4 );\r
324             memset( &p[4], 0, 8 );\r
325             memcpy( &p[12], p_dec->fmt_in.p_extra, i_size );\r
326 \r
327             /* Now remove all atoms before the SMI one */\r
328             if( p_sys->p_context->extradata_size > 0x5a &&\r
329                 strncmp( &p[0x56], "SMI ", 4 ) )\r
330             {\r
331                 uint8_t *psz = &p[0x52];\r
332 \r
333                 while( psz < &p[p_sys->p_context->extradata_size - 8] )\r
334                 {\r
335                     int i_size = GetDWBE( psz );\r
336                     if( i_size <= 1 )\r
337                     {\r
338                         /* FIXME handle 1 as long size */\r
339                         break;\r
340                     }\r
341                     if( !strncmp( &psz[4], "SMI ", 4 ) )\r
342                     {\r
343                         memmove( &p[0x52], psz,\r
344                                  &p[p_sys->p_context->extradata_size] - psz );\r
345                         break;\r
346                     }\r
347 \r
348                     psz += i_size;\r
349                 }\r
350             }\r
351         }\r
352         else if( p_dec->fmt_in.i_codec == VLC_FOURCC( 'R', 'V', '1', '0' ) ||\r
353                  p_dec->fmt_in.i_codec == VLC_FOURCC( 'R', 'V', '1', '3' ) ||\r
354                  p_dec->fmt_in.i_codec == VLC_FOURCC( 'R', 'V', '2', '0' ) )\r
355         {\r
356             if( p_dec->fmt_in.i_extra == 8 )\r
357             {\r
358                 p_sys->p_context->extradata_size = 8;\r
359                 p_sys->p_context->extradata = malloc( 8 );\r
360 \r
361                 memcpy( p_sys->p_context->extradata,\r
362                         p_dec->fmt_in.p_extra,\r
363                         p_dec->fmt_in.i_extra );\r
364                 p_sys->p_context->sub_id= ((uint32_t*)p_dec->fmt_in.p_extra)[1];\r
365 \r
366                 msg_Warn( p_dec, "using extra data for RV codec sub_id=%08x",\r
367                           p_sys->p_context->sub_id );\r
368             }\r
369         }\r
370         /* FIXME: remove when ffmpeg deals properly with avc1 */\r
371         else if( p_dec->fmt_in.i_codec == VLC_FOURCC('a','v','c','1') )\r
372         {\r
373             ;\r
374         }\r
375         /* End FIXME */\r
376         else\r
377         {\r
378             p_sys->p_context->extradata_size = i_size;\r
379             p_sys->p_context->extradata =\r
380                 malloc( i_size + FF_INPUT_BUFFER_PADDING_SIZE );\r
381             memcpy( p_sys->p_context->extradata,\r
382                     p_dec->fmt_in.p_extra, i_size );\r
383             memset( &((uint8_t*)p_sys->p_context->extradata)[i_size],\r
384                     0, FF_INPUT_BUFFER_PADDING_SIZE );\r
385         }\r
386     }\r
387 \r
388     /* ***** misc init ***** */\r
389     p_sys->input_pts = p_sys->input_dts = 0;\r
390     p_sys->i_pts = 0;\r
391     p_sys->b_has_b_frames = VLC_FALSE;\r
392     p_sys->b_first_frame = VLC_TRUE;\r
393     p_sys->i_late_frames = 0;\r
394     p_sys->i_buffer = 0;\r
395     p_sys->i_buffer_orig = 1;\r
396     p_sys->p_buffer_orig = p_sys->p_buffer = malloc( p_sys->i_buffer_orig );\r
397 \r
398     /* Set output properties */\r
399     p_dec->fmt_out.i_cat = VIDEO_ES;\r
400     p_dec->fmt_out.i_codec = ffmpeg_PixFmtToChroma( p_context->pix_fmt );\r
401 \r
402     /* Setup palette */\r
403 #if LIBAVCODEC_BUILD >= 4688\r
404     if( p_dec->fmt_in.video.p_palette )\r
405         p_sys->p_context->palctrl =\r
406             (AVPaletteControl *)p_dec->fmt_in.video.p_palette;\r
407     else\r
408         p_sys->p_context->palctrl = &palette_control;\r
409 #endif\r
410 \r
411     /* ***** Open the codec ***** */\r
412     vlc_mutex_lock( lockval.p_address );\r
413     if( avcodec_open( p_sys->p_context, p_sys->p_codec ) < 0 )\r
414     {\r
415         vlc_mutex_unlock( lockval.p_address );\r
416         msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec );\r
417         free( p_sys );\r
418         return VLC_EGENERIC;\r
419     }\r
420     vlc_mutex_unlock( lockval.p_address );\r
421     msg_Dbg( p_dec, "ffmpeg codec (%s) started", p_sys->psz_namecodec );\r
422 \r
423 \r
424     return VLC_SUCCESS;\r
425 }\r
426 \r
427 /*****************************************************************************\r
428  * DecodeVideo: Called to decode one or more frames\r
429  *****************************************************************************/\r
430 picture_t *E_(DecodeVideo)( decoder_t *p_dec, block_t **pp_block )\r
431 {\r
432     decoder_sys_t *p_sys = p_dec->p_sys;\r
433     int b_drawpicture;\r
434     int b_null_size = VLC_FALSE;\r
435     block_t *p_block;\r
436 \r
437     if( !pp_block || !*pp_block ) return NULL;\r
438 \r
439     p_block = *pp_block;\r
440 \r
441     if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )\r
442     {\r
443         p_sys->i_buffer = 0;\r
444         p_sys->i_pts = 0; /* To make sure we recover properly */\r
445 \r
446         p_sys->input_pts = p_sys->input_dts = 0;\r
447         p_sys->i_late_frames = 0;\r
448 \r
449         block_Release( p_block );\r
450         return NULL;\r
451     }\r
452 \r
453     if( p_block->i_flags & BLOCK_FLAG_PREROLL )\r
454     {\r
455         /* Do not care about late frames when prerolling\r
456          * TODO avoid decoding of non reference frame\r
457          * (ie all B except for H264 where it depends only on nal_ref_idc) */\r
458         p_sys->i_late_frames = 0;\r
459     }\r
460 \r
461     if( !p_dec->b_pace_control && p_sys->i_late_frames > 0 &&\r
462         mdate() - p_sys->i_late_frames_start > I64C(5000000) )\r
463     {\r
464         if( p_sys->i_pts )\r
465         {\r
466             msg_Err( p_dec, "more than 5 seconds of late video -> "\r
467                      "dropping frame (computer too slow ?)" );\r
468             p_sys->i_pts = 0; /* To make sure we recover properly */\r
469         }\r
470         block_Release( p_block );\r
471         p_sys->i_late_frames--;\r
472         return NULL;\r
473     }\r
474 \r
475     if( p_block->i_pts > 0 || p_block->i_dts > 0 )\r
476     {\r
477         p_sys->input_pts = p_block->i_pts;\r
478         p_sys->input_dts = p_block->i_dts;\r
479 \r
480         /* Make sure we don't reuse the same timestamps twice */\r
481         p_block->i_pts = p_block->i_dts = 0;\r
482     }\r
483 \r
484     /* TODO implement it in a better way */\r
485     /* A good idea could be to decode all I pictures and see for the other */\r
486     if( !p_dec->b_pace_control &&\r
487         p_sys->b_hurry_up && p_sys->i_late_frames > 4 )\r
488     {\r
489         b_drawpicture = 0;\r
490         if( p_sys->i_late_frames < 8 )\r
491         {\r
492             p_sys->p_context->hurry_up = 2;\r
493         }\r
494         else\r
495         {\r
496             /* picture too late, won't decode\r
497              * but break picture until a new I, and for mpeg4 ...*/\r
498 \r
499             p_sys->i_late_frames--; /* needed else it will never be decrease */\r
500             block_Release( p_block );\r
501             p_sys->i_buffer = 0;\r
502             return NULL;\r
503         }\r
504     }\r
505     else\r
506     {\r
507         if (!(p_block->i_flags & BLOCK_FLAG_PREROLL))\r
508         {\r
509             b_drawpicture = 1;\r
510             p_sys->p_context->hurry_up = 0;\r
511         }\r
512         else\r
513         {\r
514             b_drawpicture = 0;\r
515             p_sys->p_context->hurry_up = 1;\r
516         }\r
517     }\r
518 \r
519 \r
520     if( p_sys->p_context->width <= 0 || p_sys->p_context->height <= 0 )\r
521     {\r
522         p_sys->p_context->hurry_up = 5;\r
523         b_null_size = VLC_TRUE;\r
524     }\r
525 \r
526     /*\r
527      * Do the actual decoding now\r
528      */\r
529 \r
530     /* Check if post-processing was enabled */\r
531     p_sys->b_pp = p_sys->b_pp_async;\r
532 \r
533     /* Don't forget that ffmpeg requires a little more bytes\r
534      * that the real frame size */\r
535     if( p_block->i_buffer > 0 )\r
536     {\r
537         p_sys->i_buffer = p_block->i_buffer;\r
538         if( p_sys->i_buffer + FF_INPUT_BUFFER_PADDING_SIZE >\r
539             p_sys->i_buffer_orig )\r
540         {\r
541             free( p_sys->p_buffer_orig );\r
542             p_sys->i_buffer_orig =\r
543                 p_block->i_buffer + FF_INPUT_BUFFER_PADDING_SIZE;\r
544             p_sys->p_buffer_orig = malloc( p_sys->i_buffer_orig );\r
545         }\r
546         p_sys->p_buffer = p_sys->p_buffer_orig;\r
547         p_sys->i_buffer = p_block->i_buffer;\r
548         p_dec->p_vlc->pf_memcpy( p_sys->p_buffer, p_block->p_buffer,\r
549                                  p_block->i_buffer );\r
550         memset( p_sys->p_buffer + p_block->i_buffer, 0,\r
551                 FF_INPUT_BUFFER_PADDING_SIZE );\r
552 \r
553         p_block->i_buffer = 0;\r
554     }\r
555 \r
556     while( p_sys->i_buffer > 0 )\r
557     {\r
558         int i_used, b_gotpicture;\r
559         picture_t *p_pic;\r
560 \r
561         i_used = avcodec_decode_video( p_sys->p_context, p_sys->p_ff_pic,\r
562                                        &b_gotpicture,\r
563                                        p_sys->p_buffer, p_sys->i_buffer );\r
564         if( b_null_size && p_sys->p_context->width > 0 &&\r
565             p_sys->p_context->height > 0 )\r
566         {\r
567             /* Reparse it to not drop the I frame */\r
568             b_null_size = VLC_FALSE;\r
569             p_sys->p_context->hurry_up = 0;\r
570             i_used = avcodec_decode_video( p_sys->p_context, p_sys->p_ff_pic,\r
571                                            &b_gotpicture,\r
572                                            p_sys->p_buffer, p_sys->i_buffer );\r
573         }\r
574 \r
575         if( i_used < 0 )\r
576         {\r
577             msg_Warn( p_dec, "cannot decode one frame (%d bytes)",\r
578                       p_sys->i_buffer );\r
579             block_Release( p_block );\r
580             return NULL;\r
581         }\r
582         else if( i_used > p_sys->i_buffer )\r
583         {\r
584             i_used = p_sys->i_buffer;\r
585         }\r
586 \r
587         /* Consumed bytes */\r
588         p_sys->i_buffer -= i_used;\r
589         p_sys->p_buffer += i_used;\r
590 \r
591         /* Nothing to display */\r
592         if( !b_gotpicture )\r
593         {\r
594             if( i_used == 0 ) break;\r
595             continue;\r
596         }\r
597 \r
598         /* Update frame late count (except when doing preroll) */\r
599         if( p_sys->i_pts && p_sys->i_pts <= mdate() &&\r
600             !(p_block->i_flags & BLOCK_FLAG_PREROLL) )\r
601         {\r
602             p_sys->i_late_frames++;\r
603             if( p_sys->i_late_frames == 1 )\r
604                 p_sys->i_late_frames_start = mdate();\r
605         }\r
606         else\r
607         {\r
608             p_sys->i_late_frames = 0;\r
609         }\r
610 \r
611         if( !b_drawpicture || !p_sys->p_ff_pic->linesize[0] )\r
612         {\r
613             /* Do not display the picture */\r
614             continue;\r
615         }\r
616 \r
617         if( !p_sys->p_ff_pic->opaque )\r
618         {\r
619             /* Get a new picture */\r
620             p_pic = ffmpeg_NewPictBuf( p_dec, p_sys->p_context );\r
621             if( !p_pic )\r
622             {\r
623                 block_Release( p_block );\r
624                 return NULL;\r
625             }\r
626 \r
627             /* Fill p_picture_t from AVVideoFrame and do chroma conversion\r
628              * if needed */\r
629             ffmpeg_CopyPicture( p_dec, p_pic, p_sys->p_ff_pic );\r
630         }\r
631         else\r
632         {\r
633             p_pic = (picture_t *)p_sys->p_ff_pic->opaque;\r
634         }\r
635 \r
636         /* Set the PTS */\r
637         if( p_sys->p_ff_pic->pts ) p_sys->i_pts = p_sys->p_ff_pic->pts;\r
638 \r
639         /* Sanity check (seems to be needed for some streams ) */\r
640         if( p_sys->p_ff_pic->pict_type == FF_B_TYPE )\r
641         {\r
642             p_sys->b_has_b_frames = VLC_TRUE;\r
643         }\r
644 \r
645         /* Send decoded frame to vout */\r
646         if( p_sys->i_pts )\r
647         {\r
648             p_pic->date = p_sys->i_pts;\r
649 \r
650             /* interpolate the next PTS */\r
651             if( p_sys->p_context->frame_rate > 0 )\r
652             {\r
653                 p_sys->i_pts += I64C(1000000) *\r
654                     (2 + p_sys->p_ff_pic->repeat_pict) *\r
655                     p_sys->p_context->frame_rate_base /\r
656                     (2 * p_sys->p_context->frame_rate);\r
657             }\r
658 \r
659             if( p_sys->b_first_frame )\r
660             {\r
661                 /* Hack to force display of still pictures */\r
662                 p_sys->b_first_frame = VLC_FALSE;\r
663                 p_pic->b_force = VLC_TRUE;\r
664             }\r
665 \r
666             p_pic->i_nb_fields = 2 + p_sys->p_ff_pic->repeat_pict;\r
667 #if LIBAVCODEC_BUILD >= 4685\r
668             p_pic->b_progressive = !p_sys->p_ff_pic->interlaced_frame;\r
669             p_pic->b_top_field_first = p_sys->p_ff_pic->top_field_first;\r
670 #endif\r
671 \r
672             return p_pic;\r
673         }\r
674         else\r
675         {\r
676             p_dec->pf_vout_buffer_del( p_dec, p_pic );\r
677         }\r
678     }\r
679 \r
680     block_Release( p_block );\r
681     return NULL;\r
682 }\r
683 \r
684 /*****************************************************************************\r
685  * EndVideo: decoder destruction\r
686  *****************************************************************************\r
687  * This function is called when the thread ends after a sucessful\r
688  * initialization.\r
689  *****************************************************************************/\r
690 void E_(EndVideoDec)( decoder_t *p_dec )\r
691 {\r
692     decoder_sys_t *p_sys = p_dec->p_sys;\r
693 \r
694     if( p_sys->p_ff_pic ) av_free( p_sys->p_ff_pic );\r
695 \r
696 #ifdef LIBAVCODEC_PP\r
697     E_(ClosePostproc)( p_dec, p_sys->p_pp );\r
698 #endif\r
699 \r
700     free( p_sys->p_buffer_orig );\r
701 }\r
702 \r
703 /*****************************************************************************\r
704  * ffmpeg_CopyPicture: copy a picture from ffmpeg internal buffers to a\r
705  *                     picture_t structure (when not in direct rendering mode).\r
706  *****************************************************************************/\r
707 static void ffmpeg_CopyPicture( decoder_t *p_dec,\r
708                                 picture_t *p_pic, AVFrame *p_ff_pic )\r
709 {\r
710     decoder_sys_t *p_sys = p_dec->p_sys;\r
711 \r
712     if( ffmpeg_PixFmtToChroma( p_sys->p_context->pix_fmt ) )\r
713     {\r
714         int i_plane, i_size, i_line;\r
715         uint8_t *p_dst, *p_src;\r
716         int i_src_stride, i_dst_stride;\r
717 \r
718 #ifdef LIBAVCODEC_PP\r
719         if( p_sys->p_pp && p_sys->b_pp )\r
720             E_(PostprocPict)( p_dec, p_sys->p_pp, p_pic, p_ff_pic );\r
721         else\r
722 #endif\r
723         for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )\r
724         {\r
725             p_src  = p_ff_pic->data[i_plane];\r
726             p_dst = p_pic->p[i_plane].p_pixels;\r
727             i_src_stride = p_ff_pic->linesize[i_plane];\r
728             i_dst_stride = p_pic->p[i_plane].i_pitch;\r
729 \r
730             i_size = __MIN( i_src_stride, i_dst_stride );\r
731             for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines;\r
732                  i_line++ )\r
733             {\r
734                 p_dec->p_vlc->pf_memcpy( p_dst, p_src, i_size );\r
735                 p_src += i_src_stride;\r
736                 p_dst += i_dst_stride;\r
737             }\r
738         }\r
739     }\r
740     else\r
741     {\r
742         AVPicture dest_pic;\r
743         int i;\r
744 \r
745         /* we need to convert to I420 */\r
746         switch( p_sys->p_context->pix_fmt )\r
747         {\r
748         case PIX_FMT_YUV410P:\r
749         case PIX_FMT_YUV411P:\r
750         case PIX_FMT_PAL8:\r
751             for( i = 0; i < p_pic->i_planes; i++ )\r
752             {\r
753                 dest_pic.data[i] = p_pic->p[i].p_pixels;\r
754                 dest_pic.linesize[i] = p_pic->p[i].i_pitch;\r
755             }\r
756             img_convert( &dest_pic, PIX_FMT_YUV420P,\r
757                          (AVPicture *)p_ff_pic,\r
758                          p_sys->p_context->pix_fmt,\r
759                          p_sys->p_context->width,\r
760                          p_sys->p_context->height );\r
761             break;\r
762         default:\r
763             msg_Err( p_dec, "don't know how to convert chroma %i",\r
764                      p_sys->p_context->pix_fmt );\r
765             p_dec->b_error = 1;\r
766             break;\r
767         }\r
768     }\r
769 }\r
770 \r
771 /*****************************************************************************\r
772  * ffmpeg_GetFrameBuf: callback used by ffmpeg to get a frame buffer.\r
773  *****************************************************************************\r
774  * It is used for direct rendering as well as to get the right PTS for each\r
775  * decoded picture (even in indirect rendering mode).\r
776  *****************************************************************************/\r
777 static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context,\r
778                                AVFrame *p_ff_pic )\r
779 {\r
780     decoder_t *p_dec = (decoder_t *)p_context->opaque;\r
781     decoder_sys_t *p_sys = p_dec->p_sys;\r
782     picture_t *p_pic;\r
783 \r
784     /* Set picture PTS */\r
785     if( p_sys->input_pts )\r
786     {\r
787         p_ff_pic->pts = p_sys->input_pts;\r
788     }\r
789     else if( p_sys->input_dts )\r
790     {\r
791         /* Some demuxers only set the dts so let's try to find a useful\r
792          * timestamp from this */\r
793         if( !p_context->has_b_frames || !p_sys->b_has_b_frames ||\r
794             !p_ff_pic->reference || !p_sys->i_pts )\r
795         {\r
796             p_ff_pic->pts = p_sys->input_dts;\r
797         }\r
798         else p_ff_pic->pts = 0;\r
799     }\r
800     else p_ff_pic->pts = 0;\r
801 \r
802     if( p_sys->i_pts ) /* make sure 1st frame has a pts > 0 */\r
803     {\r
804         p_sys->input_pts = p_sys->input_dts = 0;\r
805     }\r
806 \r
807     p_ff_pic->opaque = 0;\r
808 \r
809     /* Not much to do in indirect rendering mode */\r
810     if( !p_sys->b_direct_rendering || p_sys->b_pp )\r
811     {\r
812         return avcodec_default_get_buffer( p_context, p_ff_pic );\r
813     }\r
814 \r
815     /* Some codecs set pix_fmt only after the 1st frame has been decoded,\r
816      * so this check is necessary. */\r
817     if( !ffmpeg_PixFmtToChroma( p_context->pix_fmt ) ||\r
818         p_sys->p_context->width % 16 || p_sys->p_context->height % 16 )\r
819     {\r
820         msg_Dbg( p_dec, "disabling direct rendering" );\r
821         p_sys->b_direct_rendering = 0;\r
822         return avcodec_default_get_buffer( p_context, p_ff_pic );\r
823     }\r
824 \r
825     /* Get a new picture */\r
826     //p_sys->p_vout->render.b_allow_modify_pics = 0;\r
827     p_pic = ffmpeg_NewPictBuf( p_dec, p_sys->p_context );\r
828     if( !p_pic )\r
829     {\r
830         p_sys->b_direct_rendering = 0;\r
831         return avcodec_default_get_buffer( p_context, p_ff_pic );\r
832     }\r
833     p_sys->p_context->draw_horiz_band = NULL;\r
834 \r
835     p_ff_pic->opaque = (void*)p_pic;\r
836     p_ff_pic->type = FF_BUFFER_TYPE_USER;\r
837     p_ff_pic->data[0] = p_pic->p[0].p_pixels;\r
838     p_ff_pic->data[1] = p_pic->p[1].p_pixels;\r
839     p_ff_pic->data[2] = p_pic->p[2].p_pixels;\r
840     p_ff_pic->data[3] = NULL; /* alpha channel but I'm not sure */\r
841 \r
842     p_ff_pic->linesize[0] = p_pic->p[0].i_pitch;\r
843     p_ff_pic->linesize[1] = p_pic->p[1].i_pitch;\r
844     p_ff_pic->linesize[2] = p_pic->p[2].i_pitch;\r
845     p_ff_pic->linesize[3] = 0;\r
846 \r
847     if( p_ff_pic->reference != 0 )\r
848     {\r
849         p_dec->pf_picture_link( p_dec, p_pic );\r
850     }\r
851 \r
852     /* FIXME what is that, should give good value */\r
853     p_ff_pic->age = 256*256*256*64; // FIXME FIXME from ffmpeg\r
854 \r
855     return 0;\r
856 }\r
857 \r
858 static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *p_context,\r
859                                     AVFrame *p_ff_pic )\r
860 {\r
861     decoder_t *p_dec = (decoder_t *)p_context->opaque;\r
862     picture_t *p_pic;\r
863 \r
864     if( !p_ff_pic->opaque )\r
865     {\r
866         avcodec_default_release_buffer( p_context, p_ff_pic );\r
867         return;\r
868     }\r
869 \r
870     p_pic = (picture_t*)p_ff_pic->opaque;\r
871 \r
872     p_ff_pic->data[0] = NULL;\r
873     p_ff_pic->data[1] = NULL;\r
874     p_ff_pic->data[2] = NULL;\r
875     p_ff_pic->data[3] = NULL;\r
876 \r
877     if( p_ff_pic->reference != 0 )\r
878     {\r
879         p_dec->pf_picture_unlink( p_dec, p_pic );\r
880     }\r
881 }\r