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 $
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 *, AVVideoFrame *, 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 *, AVVideoFrame *);
62 static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *, AVVideoFrame *);
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
94 static vout_thread_t *ffmpeg_CreateVout( vdec_thread_t *p_vdec,
95 AVCodecContext *p_context )
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;
103 if( !i_width || !i_height )
105 return( NULL ); /* Can't create a new vout without display size */
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 */
116 #if LIBAVCODEC_BUILD >= 4640
117 i_aspect = VOUT_ASPECT_FACTOR * p_context->aspect_ratio;
120 i_aspect = VOUT_ASPECT_FACTOR * i_width / i_height;
123 switch( p_context->aspect_ratio_info )
125 case( FF_ASPECT_4_3_625 ):
126 case( FF_ASPECT_4_3_525 ):
127 i_aspect = VOUT_ASPECT_FACTOR * 4 / 3;
129 case( FF_ASPECT_16_9_625 ):
130 case( FF_ASPECT_16_9_525 ):
131 i_aspect = VOUT_ASPECT_FACTOR * 16 / 9 ;
133 case( FF_ASPECT_SQUARE ):
135 i_aspect = VOUT_ASPECT_FACTOR * i_width / i_height;
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 );
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
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 )
158 static void ffmpeg_ConvertPictureI410toI420( picture_t *p_pic,
160 vdec_thread_t *p_vdec )
163 uint8_t *p_src, *p_dst;
167 int i_stride, i_lines;
168 int i_height, i_width;
171 i_height = p_vdec->p_context->height;
172 i_width = p_vdec->p_context->width;
174 p_dst = p_pic->p[0].p_pixels;
175 p_src = p_ff_pic->data[0];
177 /* copy first plane */
178 for( i_y = 0; i_y < i_height; i_y++ )
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];
185 /* process each plane in a temporary buffer */
186 for( i_plane = 1; i_plane < 3; i_plane++ )
188 i_stride = p_ff_pic->linesize[i_plane];
189 i_lines = i_height / 4;
191 p_dst = p_plane[i_plane] = malloc( i_lines * i_stride * 2 * 2 );
192 p_src = p_ff_pic->data[i_plane];
194 /* for each source line */
195 for( i_y = 0; i_y < i_lines; i_y++ )
197 for( i_x = 0; i_x < i_stride - 1; i_x++ )
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;
203 p_dst[2 * i_stride - 2] = p_src[i_x];
204 p_dst[2 * i_stride - 1] = p_src[i_x];
206 p_dst += 4 * i_stride; /* process the next even lines */
211 for( i_plane = 1; i_plane < 3; i_plane++ )
213 i_stride = p_ff_pic->linesize[i_plane];
214 i_lines = i_height / 4;
216 p_dst = p_plane[i_plane] + 2*i_stride;
217 p_src = p_plane[i_plane];
219 for( i_y = 0; i_y < i_lines - 1; i_y++ )
221 for( i_x = 0; i_x < 2 * i_stride ; i_x++ )
223 p_dst[i_x] = ( p_src[i_x] + p_src[i_x + 4*i_stride])/2;
226 p_dst += 4 * i_stride; /* process the next odd lines */
227 p_src += 4 * i_stride;
230 p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, 2*i_stride );
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++ )
238 p_src = p_plane[i_plane];
239 p_dst = p_pic->p[i_plane].p_pixels;
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++ )
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;
248 free( p_plane[i_plane] );
252 /*****************************************************************************
254 * Functions that initialize, decode and end the decoding process
256 * Functions exported for ffmpeg.c
257 * * E_( InitThread_Video )
258 * * E_( DecodeThread )
259 * * E_( EndThread_Video )
260 *****************************************************************************/
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.
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 )
275 #if LIBAVCODEC_BUILD >= 4641
276 p_vdec->p_ff_pic = avcodec_alloc_picture();
278 p_vdec->p_ff_pic = &p_vdec->ff_pic;
281 if( p_vdec->p_fifo->p_demux_data )
283 p_vdec->p_format = (BITMAPINFOHEADER *)p_vdec->p_fifo->p_demux_data;
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;
292 msg_Warn( p_vdec->p_fifo, "display informations missing" );
293 p_vdec->p_format = NULL;
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 );
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 );
305 #if LIBAVCODEC_BUILD >= 4614
306 if( config_GetInt( p_vdec->p_fifo, "grayscale" ) )
308 p_vdec->p_context->flags|= CODEC_FLAG_GRAY;
312 p_vdec->b_hurry_up = config_GetInt(p_vdec->p_fifo, "ffmpeg-hurry-up");
314 p_vdec->b_direct_rendering = 0;
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 */
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;
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)
336 msg_Dbg( p_vdec->p_fifo, "CODEC_FLAG_TRUNCATED supported" );
337 p_vdec->p_context->flags |= CODEC_FLAG_TRUNCATED;
341 /* ***** Open the codec ***** */
342 if( avcodec_open(p_vdec->p_context, p_vdec->p_codec) < 0 )
344 msg_Err( p_vdec->p_fifo, "cannot open codec (%s)",
345 p_vdec->psz_namecodec );
350 msg_Dbg( p_vdec->p_fifo, "ffmpeg codec (%s) started",
351 p_vdec->psz_namecodec );
354 /* ***** init this codec with special data ***** */
355 if( p_vdec->p_format &&
356 p_vdec->p_format->biSize > sizeof(BITMAPINFOHEADER) )
360 switch( p_vdec->i_codec_id )
362 case( CODEC_ID_MPEG4 ):
363 avcodec_decode_video( p_vdec->p_context, p_vdec->p_ff_pic,
365 (void *)&p_vdec->p_format[1],
366 p_vdec->p_format->biSize
367 - sizeof(BITMAPINFOHEADER) );
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 )
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 );
393 /* ***** Load post processing ***** */
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;
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 ) )
414 /* check if the codec support postproc. */
415 switch( p_vdec->i_codec_id )
417 #if LIBAVCODEC_BUILD > 4608
418 case( CODEC_ID_MSMPEG4V1 ):
419 case( CODEC_ID_MSMPEG4V2 ):
420 case( CODEC_ID_MSMPEG4V3 ):
422 case( CODEC_ID_MSMPEG4 ):
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" );
437 if( !p_vdec->p_pp->p_module )
439 msg_Warn( p_vdec->p_fifo,
440 "no suitable postprocessing module" );
441 vlc_object_destroy( p_vdec->p_pp );
443 p_vdec->i_pp_mode = 0;
447 /* get mode upon quality */
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" )
455 p_vdec->i_pp_mode = 0;
456 msg_Warn( p_vdec->p_fifo,
457 "post-processing not supported, upgrade ffmpeg" );
461 p_vdec->i_pp_mode = 0;
462 msg_Warn( p_vdec->p_fifo,
463 "Post processing unsupported for this codec" );
468 // memset( &p_vdec->statistic, 0, sizeof( statistic_t ) );
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 )
486 picture_t *p_pic; /* videolan picture */
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 ) )
494 if( p_vdec->i_frame_late < 8 )
496 p_vdec->p_context->hurry_up = 2;
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 );
510 p_vdec->p_context->hurry_up = 0;
515 input_ExtractPES( p_vdec->p_fifo, &p_pes );
518 p_vdec->p_fifo->b_error = 1;
522 if( p_vdec->i_codec_id == CODEC_ID_MPEG1VIDEO )
526 p_vdec->pts = p_pes->i_dts;
527 p_vdec->i_frame_count = 0;
534 p_vdec->pts = p_pes->i_pts;
535 p_vdec->i_frame_count = 0;
541 p_vdec->pts = p_pes->i_pts;
542 p_vdec->i_frame_count = 0;
545 i_frame_size = p_pes->i_pes_size;
547 if( i_frame_size > 0 )
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)
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 )
561 memcpy( p_vdec->p_buffer, p_last, p_vdec->i_buffer );
566 E_( GetPESData )( p_vdec->p_buffer + p_vdec->i_buffer,
569 memset( p_vdec->p_buffer + p_vdec->i_buffer + i_frame_size,
573 input_DeletePES( p_vdec->p_fifo->p_packets_mgt, p_pes );
574 } while( i_frame_size <= 0 );
576 i_frame_size += p_vdec->i_buffer;
579 i_used = avcodec_decode_video( p_vdec->p_context,
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" );
592 msg_Warn( p_vdec->p_fifo, "cannot decode one frame (%d bytes)",
594 p_vdec->i_frame_error++;
595 p_vdec->i_buffer = 0;
598 else if( i_used < i_frame_size )
601 msg_Dbg( p_vdec->p_fifo,
602 "didn't use all memory(%d < %d)", i_used, i_frame_size );
604 memmove( p_vdec->p_buffer,
605 p_vdec->p_buffer + i_used,
606 p_vdec->i_buffer_size - i_used );
608 p_vdec->i_buffer = i_frame_size - i_used;
612 p_vdec->i_buffer = 0;
617 p_vdec->i_frame_count++;
621 i_frame_size -= i_used;
623 /* Update frame late count*/
624 /* I don't make statistic on decoding time */
625 if( p_vdec->pts <= mdate())
627 p_vdec->i_frame_late++;
631 p_vdec->i_frame_late = 0;
634 if( !b_gotpicture || p_vdec->p_ff_pic->linesize[0] == 0 || !b_drawpicture )
639 if( !p_vdec->b_direct_rendering )
641 p_vdec->p_vout = ffmpeg_CreateVout( p_vdec, p_vdec->p_context );
642 if( !p_vdec->p_vout )
644 msg_Err( p_vdec->p_fifo, "cannot create vout" );
645 p_vdec->p_fifo->b_error = 1; /* abort */
649 /* Get a new picture */
650 while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
652 if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error )
656 msleep( VOUT_OUTMEM_SLEEP );
659 /* fill p_picture_t from AVVideoFrame, do I410->I420 if needed */
660 ffmpeg_CopyPicture( p_pic, p_vdec->p_ff_pic, p_vdec );
664 #if LIBAVCODEC_BUILD >= 4641
665 p_pic = (picture_t *)p_vdec->p_ff_pic->opaque;
667 p_pic = NULL; /* f**ck gcc warning */
671 /* Do post-processing if requested */
672 /* XXX: with dr it is not a good thing if the picture will be used as
674 ffmpeg_PostProcPicture( p_vdec, p_pic );
676 /* fix date calculation */
677 if( p_vdec->pts > 0 )
681 if( p_vdec->p_context->frame_rate > 0 )
683 i_pts += (uint64_t)1000000 *
684 ( p_vdec->i_frame_count - 1) /
686 p_vdec->p_context->frame_rate;
691 i_pts = mdate() + DEFAULT_PTS_DELAY; // FIXME
694 vout_DatePicture( p_vdec->p_vout,
698 /* Send decoded frame to vout */
699 vout_DisplayPicture( p_vdec->p_vout, p_pic );
701 if( i_frame_size > 0 )
703 goto usenextdata; /* try to use all data */
707 /*****************************************************************************
708 * EndThread: thread destruction
709 *****************************************************************************
710 * This function is called when the thread ends after a sucessful
712 *****************************************************************************/
713 void E_( EndThread_Video )( vdec_thread_t *p_vdec )
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 );
724 #if LIBAVCODEC_BUILD >= 4641
725 if( p_vdec->p_ff_pic )
727 free( p_vdec->p_ff_pic );
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 );
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 )
744 static void ffmpeg_CopyPicture( picture_t *p_pic,
746 vdec_thread_t *p_vdec )
758 if( ffmpeg_PixFmtToChroma( p_vdec->p_context->pix_fmt ) )
760 for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
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;
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++ )
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;
778 /* we need to convert to I420 */
779 switch( p_vdec->p_context->pix_fmt )
781 #if LIBAVCODEC_BUILD >= 4615
782 case( PIX_FMT_YUV410P ):
783 ffmpeg_ConvertPictureI410toI420( p_pic, p_ff_pic, p_vdec );
787 p_vdec->p_fifo->b_error = 1;
793 /*****************************************************************************
794 * ffmpeg_PostProcPicture: Postprocessing is done here.
795 *****************************************************************************/
796 static void ffmpeg_PostProcPicture( vdec_thread_t *p_vdec, picture_t *p_pic )
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' ) ) ) )
804 #if LIBAVCODEC_BUILD >= 4641
806 p_vdec->p_pp->pf_postprocess( p_pic,
807 p_vdec->p_ff_pic->qscale_table,
808 p_vdec->p_ff_pic->qstride,
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,
819 #if LIBAVCODEC_BUILD >= 4641
820 /*****************************************************************************
821 * ffmpeg_GetFrameBuf: callback used by ffmpeg to get a frame buffer.
822 * (used for direct rendering)
823 *****************************************************************************/
825 static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context,
826 AVVideoFrame *p_ff_pic )
828 vdec_thread_t *p_vdec = (vdec_thread_t *)p_context->opaque;
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 )
835 msg_Err( p_vdec->p_fifo, "cannot create vout" );
836 p_vdec->p_fifo->b_error = 1; /* abort */
839 p_vdec->p_vout->render.b_allow_modify_pics = 0;
841 /* Get a new picture */
842 while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
844 if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error )
848 msleep( VOUT_OUTMEM_SLEEP );
850 p_vdec->p_context->draw_horiz_band= NULL;
852 p_ff_pic->opaque = (void*)p_pic;
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 */
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;
864 if( p_ff_pic->reference != 0 )
866 vout_LinkPicture( p_vdec->p_vout, p_pic );
868 /* FIXME what is that, should give good value */
869 p_ff_pic->age = 256*256*256*64; // FIXME FIXME from ffmpeg
874 static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *p_context,
875 AVVideoFrame *p_ff_pic )
877 vdec_thread_t *p_vdec = (vdec_thread_t *)p_context->opaque;
880 //msg_Dbg( p_vdec->p_fifo, "ffmpeg_ReleaseFrameBuf" );
881 p_pic = (picture_t*)p_ff_pic->opaque;
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;
888 vout_UnlinkPicture( p_vdec->p_vout, p_pic );