1 /*****************************************************************************
2 * video.c: video decoder using ffmpeg library
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: video.c,v 1.8 2002/11/28 17:35:00 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 static void ffmpeg_CopyPicture( picture_t *, AVPicture *, vdec_thread_t * );
53 static void ffmpeg_PostProcPicture( vdec_thread_t *, picture_t * );
54 static int ffmpeg_GetFrameBuf( struct AVCodecContext *, int, int, int );
56 /* FIXME FIXME some of them are wrong */
57 static int i_ffmpeg_PixFmtToChroma[] =
59 /* PIX_FMT_ANY = -1, PIX_FMT_YUV420P,
60 PIX_FMT_YUV422, PIX_FMT_RGB24,
61 PIX_FMT_BGR24, PIX_FMT_YUV422P,
62 PIX_FMT_YUV444P, PIX_FMT_YUV410P
64 0, VLC_FOURCC('I','4','2','0'),
65 VLC_FOURCC('I','4','2','0'), VLC_FOURCC('R','V','2','4'),
66 0, VLC_FOURCC('I','4','2','2'),
67 VLC_FOURCC('I','4','4','4'), 0
70 /*****************************************************************************
72 *****************************************************************************/
74 static inline u32 ffmpeg_PixFmtToChroma( int i_ffmpegchroma )
76 if( ++i_ffmpegchroma > 7 )
82 return( i_ffmpeg_PixFmtToChroma[i_ffmpegchroma] );
86 static inline int ffmpeg_FfAspect( int i_width, int i_height, int i_ffaspect )
90 case( FF_ASPECT_4_3_625 ):
91 case( FF_ASPECT_4_3_525 ):
92 return( VOUT_ASPECT_FACTOR * 4 / 3);
93 case( FF_ASPECT_16_9_625 ):
94 case( FF_ASPECT_16_9_525 ):
95 return( VOUT_ASPECT_FACTOR * 16 / 9 );
96 case( FF_ASPECT_SQUARE ):
98 return( VOUT_ASPECT_FACTOR * i_width / i_height );
103 static vout_thread_t *ffmpeg_CreateVout( vdec_thread_t *p_vdec,
104 AVCodecContext *p_context )
106 vout_thread_t *p_vout;
107 int i_width = p_vdec->p_context->width;
108 int i_height = p_vdec->p_context->height;
109 uint32_t i_chroma = ffmpeg_PixFmtToChroma( p_vdec->p_context->pix_fmt );
112 if( !i_width || !i_height )
114 return( NULL ); /* Can't create a new vout without display size */
119 /* we make conversion if possible*/
120 i_chroma = VLC_FOURCC('I','4','2','0');
121 msg_Warn( p_vdec->p_fifo, "Internal chroma conversion (FIXME)");
122 /* It's mainly for I410 -> I420 conversion that I've made,
123 it's buggy and very slow */
126 #if LIBAVCODEC_BUILD >= 4640
127 i_aspect = (int) ( VOUT_ASPECT_FACTOR * p_vdec->p_context->aspect_ratio );
131 i_aspect = VOUT_ASPECT_FACTOR * i_width / i_height;
135 switch( p_vdec->p_context->aspect_ratio_info )
137 case( FF_ASPECT_4_3_625 ):
138 case( FF_ASPECT_4_3_525 ):
139 i_aspect = VOUT_ASPECT_FACTOR * 4 / 3;
141 case( FF_ASPECT_16_9_625 ):
142 case( FF_ASPECT_16_9_525 ):
143 i_aspect = VOUT_ASPECT_FACTOR * 16 / 9 ;
145 case( FF_ASPECT_SQUARE ):
147 i_aspect = VOUT_ASPECT_FACTOR * i_width / i_height;
151 /* Spawn a video output if there is none. First we look for our children,
152 * then we look for any other vout that might be available. */
153 p_vout = vout_Request( p_vdec->p_fifo, NULL,
154 i_width, i_height, i_chroma, i_aspect );
159 /* FIXME FIXME FIXME this is a big shit
160 does someone want to rewrite this function ?
161 or said to me how write a better thing
164 static void ffmpeg_ConvertPictureI410toI420( picture_t *p_pic,
165 AVPicture *p_avpicture,
166 vdec_thread_t *p_vdec )
172 int i_stride, i_lines;
173 int i_height, i_width;
176 i_height = p_vdec->p_context->height;
177 i_width = p_vdec->p_context->width;
179 p_dst = p_pic->p[0].p_pixels;
180 p_src = p_avpicture->data[0];
182 /* copy first plane */
183 for( i_y = 0; i_y < i_height; i_y++ )
185 p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, i_width);
186 p_dst += p_pic->p[0].i_pitch;
187 p_src += p_avpicture->linesize[0];
190 /* process each plane in a temporary buffer */
191 for( i_plane = 1; i_plane < 3; i_plane++ )
193 i_stride = p_avpicture->linesize[i_plane];
194 i_lines = i_height / 4;
196 p_dst = p_plane[i_plane] = malloc( i_lines * i_stride * 2 * 2 );
197 p_src = p_avpicture->data[i_plane];
199 /* for each source line */
200 for( i_y = 0; i_y < i_lines; i_y++ )
202 for( i_x = 0; i_x < i_stride - 1; i_x++ )
204 p_dst[2 * i_x ] = p_src[i_x];
205 p_dst[2 * i_x + 1] = ( p_src[i_x] + p_src[i_x + 1]) / 2;
208 p_dst[2 * i_stride - 2] = p_src[i_x];
209 p_dst[2 * i_stride - 1] = p_src[i_x];
211 p_dst += 4 * i_stride; /* process the next even lines */
216 for( i_plane = 1; i_plane < 3; i_plane++ )
218 i_stride = p_avpicture->linesize[i_plane];
219 i_lines = i_height / 4;
221 p_dst = p_plane[i_plane] + 2*i_stride;
222 p_src = p_plane[i_plane];
224 for( i_y = 0; i_y < i_lines - 1; i_y++ )
226 for( i_x = 0; i_x < 2 * i_stride ; i_x++ )
228 p_dst[i_x] = ( p_src[i_x] + p_src[i_x + 4*i_stride])/2;
231 p_dst += 4 * i_stride; /* process the next odd lines */
232 p_src += 4 * i_stride;
235 p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, 2*i_stride );
237 /* copy to p_pic, by block
238 if I do pixel per pixel it segfault. It's why I use
239 temporaries buffers */
240 for( i_plane = 1; i_plane < 3; i_plane++ )
243 p_src = p_plane[i_plane];
244 p_dst = p_pic->p[i_plane].p_pixels;
246 i_size = __MIN( 2*i_stride, p_pic->p[i_plane].i_pitch);
247 for( i_y = 0; i_y < __MIN(p_pic->p[i_plane].i_lines, 2 * i_lines); i_y++ )
249 p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, i_size );
250 p_src += 2 * i_stride;
251 p_dst += p_pic->p[i_plane].i_pitch;
253 free( p_plane[i_plane] );
257 /*****************************************************************************
259 * Functions that initialize, decode and end the decoding process
261 * Functions exported for ffmpeg.c
262 * * E_( InitThread_Video )
263 * * E_( DecodeThread )
264 * * E_( EndThread_Video )
265 *****************************************************************************/
267 /*****************************************************************************
268 * InitThread: initialize vdec output thread
269 *****************************************************************************
270 * This function is called from decoder_Run and performs the second step
271 * of the initialization. It returns 0 on success. Note that the thread's
272 * flag are not modified inside this function.
274 * ffmpeg codec will be open, some memory allocated. But Vout is not yet
275 * open (done after the first decoded frame)
276 *****************************************************************************/
277 int E_( InitThread_Video )( vdec_thread_t *p_vdec )
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->p_lastpic = NULL;
315 p_vdec->p_secondlastpic = NULL;
316 p_vdec->b_direct_rendering = 0;
317 #if LIBAVCODEC_BUILD > 4615
318 if( (p_vdec->p_codec->capabilities & CODEC_CAP_DR1)
319 && (p_vdec->p_context->pix_fmt != PIX_FMT_YUV410P) &&
320 config_GetInt( p_vdec->p_fifo, "ffmpeg-dr" ) )
322 msg_Dbg( p_vdec->p_fifo, "using direct rendering" );
323 p_vdec->b_direct_rendering = 1;
324 p_vdec->p_context->flags|= CODEC_FLAG_EMU_EDGE | CODEC_FLAG_DR1;
325 p_vdec->p_context->get_buffer_callback = ffmpeg_GetFrameBuf;
326 p_vdec->p_context->opaque = p_vdec;
331 /* check if codec support truncated frames */
332 // if( p_vdec->p_codec->capabilities & CODEC_FLAG_TRUNCATED )
333 if( p_vdec->i_codec_id == CODEC_ID_MPEG1VIDEO)
335 msg_Dbg( p_vdec->p_fifo, "CODEC_FLAG_TRUNCATED supported" );
336 p_vdec->p_context->flags |= CODEC_FLAG_TRUNCATED;
340 /* ***** Open the codec ***** */
341 if( avcodec_open(p_vdec->p_context, p_vdec->p_codec) < 0 )
343 msg_Err( p_vdec->p_fifo, "cannot open codec (%s)",
344 p_vdec->psz_namecodec );
349 msg_Dbg( p_vdec->p_fifo, "ffmpeg codec (%s) started",
350 p_vdec->psz_namecodec );
353 /* ***** init this codec with special data ***** */
354 if( p_vdec->p_format &&
355 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, &avpicture,
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" )
454 /* allocate table for postprocess */
455 // p_vdec->p_context->quant_store =
456 // malloc( sizeof( int ) * ( MBR + 1 ) * ( MBC + 1 ) );
457 // p_vdec->p_context->qstride = MBC + 1;
460 p_vdec->i_pp_mode = 0;
461 msg_Warn( p_vdec->p_fifo,
462 "post-processing not supported, upgrade ffmpeg" );
466 p_vdec->i_pp_mode = 0;
467 msg_Warn( p_vdec->p_fifo,
468 "Post processing unsupported for this codec" );
473 // memset( &p_vdec->statistic, 0, sizeof( statistic_t ) );
478 /*****************************************************************************
479 * DecodeThread: Called to decode one frame
480 *****************************************************************************
481 * We have to get a frame stored in a pes, give it to ffmpeg decoder and send
482 * the image to the output.
483 *****************************************************************************/
484 void E_( DecodeThread_Video )( vdec_thread_t *p_vdec )
491 AVPicture avpicture; /* ffmpeg picture */
492 picture_t *p_pic; /* videolan picture */
495 /* TODO implement it in a better way */
496 /* A good idea could be to decode all I pictures and see for the other */
497 if( ( p_vdec->b_hurry_up )&& ( p_vdec->i_frame_late > 4 ) )
499 #if LIBAVCODEC_BUILD > 4603
501 if( p_vdec->i_frame_late < 8 )
503 p_vdec->p_context->hurry_up = 2;
507 /* too much late picture, won't decode
508 but break picture until a new I, and for mpeg4 ...*/
509 p_vdec->i_frame_late--; /* needed else it will never be decrease */
510 input_ExtractPES( p_vdec->p_fifo, NULL );
514 if( p_vdec->i_frame_late < 8 )
516 b_drawpicture = 0; /* not really good but .. UPGRADE FFMPEG !! */
520 /* too much late picture, won't decode
521 but break picture until a new I, and for mpeg4 ...*/
522 p_vdec->i_frame_late--; /* needed else it will never be decrease */
523 input_ExtractPES( p_vdec->p_fifo, NULL );
531 #if LIBAVCODEC_BUILD > 4603
532 p_vdec->p_context->hurry_up = 0;
538 input_ExtractPES( p_vdec->p_fifo, &p_pes );
541 p_vdec->p_fifo->b_error = 1;
545 if( p_vdec->i_codec_id == CODEC_ID_MPEG1VIDEO )
549 p_vdec->pts = p_pes->i_dts;
550 p_vdec->i_frame_count = 0;
557 p_vdec->pts = p_pes->i_pts;
558 p_vdec->i_frame_count = 0;
564 p_vdec->pts = p_pes->i_pts;
565 p_vdec->i_frame_count = 0;
568 i_frame_size = p_pes->i_pes_size;
570 if( i_frame_size > 0 )
574 /* XXX Don't forget that ffmpeg required a little more bytes
575 * that the real frame size */
576 i_need = i_frame_size + 16 + p_vdec->i_buffer;
577 if( p_vdec->i_buffer_size < i_need)
579 p_last = p_vdec->p_buffer;
580 p_vdec->p_buffer = malloc( i_need );
581 p_vdec->i_buffer_size = i_need;
582 if( p_vdec->i_buffer > 0 )
584 memcpy( p_vdec->p_buffer, p_last, p_vdec->i_buffer );
589 E_( GetPESData )( p_vdec->p_buffer + p_vdec->i_buffer,
592 memset( p_vdec->p_buffer + p_vdec->i_buffer + i_frame_size,
596 input_DeletePES( p_vdec->p_fifo->p_packets_mgt, p_pes );
597 } while( i_frame_size <= 0 );
599 i_frame_size += p_vdec->i_buffer;
602 i_used = avcodec_decode_video( p_vdec->p_context,
609 msg_Dbg( p_vdec->p_fifo,
610 "used:%d framesize:%d (%s picture)",
611 i_used, i_frame_size, b_gotpicture ? "got":"no got" );
615 msg_Warn( p_vdec->p_fifo, "cannot decode one frame (%d bytes)",
617 p_vdec->i_frame_error++;
618 p_vdec->i_buffer = 0;
621 else if( i_used < i_frame_size )
624 msg_Dbg( p_vdec->p_fifo,
625 "didn't use all memory(%d < %d)", i_used, i_frame_size );
627 memmove( p_vdec->p_buffer,
628 p_vdec->p_buffer + i_used,
629 p_vdec->i_buffer_size - i_used );
631 p_vdec->i_buffer = i_frame_size - i_used;
635 p_vdec->i_buffer = 0;
640 p_vdec->i_frame_count++;
644 i_frame_size -= i_used;
646 /* Update frame late count*/
647 /* I don't make statistic on decoding time */
648 if( p_vdec->pts <= mdate())
650 p_vdec->i_frame_late++;
654 p_vdec->i_frame_late = 0;
657 if( !b_gotpicture || avpicture.linesize[0] == 0 || !b_drawpicture )
662 if( !p_vdec->b_direct_rendering )
664 p_vdec->p_vout = ffmpeg_CreateVout( p_vdec, p_vdec->p_context );
665 if( !p_vdec->p_vout )
667 msg_Err( p_vdec->p_fifo, "cannot create vout" );
668 p_vdec->p_fifo->b_error = 1; /* abort */
672 /* Get a new picture */
673 while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
675 if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error )
679 msleep( VOUT_OUTMEM_SLEEP );
682 /* fill p_picture_t from avpicture, do I410->I420 if needed */
683 ffmpeg_CopyPicture( p_pic, &avpicture, p_vdec );
687 #if LIBAVCODEC_BUILD > 4615
688 p_pic = (picture_t *)p_vdec->p_context->dr_opaque_frame;
692 /* Do post-processing if requested */
693 ffmpeg_PostProcPicture( p_vdec, p_pic );
695 /* Send decoded frame to vout */
696 if( p_vdec->pts > 0 )
700 if( p_vdec->p_context->frame_rate > 0 )
702 i_pts += (uint64_t)1000000 *
703 ( p_vdec->i_frame_count - 1) /
705 p_vdec->p_context->frame_rate;
710 i_pts = mdate() + DEFAULT_PTS_DELAY; // FIXME
713 vout_DatePicture( p_vdec->p_vout,
717 vout_DisplayPicture( p_vdec->p_vout, p_pic );
719 if( i_frame_size > 0 )
725 /*****************************************************************************
726 * EndThread: thread destruction
727 *****************************************************************************
728 * This function is called when the thread ends after a sucessful
730 *****************************************************************************/
731 void E_( EndThread_Video )( vdec_thread_t *p_vdec )
733 if( p_vdec->p_secondlastpic )
734 vout_UnlinkPicture( p_vdec->p_vout, p_vdec->p_secondlastpic );
735 if( p_vdec->p_lastpic )
736 vout_UnlinkPicture( p_vdec->p_vout, p_vdec->p_lastpic );
740 /* release postprocessing module */
741 module_Unneed( p_vdec->p_pp, p_vdec->p_pp->p_module );
742 vlc_object_destroy( p_vdec->p_pp );
746 /* We are about to die. Reattach video output to p_vlc. */
747 vout_Request( p_vdec->p_fifo, p_vdec->p_vout, 0, 0, 0, 0 );
750 /*****************************************************************************
751 * ffmpeg_CopyPicture: copy a picture from ffmpeg internal buffers to a
752 * picture_t structure (when not in direct rendering mode).
753 *****************************************************************************/
754 static void ffmpeg_CopyPicture( picture_t *p_pic, AVPicture *p_avpicture,
755 vdec_thread_t *p_vdec )
766 if( ffmpeg_PixFmtToChroma( p_vdec->p_context->pix_fmt ) )
768 for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
770 p_src = p_avpicture->data[i_plane];
771 p_dst = p_pic->p[i_plane].p_pixels;
772 i_src_stride = p_avpicture->linesize[i_plane];
773 i_dst_stride = p_pic->p[i_plane].i_pitch;
775 i_size = __MIN( i_src_stride, i_dst_stride );
776 for( i_line = 0; i_line < p_pic->p[i_plane].i_lines; i_line++ )
778 p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, i_size );
779 p_src += i_src_stride;
780 p_dst += i_dst_stride;
786 /* we need to convert to I420 */
787 switch( p_vdec->p_context->pix_fmt )
789 #if LIBAVCODEC_BUILD >= 4615
790 case( PIX_FMT_YUV410P ):
791 ffmpeg_ConvertPictureI410toI420( p_pic, p_avpicture, p_vdec );
795 p_vdec->p_fifo->b_error = 1;
801 /*****************************************************************************
802 * ffmpeg_PostProcPicture: Postprocessing is done here.
803 *****************************************************************************/
804 static void ffmpeg_PostProcPicture( vdec_thread_t *p_vdec, picture_t *p_pic )
806 #if LIBAVCODEC_BUILD > 4313
807 if( ( p_vdec->i_pp_mode )&&
808 ( ( p_vdec->p_vout->render.i_chroma ==
809 VLC_FOURCC( 'I','4','2','0' ) )||
810 ( p_vdec->p_vout->render.i_chroma ==
811 VLC_FOURCC( 'Y','V','1','2' ) ) ) )
814 p_vdec->p_pp->pf_postprocess( p_pic,
815 p_vdec->p_context->display_qscale_table,
816 // p_vdec->p_context->current_qscale_table,
817 p_vdec->p_context->qstride,
823 /*****************************************************************************
824 * ffmpeg_GetFrameBuf: callback used by ffmpeg to get a frame buffer.
825 * (used for direct rendering)
826 *****************************************************************************/
827 static int ffmpeg_GetFrameBuf( struct AVCodecContext *avctx, int width,
828 int height, int pict_type )
830 #if LIBAVCODEC_BUILD > 4615
831 vdec_thread_t *p_vdec = (vdec_thread_t *)avctx->opaque;
835 p_vdec->p_vout = ffmpeg_CreateVout( p_vdec, p_vdec->p_context );
836 if( !p_vdec->p_vout )
838 msg_Err( p_vdec->p_fifo, "cannot create vout" );
839 p_vdec->p_fifo->b_error = 1; /* abort */
843 /* Get a new picture */
844 while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
846 if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error )
850 msleep( VOUT_OUTMEM_SLEEP );
853 /* FIXME: We keep the last picture linked until the current one is decoded,
854 * this trick won't work with streams with B frames though. */
855 vout_LinkPicture( p_vdec->p_vout, p_pic );
856 if( p_vdec->p_secondlastpic )
857 vout_UnlinkPicture( p_vdec->p_vout, p_vdec->p_secondlastpic );
858 p_vdec->p_secondlastpic = p_vdec->p_lastpic;
859 p_vdec->p_lastpic = p_pic;
861 avctx->draw_horiz_band= NULL;
862 avctx->dr_buffer[0]= p_pic->p[0].p_pixels;
863 avctx->dr_buffer[1]= p_pic->p[1].p_pixels;
864 avctx->dr_buffer[2]= p_pic->p[2].p_pixels;
866 avctx->dr_stride = p_pic->p[0].i_pitch;
867 avctx->dr_uvstride = p_pic->p[1].i_pitch;
869 avctx->dr_opaque_frame = p_pic;
871 /* This variable is used to determine if a macro-block to be written
872 * can be skipped. The idea behind this is that if a macro-block hasn't
873 * changed and all the frame-buffers already have the value of this
874 * macro-block, then we don't need to write it again. */
875 avctx->dr_ip_buffer_count = p_vdec->p_vout->render.i_pictures;
876 p_vdec->p_vout->render.b_allow_modify_pics = 0;