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 $
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8 * Gildas Bazin <gbazin@netcourrier.com>
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.
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.
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 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
28 #include <stdlib.h> /* malloc(), free() */
33 #include <vlc/decoder.h>
34 #include <vlc/input.h>
38 #ifdef HAVE_SYS_TIMES_H
39 # include <sys/times.h>
42 #include "avcodec.h" /* ffmpeg */
44 #include "postprocessing/postprocessing.h"
49 /*****************************************************************************
51 *****************************************************************************/
52 #if LIBAVCODEC_BUILD >= 4641
53 static void ffmpeg_CopyPicture( picture_t *, AVFrame *, vdec_thread_t * );
55 static void ffmpeg_CopyPicture( picture_t *, AVPicture *, vdec_thread_t * );
58 static void ffmpeg_PostProcPicture( vdec_thread_t *, picture_t * );
60 #if LIBAVCODEC_BUILD >= 4641
61 static int ffmpeg_GetFrameBuf( struct AVCodecContext *, AVFrame *);
62 static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *, AVFrame *);
65 /*****************************************************************************
67 *****************************************************************************/
69 static inline uint32_t ffmpeg_PixFmtToChroma( int i_ff_chroma )
71 /* FIXME FIXME some of them are wrong */
76 return( VLC_FOURCC('I','4','2','0') );
78 return( VLC_FOURCC('R','V','2','4') );
81 return( VLC_FOURCC('I','4','2','2') );
83 return( VLC_FOURCC('I','4','4','4') );
84 #if LIBAVCODEC_BUILD >= 4615
95 static vout_thread_t *ffmpeg_CreateVout( vdec_thread_t *p_vdec,
96 AVCodecContext *p_context )
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;
104 if( !i_width || !i_height )
106 return( NULL ); /* Can't create a new vout without display size */
111 /* we make conversion if possible*/
112 i_chroma = VLC_FOURCC('I','4','2','0');
114 #if LIBAVCODEC_BUILD >= 4640
115 i_aspect = VOUT_ASPECT_FACTOR * p_context->aspect_ratio;
118 i_aspect = VOUT_ASPECT_FACTOR * i_width / i_height;
121 switch( p_context->aspect_ratio_info )
123 case( FF_ASPECT_4_3_625 ):
124 case( FF_ASPECT_4_3_525 ):
125 i_aspect = VOUT_ASPECT_FACTOR * 4 / 3;
127 case( FF_ASPECT_16_9_625 ):
128 case( FF_ASPECT_16_9_525 ):
129 i_aspect = VOUT_ASPECT_FACTOR * 16 / 9 ;
131 case( FF_ASPECT_SQUARE ):
133 i_aspect = VOUT_ASPECT_FACTOR * i_width / i_height;
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 );
146 /*****************************************************************************
148 * Functions that initialize, decode and end the decoding process
150 * Functions exported for ffmpeg.c
151 * * E_( InitThread_Video )
152 * * E_( DecodeThread )
153 * * E_( EndThread_Video )
154 *****************************************************************************/
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.
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 )
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();
174 p_vdec->p_ff_pic = &p_vdec->ff_pic;
177 if( ( p_vdec->p_format = (BITMAPINFOHEADER *)p_vdec->p_fifo->p_bitmapinfoheader) != NULL )
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;
186 msg_Warn( p_vdec->p_fifo, "display informations missing" );
187 p_vdec->p_format = NULL;
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 );
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 );
199 #if LIBAVCODEC_BUILD >= 4614
200 if( config_GetInt( p_vdec->p_fifo, "grayscale" ) )
202 p_vdec->p_context->flags|= CODEC_FLAG_GRAY;
206 p_vdec->b_hurry_up = config_GetInt(p_vdec->p_fifo, "ffmpeg-hurry-up");
208 p_vdec->b_direct_rendering = 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)
215 msg_Dbg( p_vdec->p_fifo, "CODEC_FLAG_TRUNCATED supported" );
216 p_vdec->p_context->flags |= CODEC_FLAG_TRUNCATED;
220 /* ***** Open the codec ***** */
221 if( avcodec_open(p_vdec->p_context, p_vdec->p_codec) < 0 )
223 msg_Err( p_vdec->p_fifo, "cannot open codec (%s)",
224 p_vdec->psz_namecodec );
229 msg_Dbg( p_vdec->p_fifo, "ffmpeg codec (%s) started",
230 p_vdec->psz_namecodec );
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 ) )
238 /* FIXME: some codecs set pix_fmt only after a frame
239 * has been decoded. */
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;
251 /* ***** init this codec with special data ***** */
252 if( p_vdec->p_format &&
253 p_vdec->p_format->biSize > sizeof(BITMAPINFOHEADER) )
257 switch( p_vdec->i_codec_id )
259 case( CODEC_ID_MPEG4 ):
261 avcodec_decode_video( p_vdec->p_context, p_vdec->p_ff_pic,
263 (void *)&p_vdec->p_format[1],
264 p_vdec->p_format->biSize
265 - sizeof(BITMAPINFOHEADER) );
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 )
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 );
292 /* ***** Load post processing ***** */
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;
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 ) )
313 /* check if the codec support postproc. */
314 switch( p_vdec->i_codec_id )
316 #if LIBAVCODEC_BUILD > 4608
317 case( CODEC_ID_MSMPEG4V1 ):
318 case( CODEC_ID_MSMPEG4V2 ):
319 case( CODEC_ID_MSMPEG4V3 ):
321 case( CODEC_ID_MSMPEG4 ):
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" );
336 if( !p_vdec->p_pp->p_module )
338 msg_Warn( p_vdec->p_fifo,
339 "no suitable postprocessing module" );
340 vlc_object_destroy( p_vdec->p_pp );
342 p_vdec->i_pp_mode = 0;
346 /* get mode upon quality */
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" )
354 p_vdec->i_pp_mode = 0;
355 msg_Warn( p_vdec->p_fifo,
356 "post-processing not supported, upgrade ffmpeg" );
360 p_vdec->i_pp_mode = 0;
361 msg_Warn( p_vdec->p_fifo,
362 "Post processing unsupported for this codec" );
367 // memset( &p_vdec->statistic, 0, sizeof( statistic_t ) );
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 )
385 picture_t *p_pic; /* videolan picture */
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 ) )
393 if( p_vdec->i_frame_late < 8 )
395 p_vdec->p_context->hurry_up = 2;
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 );
409 p_vdec->p_context->hurry_up = 0;
412 if( !p_vdec->p_context->width || !p_vdec->p_context->height )
414 p_vdec->p_context->hurry_up = 5;
419 input_ExtractPES( p_vdec->p_fifo, &p_pes );
422 p_vdec->p_fifo->b_error = 1;
426 if( p_vdec->i_codec_id == CODEC_ID_MPEG1VIDEO )
430 p_vdec->pts = p_pes->i_dts;
431 p_vdec->i_frame_count = 0;
438 p_vdec->pts = p_pes->i_pts;
439 p_vdec->i_frame_count = 0;
445 p_vdec->pts = p_pes->i_pts;
446 p_vdec->i_frame_count = 0;
449 i_frame_size = p_pes->i_pes_size;
451 if( i_frame_size > 0 )
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)
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 )
465 memcpy( p_vdec->p_buffer, p_last, p_vdec->i_buffer );
470 E_( GetPESData )( p_vdec->p_buffer + p_vdec->i_buffer,
473 memset( p_vdec->p_buffer + p_vdec->i_buffer + i_frame_size,
477 input_DeletePES( p_vdec->p_fifo->p_packets_mgt, p_pes );
478 } while( i_frame_size <= 0 );
480 i_frame_size += p_vdec->i_buffer;
483 i_used = avcodec_decode_video( p_vdec->p_context,
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" );
496 msg_Warn( p_vdec->p_fifo, "cannot decode one frame (%d bytes)",
498 p_vdec->i_frame_error++;
499 p_vdec->i_buffer = 0;
502 else if( i_used < i_frame_size )
505 msg_Dbg( p_vdec->p_fifo,
506 "didn't use all memory(%d < %d)", i_used, i_frame_size );
508 memmove( p_vdec->p_buffer,
509 p_vdec->p_buffer + i_used,
510 p_vdec->i_buffer_size - i_used );
512 p_vdec->i_buffer = i_frame_size - i_used;
516 p_vdec->i_buffer = 0;
521 p_vdec->i_frame_count++;
525 i_frame_size -= i_used;
527 /* Update frame late count*/
528 /* I don't make statistic on decoding time */
529 if( p_vdec->pts <= mdate())
531 p_vdec->i_frame_late++;
535 p_vdec->i_frame_late = 0;
538 if( !b_gotpicture || p_vdec->p_ff_pic->linesize[0] == 0 || !b_drawpicture )
543 if( !p_vdec->b_direct_rendering )
545 p_vdec->p_vout = ffmpeg_CreateVout( p_vdec, p_vdec->p_context );
546 if( !p_vdec->p_vout )
548 msg_Err( p_vdec->p_fifo, "cannot create vout" );
549 p_vdec->p_fifo->b_error = 1; /* abort */
553 /* Get a new picture */
554 while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
556 if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error )
560 msleep( VOUT_OUTMEM_SLEEP );
563 /* fill p_picture_t from AVVideoFrame and do chroma conversion
565 ffmpeg_CopyPicture( p_pic, p_vdec->p_ff_pic, p_vdec );
569 #if LIBAVCODEC_BUILD >= 4641
570 p_pic = (picture_t *)p_vdec->p_ff_pic->opaque;
572 p_pic = NULL; /* f**ck gcc warning */
576 /* Do post-processing if requested */
577 /* XXX: with dr it is not a good thing if the picture will be used as
579 ffmpeg_PostProcPicture( p_vdec, p_pic );
581 /* fix date calculation */
582 if( p_vdec->pts > 0 )
586 if( p_vdec->p_context->frame_rate > 0 )
588 i_pts += (uint64_t)1000000 *
589 ( p_vdec->i_frame_count - 1) /
591 p_vdec->p_context->frame_rate;
596 i_pts = mdate() + DEFAULT_PTS_DELAY; // FIXME
599 vout_DatePicture( p_vdec->p_vout,
603 /* Send decoded frame to vout */
604 vout_DisplayPicture( p_vdec->p_vout, p_pic );
606 if( i_frame_size > 0 )
608 goto usenextdata; /* try to use all data */
612 /*****************************************************************************
613 * EndThread: thread destruction
614 *****************************************************************************
615 * This function is called when the thread ends after a sucessful
617 *****************************************************************************/
618 void E_( EndThread_Video )( vdec_thread_t *p_vdec )
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 );
629 #if LIBAVCODEC_BUILD >= 4641
630 if( p_vdec->p_ff_pic )
632 free( p_vdec->p_ff_pic );
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 );
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,
647 vdec_thread_t *p_vdec )
649 static void ffmpeg_CopyPicture( picture_t *p_pic,
651 vdec_thread_t *p_vdec )
663 if( ffmpeg_PixFmtToChroma( p_vdec->p_context->pix_fmt ) )
665 for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
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;
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++ )
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;
683 /* we need to convert to I420 */
684 switch( p_vdec->p_context->pix_fmt )
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++ )
694 dest_pic.data[i] = p_pic->p[i].p_pixels;
695 dest_pic.linesize[i] = p_pic->p[i].i_pitch;
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 );
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;
713 /*****************************************************************************
714 * ffmpeg_PostProcPicture: Postprocessing is done here.
715 *****************************************************************************/
716 static void ffmpeg_PostProcPicture( vdec_thread_t *p_vdec, picture_t *p_pic )
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' ) ) ) )
724 #if LIBAVCODEC_BUILD >= 4641
726 p_vdec->p_pp->pf_postprocess( p_pic,
727 p_vdec->p_ff_pic->qscale_table,
728 p_vdec->p_ff_pic->qstride,
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,
739 #if LIBAVCODEC_BUILD >= 4641
740 /*****************************************************************************
741 * ffmpeg_GetFrameBuf: callback used by ffmpeg to get a frame buffer.
742 * (used for direct rendering)
743 *****************************************************************************/
745 static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context,
748 vdec_thread_t *p_vdec = (vdec_thread_t *)p_context->opaque;
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 )
755 msg_Err( p_vdec->p_fifo, "cannot create vout" );
756 p_vdec->p_fifo->b_error = 1; /* abort */
759 p_vdec->p_vout->render.b_allow_modify_pics = 0;
761 /* Get a new picture */
762 while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
764 if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error )
768 msleep( VOUT_OUTMEM_SLEEP );
770 p_vdec->p_context->draw_horiz_band= NULL;
772 p_ff_pic->opaque = (void*)p_pic;
773 #if LIBAVCODEC_BUILD >= 4645
774 p_ff_pic->type = FF_BUFFER_TYPE_USER;
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 */
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;
786 if( p_ff_pic->reference != 0 )
788 vout_LinkPicture( p_vdec->p_vout, p_pic );
790 /* FIXME what is that, should give good value */
791 p_ff_pic->age = 256*256*256*64; // FIXME FIXME from ffmpeg
796 static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *p_context,
799 vdec_thread_t *p_vdec = (vdec_thread_t *)p_context->opaque;
802 //msg_Dbg( p_vdec->p_fifo, "ffmpeg_ReleaseFrameBuf" );
803 p_pic = (picture_t*)p_ff_pic->opaque;
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;
810 vout_UnlinkPicture( p_vdec->p_vout, p_pic );