1 /*****************************************************************************
2 * video.c: video decoder using ffmpeg library
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: video.c,v 1.7 2002/11/28 16:44:05 fenrir 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 );
102 /* Check if we have a Vout with good parameters */
103 static int ffmpeg_CheckVout( vout_thread_t *p_vout,
114 /* we will try to make conversion */
115 i_chroma = VLC_FOURCC('I','4','2','0');
118 if( ( p_vout->render.i_width != i_width )||
119 ( p_vout->render.i_height != i_height )||
120 ( p_vout->render.i_chroma != i_chroma ) )
131 static vout_thread_t *ffmpeg_CreateVout( vdec_thread_t *p_vdec,
132 AVCodecContext *p_context )
134 vout_thread_t *p_vout;
135 int i_width = p_vdec->p_context->width;
136 int i_height = p_vdec->p_context->height;
137 uint32_t i_chroma = ffmpeg_PixFmtToChroma( p_vdec->p_context->pix_fmt );
140 if( !i_width || !i_height )
142 return( NULL ); /* Can't create a new vout without display size */
147 /* we make conversion if possible*/
148 i_chroma = VLC_FOURCC('I','4','2','0');
149 msg_Warn( p_vdec->p_fifo, "Internal chroma conversion (FIXME)");
150 /* It's mainly for I410 -> I420 conversion that I've made,
151 it's buggy and very slow */
154 #if LIBAVCODEC_BUILD >= 4640
155 i_aspect = (int) ( VOUT_ASPECT_FACTOR * p_vdec->p_context->aspect_ratio );
159 i_aspect = VOUT_ASPECT_FACTOR * i_width / i_height;
163 switch( p_vdec->p_context->aspect_ratio_info )
165 case( FF_ASPECT_4_3_625 ):
166 case( FF_ASPECT_4_3_525 ):
167 i_aspect = VOUT_ASPECT_FACTOR * 4 / 3;
169 case( FF_ASPECT_16_9_625 ):
170 case( FF_ASPECT_16_9_525 ):
171 i_aspect = VOUT_ASPECT_FACTOR * 16 / 9 ;
173 case( FF_ASPECT_SQUARE ):
175 i_aspect = VOUT_ASPECT_FACTOR * i_width / i_height;
179 /* Spawn a video output if there is none. First we look for our children,
180 * then we look for any other vout that might be available. */
181 p_vout = vlc_object_find( p_vdec->p_fifo, VLC_OBJECT_VOUT,
185 p_vout = vlc_object_find( p_vdec->p_fifo, VLC_OBJECT_VOUT,
191 if( !ffmpeg_CheckVout( p_vout, i_width, i_height, i_chroma ) )
193 /* We are not interested in this format, close this vout */
194 vlc_object_detach( p_vout );
195 vlc_object_release( p_vout );
196 vout_DestroyThread( p_vout );
201 /* This video output is cool! Hijack it. */
202 vlc_object_detach( p_vout );
203 vlc_object_attach( p_vout, p_vdec->p_fifo );
204 vlc_object_release( p_vout );
210 msg_Dbg( p_vdec->p_fifo, "no vout present, spawning one" );
212 p_vout = vout_CreateThread( p_vdec->p_fifo,
214 i_chroma, i_aspect );
220 /* FIXME FIXME FIXME this is a big shit
221 does someone want to rewrite this function ?
222 or said to me how write a better thing
225 static void ffmpeg_ConvertPictureI410toI420( picture_t *p_pic,
226 AVPicture *p_avpicture,
227 vdec_thread_t *p_vdec )
233 int i_stride, i_lines;
234 int i_height, i_width;
237 i_height = p_vdec->p_context->height;
238 i_width = p_vdec->p_context->width;
240 p_dst = p_pic->p[0].p_pixels;
241 p_src = p_avpicture->data[0];
243 /* copy first plane */
244 for( i_y = 0; i_y < i_height; i_y++ )
246 p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, i_width);
247 p_dst += p_pic->p[0].i_pitch;
248 p_src += p_avpicture->linesize[0];
251 /* process each plane in a temporary buffer */
252 for( i_plane = 1; i_plane < 3; i_plane++ )
254 i_stride = p_avpicture->linesize[i_plane];
255 i_lines = i_height / 4;
257 p_dst = p_plane[i_plane] = malloc( i_lines * i_stride * 2 * 2 );
258 p_src = p_avpicture->data[i_plane];
260 /* for each source line */
261 for( i_y = 0; i_y < i_lines; i_y++ )
263 for( i_x = 0; i_x < i_stride - 1; i_x++ )
265 p_dst[2 * i_x ] = p_src[i_x];
266 p_dst[2 * i_x + 1] = ( p_src[i_x] + p_src[i_x + 1]) / 2;
269 p_dst[2 * i_stride - 2] = p_src[i_x];
270 p_dst[2 * i_stride - 1] = p_src[i_x];
272 p_dst += 4 * i_stride; /* process the next even lines */
277 for( i_plane = 1; i_plane < 3; i_plane++ )
279 i_stride = p_avpicture->linesize[i_plane];
280 i_lines = i_height / 4;
282 p_dst = p_plane[i_plane] + 2*i_stride;
283 p_src = p_plane[i_plane];
285 for( i_y = 0; i_y < i_lines - 1; i_y++ )
287 for( i_x = 0; i_x < 2 * i_stride ; i_x++ )
289 p_dst[i_x] = ( p_src[i_x] + p_src[i_x + 4*i_stride])/2;
292 p_dst += 4 * i_stride; /* process the next odd lines */
293 p_src += 4 * i_stride;
296 p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, 2*i_stride );
298 /* copy to p_pic, by block
299 if I do pixel per pixel it segfault. It's why I use
300 temporaries buffers */
301 for( i_plane = 1; i_plane < 3; i_plane++ )
304 p_src = p_plane[i_plane];
305 p_dst = p_pic->p[i_plane].p_pixels;
307 i_size = __MIN( 2*i_stride, p_pic->p[i_plane].i_pitch);
308 for( i_y = 0; i_y < __MIN(p_pic->p[i_plane].i_lines, 2 * i_lines); i_y++ )
310 p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, i_size );
311 p_src += 2 * i_stride;
312 p_dst += p_pic->p[i_plane].i_pitch;
314 free( p_plane[i_plane] );
318 /*****************************************************************************
320 * Functions that initialize, decode and end the decoding process
322 * Functions exported for ffmpeg.c
323 * * E_( InitThread_Video )
324 * * E_( DecodeThread )
325 * * E_( EndThread_Video )
326 *****************************************************************************/
328 /*****************************************************************************
329 * InitThread: initialize vdec output thread
330 *****************************************************************************
331 * This function is called from decoder_Run and performs the second step
332 * of the initialization. It returns 0 on success. Note that the thread's
333 * flag are not modified inside this function.
335 * ffmpeg codec will be open, some memory allocated. But Vout is not yet
336 * open (done after the first decoded frame)
337 *****************************************************************************/
338 int E_( InitThread_Video )( vdec_thread_t *p_vdec )
342 if( p_vdec->p_fifo->p_demux_data )
344 p_vdec->p_format = (BITMAPINFOHEADER *)p_vdec->p_fifo->p_demux_data;
346 /* ***** Fill p_context with init values ***** */
347 p_vdec->p_context->width = p_vdec->p_format->biWidth;
348 p_vdec->p_context->height = p_vdec->p_format->biHeight;
353 msg_Warn( p_vdec->p_fifo, "display informations missing" );
354 p_vdec->p_format = NULL;
358 /* ***** Get configuration of ffmpeg plugin ***** */
359 #if LIBAVCODEC_BUILD >= 4611
360 i_tmp = config_GetInt( p_vdec->p_fifo, "ffmpeg-workaround-bugs" );
361 p_vdec->p_context->workaround_bugs = __MAX( __MIN( i_tmp, 99 ), 0 );
363 i_tmp = config_GetInt( p_vdec->p_fifo, "ffmpeg-error-resilience" );
364 p_vdec->p_context->error_resilience = __MAX( __MIN( i_tmp, 99 ), -1 );
366 #if LIBAVCODEC_BUILD >= 4614
367 if( config_GetInt( p_vdec->p_fifo, "grayscale" ) )
369 p_vdec->p_context->flags|= CODEC_FLAG_GRAY;
373 p_vdec->b_hurry_up = config_GetInt(p_vdec->p_fifo, "ffmpeg-hurry-up");
375 p_vdec->p_lastpic = NULL;
376 p_vdec->p_secondlastpic = NULL;
377 p_vdec->b_direct_rendering = 0;
378 #if LIBAVCODEC_BUILD > 4615
379 if( (p_vdec->p_codec->capabilities & CODEC_CAP_DR1)
380 && (p_vdec->p_context->pix_fmt != PIX_FMT_YUV410P) &&
381 config_GetInt( p_vdec->p_fifo, "ffmpeg-dr" ) )
383 msg_Dbg( p_vdec->p_fifo, "using direct rendering" );
384 p_vdec->b_direct_rendering = 1;
385 p_vdec->p_context->flags|= CODEC_FLAG_EMU_EDGE | CODEC_FLAG_DR1;
386 p_vdec->p_context->get_buffer_callback = ffmpeg_GetFrameBuf;
387 p_vdec->p_context->opaque = p_vdec;
392 /* check if codec support truncated frames */
393 // if( p_vdec->p_codec->capabilities & CODEC_FLAG_TRUNCATED )
394 if( p_vdec->i_codec_id == CODEC_ID_MPEG1VIDEO)
396 msg_Dbg( p_vdec->p_fifo, "CODEC_FLAG_TRUNCATED supported" );
397 p_vdec->p_context->flags |= CODEC_FLAG_TRUNCATED;
401 /* ***** Open the codec ***** */
402 if( avcodec_open(p_vdec->p_context, p_vdec->p_codec) < 0 )
404 msg_Err( p_vdec->p_fifo, "cannot open codec (%s)",
405 p_vdec->psz_namecodec );
410 msg_Dbg( p_vdec->p_fifo, "ffmpeg codec (%s) started",
411 p_vdec->psz_namecodec );
414 /* ***** init this codec with special data ***** */
415 if( p_vdec->p_format &&
416 p_vdec->p_format->biSize > sizeof(BITMAPINFOHEADER) )
421 switch( p_vdec->i_codec_id )
423 case( CODEC_ID_MPEG4 ):
424 avcodec_decode_video( p_vdec->p_context, &avpicture,
426 (void *)&p_vdec->p_format[1],
427 p_vdec->p_format->biSize
428 - sizeof(BITMAPINFOHEADER) );
431 if( p_vdec->p_fifo->i_fourcc == FOURCC_MP4S ||
432 p_vdec->p_fifo->i_fourcc == FOURCC_mp4s ||
433 p_vdec->p_fifo->i_fourcc == FOURCC_M4S2 ||
434 p_vdec->p_fifo->i_fourcc == FOURCC_m4s2 ||
435 p_vdec->p_fifo->i_fourcc == FOURCC_WMV2 ||
436 p_vdec->p_fifo->i_fourcc == FOURCC_MJPG ||
437 p_vdec->p_fifo->i_fourcc == FOURCC_mjpg ||
438 p_vdec->p_fifo->i_fourcc == FOURCC_mjpa ||
439 p_vdec->p_fifo->i_fourcc == FOURCC_mjpb )
441 p_vdec->p_context->extradata_size =
442 p_vdec->p_format->biSize - sizeof(BITMAPINFOHEADER);
443 p_vdec->p_context->extradata =
444 malloc( p_vdec->p_context->extradata_size );
445 memcpy( p_vdec->p_context->extradata,
446 &p_vdec->p_format[1],
447 p_vdec->p_context->extradata_size );
454 /* ***** Load post processing ***** */
456 /* get overridding settings */
457 p_vdec->i_pp_mode = 0;
458 if( config_GetInt( p_vdec->p_fifo, "ffmpeg-db-yv" ) )
459 p_vdec->i_pp_mode |= PP_DEBLOCK_Y_V;
460 if( config_GetInt( p_vdec->p_fifo, "ffmpeg-db-yh" ) )
461 p_vdec->i_pp_mode |= PP_DEBLOCK_Y_H;
462 if( config_GetInt( p_vdec->p_fifo, "ffmpeg-db-cv" ) )
463 p_vdec->i_pp_mode |= PP_DEBLOCK_C_V;
464 if( config_GetInt( p_vdec->p_fifo, "ffmpeg-db-ch" ) )
465 p_vdec->i_pp_mode |= PP_DEBLOCK_C_H;
466 if( config_GetInt( p_vdec->p_fifo, "ffmpeg-dr-y" ) )
467 p_vdec->i_pp_mode |= PP_DERING_Y;
468 if( config_GetInt( p_vdec->p_fifo, "ffmpeg-dr-c" ) )
469 p_vdec->i_pp_mode |= PP_DERING_C;
471 if( ( config_GetInt( p_vdec->p_fifo, "ffmpeg-pp-q" ) > 0 )||
472 ( config_GetInt( p_vdec->p_fifo, "ffmpeg-pp-auto" ) )||
473 ( p_vdec->i_pp_mode != 0 ) )
475 /* check if the codec support postproc. */
476 switch( p_vdec->i_codec_id )
478 #if LIBAVCODEC_BUILD > 4608
479 case( CODEC_ID_MSMPEG4V1 ):
480 case( CODEC_ID_MSMPEG4V2 ):
481 case( CODEC_ID_MSMPEG4V3 ):
483 case( CODEC_ID_MSMPEG4 ):
485 case( CODEC_ID_MPEG4 ):
486 case( CODEC_ID_H263 ):
487 // case( CODEC_ID_H263P ): I don't use it up to now
488 case( CODEC_ID_H263I ):
489 /* Ok we can make postprocessing :)) */
490 /* first try to get a postprocess module */
491 #if LIBAVCODEC_BUILD >= 4633
492 p_vdec->p_pp = vlc_object_create( p_vdec->p_fifo,
493 sizeof( postprocessing_t ) );
494 p_vdec->p_pp->psz_object_name = "postprocessing";
495 p_vdec->p_pp->p_module =
496 module_Need( p_vdec->p_pp, "postprocessing", "$ffmpeg-pp" );
498 if( !p_vdec->p_pp->p_module )
500 msg_Warn( p_vdec->p_fifo,
501 "no suitable postprocessing module" );
502 vlc_object_destroy( p_vdec->p_pp );
504 p_vdec->i_pp_mode = 0;
508 /* get mode upon quality */
510 p_vdec->p_pp->pf_getmode(
511 config_GetInt( p_vdec->p_fifo, "ffmpeg-pp-q" ),
512 config_GetInt( p_vdec->p_fifo, "ffmpeg-pp-auto" )
515 /* allocate table for postprocess */
516 // p_vdec->p_context->quant_store =
517 // malloc( sizeof( int ) * ( MBR + 1 ) * ( MBC + 1 ) );
518 // p_vdec->p_context->qstride = MBC + 1;
521 p_vdec->i_pp_mode = 0;
522 msg_Warn( p_vdec->p_fifo,
523 "post-processing not supported, upgrade ffmpeg" );
527 p_vdec->i_pp_mode = 0;
528 msg_Warn( p_vdec->p_fifo,
529 "Post processing unsupported for this codec" );
534 // memset( &p_vdec->statistic, 0, sizeof( statistic_t ) );
539 /*****************************************************************************
540 * DecodeThread: Called to decode one frame
541 *****************************************************************************
542 * We have to get a frame stored in a pes, give it to ffmpeg decoder and send
543 * the image to the output.
544 *****************************************************************************/
545 void E_( DecodeThread_Video )( vdec_thread_t *p_vdec )
552 AVPicture avpicture; /* ffmpeg picture */
553 picture_t *p_pic; /* videolan picture */
556 /* TODO implement it in a better way */
557 /* A good idea could be to decode all I pictures and see for the other */
558 if( ( p_vdec->b_hurry_up )&& ( p_vdec->i_frame_late > 4 ) )
560 #if LIBAVCODEC_BUILD > 4603
562 if( p_vdec->i_frame_late < 8 )
564 p_vdec->p_context->hurry_up = 2;
568 /* too much late picture, won't decode
569 but break picture until a new I, and for mpeg4 ...*/
570 p_vdec->i_frame_late--; /* needed else it will never be decrease */
571 input_ExtractPES( p_vdec->p_fifo, NULL );
575 if( p_vdec->i_frame_late < 8 )
577 b_drawpicture = 0; /* not really good but .. UPGRADE FFMPEG !! */
581 /* too much late picture, won't decode
582 but break picture until a new I, and for mpeg4 ...*/
583 p_vdec->i_frame_late--; /* needed else it will never be decrease */
584 input_ExtractPES( p_vdec->p_fifo, NULL );
592 #if LIBAVCODEC_BUILD > 4603
593 p_vdec->p_context->hurry_up = 0;
599 input_ExtractPES( p_vdec->p_fifo, &p_pes );
602 p_vdec->p_fifo->b_error = 1;
606 if( p_vdec->i_codec_id == CODEC_ID_MPEG1VIDEO )
610 p_vdec->pts = p_pes->i_dts;
611 p_vdec->i_frame_count = 0;
618 p_vdec->pts = p_pes->i_pts;
619 p_vdec->i_frame_count = 0;
625 p_vdec->pts = p_pes->i_pts;
626 p_vdec->i_frame_count = 0;
629 i_frame_size = p_pes->i_pes_size;
631 if( i_frame_size > 0 )
635 /* XXX Don't forget that ffmpeg required a little more bytes
636 * that the real frame size */
637 i_need = i_frame_size + 16 + p_vdec->i_buffer;
638 if( p_vdec->i_buffer_size < i_need)
640 p_last = p_vdec->p_buffer;
641 p_vdec->p_buffer = malloc( i_need );
642 p_vdec->i_buffer_size = i_need;
643 if( p_vdec->i_buffer > 0 )
645 memcpy( p_vdec->p_buffer, p_last, p_vdec->i_buffer );
650 E_( GetPESData )( p_vdec->p_buffer + p_vdec->i_buffer,
653 memset( p_vdec->p_buffer + p_vdec->i_buffer + i_frame_size,
657 input_DeletePES( p_vdec->p_fifo->p_packets_mgt, p_pes );
658 } while( i_frame_size <= 0 );
660 i_frame_size += p_vdec->i_buffer;
663 i_used = avcodec_decode_video( p_vdec->p_context,
670 msg_Dbg( p_vdec->p_fifo,
671 "used:%d framesize:%d (%s picture)",
672 i_used, i_frame_size, b_gotpicture ? "got":"no got" );
676 msg_Warn( p_vdec->p_fifo, "cannot decode one frame (%d bytes)",
678 p_vdec->i_frame_error++;
679 p_vdec->i_buffer = 0;
682 else if( i_used < i_frame_size )
685 msg_Dbg( p_vdec->p_fifo,
686 "didn't use all memory(%d < %d)", i_used, i_frame_size );
688 memmove( p_vdec->p_buffer,
689 p_vdec->p_buffer + i_used,
690 p_vdec->i_buffer_size - i_used );
692 p_vdec->i_buffer = i_frame_size - i_used;
696 p_vdec->i_buffer = 0;
701 p_vdec->i_frame_count++;
705 i_frame_size -= i_used;
707 /* Update frame late count*/
708 /* I don't make statistic on decoding time */
709 if( p_vdec->pts <= mdate())
711 p_vdec->i_frame_late++;
715 p_vdec->i_frame_late = 0;
718 if( !b_gotpicture || avpicture.linesize[0] == 0 || !b_drawpicture )
723 if( !p_vdec->b_direct_rendering )
726 if( !ffmpeg_CheckVout( p_vdec->p_vout,
727 p_vdec->p_context->width,
728 p_vdec->p_context->height,
729 ffmpeg_PixFmtToChroma(p_vdec->p_context->pix_fmt)) )
731 p_vdec->p_vout = ffmpeg_CreateVout( p_vdec, p_vdec->p_context );
732 if( !p_vdec->p_vout )
734 msg_Err( p_vdec->p_fifo, "cannot create vout" );
735 p_vdec->p_fifo->b_error = 1; /* abort */
740 /* Get a new picture */
741 while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
743 if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error )
747 msleep( VOUT_OUTMEM_SLEEP );
750 /* fill p_picture_t from avpicture, do I410->I420 if needed */
751 ffmpeg_CopyPicture( p_pic, &avpicture, p_vdec );
755 #if LIBAVCODEC_BUILD > 4615
756 p_pic = (picture_t *)p_vdec->p_context->dr_opaque_frame;
760 /* Do post-processing if requested */
761 ffmpeg_PostProcPicture( p_vdec, p_pic );
763 /* Send decoded frame to vout */
764 if( p_vdec->pts > 0 )
768 if( p_vdec->p_context->frame_rate > 0 )
770 i_pts += (uint64_t)1000000 *
771 ( p_vdec->i_frame_count - 1) /
773 p_vdec->p_context->frame_rate;
778 i_pts = mdate() + DEFAULT_PTS_DELAY; // FIXME
781 vout_DatePicture( p_vdec->p_vout,
785 vout_DisplayPicture( p_vdec->p_vout, p_pic );
787 if( i_frame_size > 0 )
793 /*****************************************************************************
794 * EndThread: thread destruction
795 *****************************************************************************
796 * This function is called when the thread ends after a sucessful
798 *****************************************************************************/
799 void E_( EndThread_Video )( vdec_thread_t *p_vdec )
801 if( p_vdec->p_secondlastpic )
802 vout_UnlinkPicture( p_vdec->p_vout, p_vdec->p_secondlastpic );
803 if( p_vdec->p_lastpic )
804 vout_UnlinkPicture( p_vdec->p_vout, p_vdec->p_lastpic );
808 /* release postprocessing module */
809 module_Unneed( p_vdec->p_pp, p_vdec->p_pp->p_module );
810 vlc_object_destroy( p_vdec->p_pp );
814 if( p_vdec->p_vout != NULL )
816 /* We are about to die. Reattach video output to p_vlc. */
817 vlc_object_detach( p_vdec->p_vout );
818 vlc_object_attach( p_vdec->p_vout, p_vdec->p_fifo->p_vlc );
822 /*****************************************************************************
823 * ffmpeg_CopyPicture: copy a picture from ffmpeg internal buffers to a
824 * picture_t structure (when not in direct rendering mode).
825 *****************************************************************************/
826 static void ffmpeg_CopyPicture( picture_t *p_pic, AVPicture *p_avpicture,
827 vdec_thread_t *p_vdec )
838 if( ffmpeg_PixFmtToChroma( p_vdec->p_context->pix_fmt ) )
840 for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
842 p_src = p_avpicture->data[i_plane];
843 p_dst = p_pic->p[i_plane].p_pixels;
844 i_src_stride = p_avpicture->linesize[i_plane];
845 i_dst_stride = p_pic->p[i_plane].i_pitch;
847 i_size = __MIN( i_src_stride, i_dst_stride );
848 for( i_line = 0; i_line < p_pic->p[i_plane].i_lines; i_line++ )
850 p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, i_size );
851 p_src += i_src_stride;
852 p_dst += i_dst_stride;
858 /* we need to convert to I420 */
859 switch( p_vdec->p_context->pix_fmt )
861 #if LIBAVCODEC_BUILD >= 4615
862 case( PIX_FMT_YUV410P ):
863 ffmpeg_ConvertPictureI410toI420( p_pic, p_avpicture, p_vdec );
867 p_vdec->p_fifo->b_error = 1;
873 /*****************************************************************************
874 * ffmpeg_PostProcPicture: Postprocessing is done here.
875 *****************************************************************************/
876 static void ffmpeg_PostProcPicture( vdec_thread_t *p_vdec, picture_t *p_pic )
878 #if LIBAVCODEC_BUILD > 4313
879 if( ( p_vdec->i_pp_mode )&&
880 ( ( p_vdec->p_vout->render.i_chroma ==
881 VLC_FOURCC( 'I','4','2','0' ) )||
882 ( p_vdec->p_vout->render.i_chroma ==
883 VLC_FOURCC( 'Y','V','1','2' ) ) ) )
886 p_vdec->p_pp->pf_postprocess( p_pic,
887 p_vdec->p_context->display_qscale_table,
888 // p_vdec->p_context->current_qscale_table,
889 p_vdec->p_context->qstride,
895 /*****************************************************************************
896 * ffmpeg_GetFrameBuf: callback used by ffmpeg to get a frame buffer.
897 * (used for direct rendering)
898 *****************************************************************************/
899 static int ffmpeg_GetFrameBuf( struct AVCodecContext *avctx, int width,
900 int height, int pict_type )
902 #if LIBAVCODEC_BUILD > 4615
903 vdec_thread_t *p_vdec = (vdec_thread_t *)avctx->opaque;
907 if( !ffmpeg_CheckVout( p_vdec->p_vout,
908 p_vdec->p_context->width,
909 p_vdec->p_context->height,
910 ffmpeg_PixFmtToChroma(p_vdec->p_context->pix_fmt)) )
912 p_vdec->p_vout = ffmpeg_CreateVout( p_vdec, p_vdec->p_context );
913 if( !p_vdec->p_vout )
915 msg_Err( p_vdec->p_fifo, "cannot create vout" );
916 p_vdec->p_fifo->b_error = 1; /* abort */
921 /* Get a new picture */
922 while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
924 if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error )
928 msleep( VOUT_OUTMEM_SLEEP );
931 /* FIXME: We keep the last picture linked until the current one is decoded,
932 * this trick won't work with streams with B frames though. */
933 vout_LinkPicture( p_vdec->p_vout, p_pic );
934 if( p_vdec->p_secondlastpic )
935 vout_UnlinkPicture( p_vdec->p_vout, p_vdec->p_secondlastpic );
936 p_vdec->p_secondlastpic = p_vdec->p_lastpic;
937 p_vdec->p_lastpic = p_pic;
939 avctx->draw_horiz_band= NULL;
940 avctx->dr_buffer[0]= p_pic->p[0].p_pixels;
941 avctx->dr_buffer[1]= p_pic->p[1].p_pixels;
942 avctx->dr_buffer[2]= p_pic->p[2].p_pixels;
944 avctx->dr_stride = p_pic->p[0].i_pitch;
945 avctx->dr_uvstride = p_pic->p[1].i_pitch;
947 avctx->dr_opaque_frame = p_pic;
949 /* This variable is used to determine if a macro-block to be written
950 * can be skipped. The idea behind this is that if a macro-block hasn't
951 * changed and all the frame-buffers already have the value of this
952 * macro-block, then we don't need to write it again. */
953 avctx->dr_ip_buffer_count = p_vdec->p_vout->render.i_pictures;
954 p_vdec->p_vout->render.b_allow_modify_pics = 0;