Commit 79da0194 authored by Laurent Aimar's avatar Laurent Aimar

* ffmpeg: sync with latest ffmpeg cvs. As it need too much

#if LIBAVCODEC_BUILD , I've enable direct rendering only with latest
ffmpeg cvs (anyway dr isn't cleanly ported to the latest version).
parent 1b7ce269
......@@ -2,7 +2,7 @@
* video.c: video decoder using ffmpeg library
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: video.c,v 1.8 2002/11/28 17:35:00 sam Exp $
* $Id: video.c,v 1.9 2002/12/06 11:53:45 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Gildas Bazin <gbazin@netcourrier.com>
......@@ -49,53 +49,44 @@
/*****************************************************************************
* Local prototypes
*****************************************************************************/
#if LIBAVCODEC_BUILD >= 4641
static void ffmpeg_CopyPicture( picture_t *, AVVideoFrame *, vdec_thread_t * );
#else
static void ffmpeg_CopyPicture( picture_t *, AVPicture *, vdec_thread_t * );
#endif
static void ffmpeg_PostProcPicture( vdec_thread_t *, picture_t * );
static int ffmpeg_GetFrameBuf( struct AVCodecContext *, int, int, int );
/* FIXME FIXME some of them are wrong */
static int i_ffmpeg_PixFmtToChroma[] =
{
/* PIX_FMT_ANY = -1, PIX_FMT_YUV420P,
PIX_FMT_YUV422, PIX_FMT_RGB24,
PIX_FMT_BGR24, PIX_FMT_YUV422P,
PIX_FMT_YUV444P, PIX_FMT_YUV410P
*/
0, VLC_FOURCC('I','4','2','0'),
VLC_FOURCC('I','4','2','0'), VLC_FOURCC('R','V','2','4'),
0, VLC_FOURCC('I','4','2','2'),
VLC_FOURCC('I','4','4','4'), 0
};
#if LIBAVCODEC_BUILD >= 4641
static int ffmpeg_GetFrameBuf( struct AVCodecContext *, AVVideoFrame *);
static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *, AVVideoFrame *);
#endif
/*****************************************************************************
* Local Functions
*****************************************************************************/
static inline u32 ffmpeg_PixFmtToChroma( int i_ffmpegchroma )
static inline uint32_t ffmpeg_PixFmtToChroma( int i_ff_chroma )
{
if( ++i_ffmpegchroma > 7 )
{
return( 0 );
}
else
{
return( i_ffmpeg_PixFmtToChroma[i_ffmpegchroma] );
}
}
static inline int ffmpeg_FfAspect( int i_width, int i_height, int i_ffaspect )
{
switch( i_ffaspect )
{
case( FF_ASPECT_4_3_625 ):
case( FF_ASPECT_4_3_525 ):
return( VOUT_ASPECT_FACTOR * 4 / 3);
case( FF_ASPECT_16_9_625 ):
case( FF_ASPECT_16_9_525 ):
return( VOUT_ASPECT_FACTOR * 16 / 9 );
case( FF_ASPECT_SQUARE ):
/* FIXME FIXME some of them are wrong */
switch( i_ff_chroma )
{
case PIX_FMT_YUV420P:
case PIX_FMT_YUV422:
return( VLC_FOURCC('I','4','2','0') );
case PIX_FMT_RGB24:
return( VLC_FOURCC('R','V','2','4') );
case PIX_FMT_YUV422P:
return( VLC_FOURCC('I','4','2','2') );
case PIX_FMT_YUV444P:
return( VLC_FOURCC('I','4','4','4') );
#if LIBAVCODEC_BUILD >= 4615
case PIX_FMT_YUV410P:
#endif
case PIX_FMT_BGR24:
default:
return( VOUT_ASPECT_FACTOR * i_width / i_height );
return( 0 );
}
}
......@@ -122,15 +113,12 @@ static vout_thread_t *ffmpeg_CreateVout( vdec_thread_t *p_vdec,
/* It's mainly for I410 -> I420 conversion that I've made,
it's buggy and very slow */
}
#if LIBAVCODEC_BUILD >= 4640
i_aspect = (int) ( VOUT_ASPECT_FACTOR * p_vdec->p_context->aspect_ratio );
if( i_aspect == 0 )
if( ( i_aspect = (int) ( VOUT_ASPECT_FACTOR *
p_vdec->p_context->aspect_ratio ) ) == 0 )
{
i_aspect = VOUT_ASPECT_FACTOR * i_width / i_height;
}
#else
switch( p_vdec->p_context->aspect_ratio_info )
{
......@@ -141,13 +129,14 @@ static vout_thread_t *ffmpeg_CreateVout( vdec_thread_t *p_vdec,
case( FF_ASPECT_16_9_625 ):
case( FF_ASPECT_16_9_525 ):
i_aspect = VOUT_ASPECT_FACTOR * 16 / 9 ;
break;
break;
case( FF_ASPECT_SQUARE ):
default:
i_aspect = VOUT_ASPECT_FACTOR * i_width / i_height;
i_aspect = VOUT_ASPECT_FACTOR * i_width / i_height;
break;
}
}
#endif
/* Spawn a video output if there is none. First we look for our children,
* then we look for any other vout that might be available. */
p_vout = vout_Request( p_vdec->p_fifo, NULL,
......@@ -161,9 +150,15 @@ static vout_thread_t *ffmpeg_CreateVout( vdec_thread_t *p_vdec,
or said to me how write a better thing
FIXME FIXME FIXME
*/
#if LIBAVCODEC_BUILD >= 4641
static void ffmpeg_ConvertPictureI410toI420( picture_t *p_pic,
AVVideoFrame *p_ff_pic,
vdec_thread_t *p_vdec )
#else
static void ffmpeg_ConvertPictureI410toI420( picture_t *p_pic,
AVPicture *p_avpicture,
AVPicture *p_ff_pic,
vdec_thread_t *p_vdec )
#endif
{
u8 *p_src, *p_dst;
u8 *p_plane[3];
......@@ -177,24 +172,24 @@ static void ffmpeg_ConvertPictureI410toI420( picture_t *p_pic,
i_width = p_vdec->p_context->width;
p_dst = p_pic->p[0].p_pixels;
p_src = p_avpicture->data[0];
p_src = p_ff_pic->data[0];
/* copy first plane */
for( i_y = 0; i_y < i_height; i_y++ )
{
p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, i_width);
p_dst += p_pic->p[0].i_pitch;
p_src += p_avpicture->linesize[0];
p_src += p_ff_pic->linesize[0];
}
/* process each plane in a temporary buffer */
for( i_plane = 1; i_plane < 3; i_plane++ )
{
i_stride = p_avpicture->linesize[i_plane];
i_stride = p_ff_pic->linesize[i_plane];
i_lines = i_height / 4;
p_dst = p_plane[i_plane] = malloc( i_lines * i_stride * 2 * 2 );
p_src = p_avpicture->data[i_plane];
p_src = p_ff_pic->data[i_plane];
/* for each source line */
for( i_y = 0; i_y < i_lines; i_y++ )
......@@ -215,7 +210,7 @@ static void ffmpeg_ConvertPictureI410toI420( picture_t *p_pic,
for( i_plane = 1; i_plane < 3; i_plane++ )
{
i_stride = p_avpicture->linesize[i_plane];
i_stride = p_ff_pic->linesize[i_plane];
i_lines = i_height / 4;
p_dst = p_plane[i_plane] + 2*i_stride;
......@@ -277,6 +272,11 @@ static void ffmpeg_ConvertPictureI410toI420( picture_t *p_pic,
int E_( InitThread_Video )( vdec_thread_t *p_vdec )
{
int i_tmp;
#if LIBAVCODEC_BUILD >= 4641
p_vdec->p_ff_pic = avcodec_alloc_picture();
#else
p_vdec->p_ff_pic = &p_vdec->ff_pic;
#endif
if( p_vdec->p_fifo->p_demux_data )
{
......@@ -311,19 +311,20 @@ int E_( InitThread_Video )( vdec_thread_t *p_vdec )
p_vdec->b_hurry_up = config_GetInt(p_vdec->p_fifo, "ffmpeg-hurry-up");
p_vdec->p_lastpic = NULL;
p_vdec->p_secondlastpic = NULL;
p_vdec->b_direct_rendering = 0;
#if LIBAVCODEC_BUILD > 4615
if( (p_vdec->p_codec->capabilities & CODEC_CAP_DR1)
&& (p_vdec->p_context->pix_fmt != PIX_FMT_YUV410P) &&
config_GetInt( p_vdec->p_fifo, "ffmpeg-dr" ) )
#if LIBAVCODEC_BUILD >= 4641
if( config_GetInt( p_vdec->p_fifo, "ffmpeg-dr" ) &&
p_vdec->p_codec->capabilities & CODEC_CAP_DR1 &&
p_vdec->p_context->pix_fmt != PIX_FMT_YUV410P ) /* <- FIXME */
{
msg_Dbg( p_vdec->p_fifo, "using direct rendering" );
p_vdec->b_direct_rendering = 1;
p_vdec->p_context->flags|= CODEC_FLAG_EMU_EDGE | CODEC_FLAG_DR1;
p_vdec->p_context->get_buffer_callback = ffmpeg_GetFrameBuf;
p_vdec->p_context->flags|= CODEC_FLAG_EMU_EDGE;
p_vdec->p_context->get_buffer = ffmpeg_GetFrameBuf;
p_vdec->p_context->release_buffer = ffmpeg_ReleaseFrameBuf;
p_vdec->p_context->opaque = p_vdec;
}
#endif
......@@ -354,13 +355,12 @@ int E_( InitThread_Video )( vdec_thread_t *p_vdec )
if( p_vdec->p_format &&
p_vdec->p_format->biSize > sizeof(BITMAPINFOHEADER) )
{
AVPicture avpicture;
int b_gotpicture;
switch( p_vdec->i_codec_id )
{
case( CODEC_ID_MPEG4 ):
avcodec_decode_video( p_vdec->p_context, &avpicture,
avcodec_decode_video( p_vdec->p_context, p_vdec->p_ff_pic,
&b_gotpicture,
(void *)&p_vdec->p_format[1],
p_vdec->p_format->biSize
......@@ -450,11 +450,6 @@ int E_( InitThread_Video )( vdec_thread_t *p_vdec )
config_GetInt( p_vdec->p_fifo, "ffmpeg-pp-q" ),
config_GetInt( p_vdec->p_fifo, "ffmpeg-pp-auto" )
);
/* allocate table for postprocess */
// p_vdec->p_context->quant_store =
// malloc( sizeof( int ) * ( MBR + 1 ) * ( MBC + 1 ) );
// p_vdec->p_context->qstride = MBC + 1;
}
#else
p_vdec->i_pp_mode = 0;
......@@ -488,7 +483,6 @@ void E_( DecodeThread_Video )( vdec_thread_t *p_vdec )
int i_used;
int b_drawpicture;
int b_gotpicture;
AVPicture avpicture; /* ffmpeg picture */
picture_t *p_pic; /* videolan picture */
mtime_t i_pts;
......@@ -496,7 +490,6 @@ void E_( DecodeThread_Video )( vdec_thread_t *p_vdec )
/* A good idea could be to decode all I pictures and see for the other */
if( ( p_vdec->b_hurry_up )&& ( p_vdec->i_frame_late > 4 ) )
{
#if LIBAVCODEC_BUILD > 4603
b_drawpicture = 0;
if( p_vdec->i_frame_late < 8 )
{
......@@ -510,27 +503,11 @@ void E_( DecodeThread_Video )( vdec_thread_t *p_vdec )
input_ExtractPES( p_vdec->p_fifo, NULL );
return;
}
#else
if( p_vdec->i_frame_late < 8 )
{
b_drawpicture = 0; /* not really good but .. UPGRADE FFMPEG !! */
}
else
{
/* too much late picture, won't decode
but break picture until a new I, and for mpeg4 ...*/
p_vdec->i_frame_late--; /* needed else it will never be decrease */
input_ExtractPES( p_vdec->p_fifo, NULL );
return;
}
#endif
}
else
{
b_drawpicture = 1;
#if LIBAVCODEC_BUILD > 4603
p_vdec->p_context->hurry_up = 0;
#endif
}
do
......@@ -600,7 +577,7 @@ void E_( DecodeThread_Video )( vdec_thread_t *p_vdec )
usenextdata:
i_used = avcodec_decode_video( p_vdec->p_context,
&avpicture,
p_vdec->p_ff_pic,
&b_gotpicture,
p_vdec->p_buffer,
i_frame_size );
......@@ -654,7 +631,7 @@ usenextdata:
p_vdec->i_frame_late = 0;
}
if( !b_gotpicture || avpicture.linesize[0] == 0 || !b_drawpicture )
if( !b_gotpicture || p_vdec->p_ff_pic->linesize[0] == 0 || !b_drawpicture )
{
return;
}
......@@ -679,20 +656,24 @@ usenextdata:
msleep( VOUT_OUTMEM_SLEEP );
}
/* fill p_picture_t from avpicture, do I410->I420 if needed */
ffmpeg_CopyPicture( p_pic, &avpicture, p_vdec );
/* fill p_picture_t from AVVideoFrame, do I410->I420 if needed */
ffmpeg_CopyPicture( p_pic, p_vdec->p_ff_pic, p_vdec );
}
else
{
#if LIBAVCODEC_BUILD > 4615
p_pic = (picture_t *)p_vdec->p_context->dr_opaque_frame;
#if LIBAVCODEC_BUILD >= 4641
p_pic = (picture_t *)p_vdec->p_ff_pic->opaque;
#else
p_pic = NULL; /* f**ck gcc warning */
#endif
}
/* Do post-processing if requested */
ffmpeg_PostProcPicture( p_vdec, p_pic );
/* XXX: with dr it is not a good thing if the picture will be used as
reference... */
ffmpeg_PostProcPicture( p_vdec, p_pic );
/* Send decoded frame to vout */
/* fix date calculation */
if( p_vdec->pts > 0 )
{
i_pts = p_vdec->pts;
......@@ -714,11 +695,12 @@ usenextdata:
p_pic,
i_pts );
/* Send decoded frame to vout */
vout_DisplayPicture( p_vdec->p_vout, p_pic );
if( i_frame_size > 0 )
{
goto usenextdata;
goto usenextdata; /* try to use all data */
}
}
......@@ -730,10 +712,6 @@ usenextdata:
*****************************************************************************/
void E_( EndThread_Video )( vdec_thread_t *p_vdec )
{
if( p_vdec->p_secondlastpic )
vout_UnlinkPicture( p_vdec->p_vout, p_vdec->p_secondlastpic );
if( p_vdec->p_lastpic )
vout_UnlinkPicture( p_vdec->p_vout, p_vdec->p_lastpic );
if( p_vdec->p_pp )
{
......@@ -743,6 +721,13 @@ void E_( EndThread_Video )( vdec_thread_t *p_vdec )
p_vdec->p_pp = NULL;
}
#if LIBAVCODEC_BUILD >= 4641
if( p_vdec->p_ff_pic )
{
free( p_vdec->p_ff_pic );
}
#endif
/* We are about to die. Reattach video output to p_vlc. */
vout_Request( p_vdec->p_fifo, p_vdec->p_vout, 0, 0, 0, 0 );
}
......@@ -751,8 +736,15 @@ void E_( EndThread_Video )( vdec_thread_t *p_vdec )
* ffmpeg_CopyPicture: copy a picture from ffmpeg internal buffers to a
* picture_t structure (when not in direct rendering mode).
*****************************************************************************/
static void ffmpeg_CopyPicture( picture_t *p_pic, AVPicture *p_avpicture,
#if LIBAVCODEC_BUILD >= 4641
static void ffmpeg_CopyPicture( picture_t *p_pic,
AVVideoFrame *p_ff_pic,
vdec_thread_t *p_vdec )
#else
static void ffmpeg_CopyPicture( picture_t *p_pic,
AVPicture *p_ff_pic,
vdec_thread_t *p_vdec )
#endif
{
int i_plane;
int i_size;
......@@ -767,9 +759,9 @@ static void ffmpeg_CopyPicture( picture_t *p_pic, AVPicture *p_avpicture,
{
for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
{
p_src = p_avpicture->data[i_plane];
p_src = p_ff_pic->data[i_plane];
p_dst = p_pic->p[i_plane].p_pixels;
i_src_stride = p_avpicture->linesize[i_plane];
i_src_stride = p_ff_pic->linesize[i_plane];
i_dst_stride = p_pic->p[i_plane].i_pitch;
i_size = __MIN( i_src_stride, i_dst_stride );
......@@ -788,7 +780,7 @@ static void ffmpeg_CopyPicture( picture_t *p_pic, AVPicture *p_avpicture,
{
#if LIBAVCODEC_BUILD >= 4615
case( PIX_FMT_YUV410P ):
ffmpeg_ConvertPictureI410toI420( p_pic, p_avpicture, p_vdec );
ffmpeg_ConvertPictureI410toI420( p_pic, p_ff_pic, p_vdec );
break;
#endif
default:
......@@ -803,35 +795,40 @@ static void ffmpeg_CopyPicture( picture_t *p_pic, AVPicture *p_avpicture,
*****************************************************************************/
static void ffmpeg_PostProcPicture( vdec_thread_t *p_vdec, picture_t *p_pic )
{
#if LIBAVCODEC_BUILD > 4313
if( ( p_vdec->i_pp_mode )&&
( ( p_vdec->p_vout->render.i_chroma ==
VLC_FOURCC( 'I','4','2','0' ) )||
( p_vdec->p_vout->render.i_chroma ==
VLC_FOURCC( 'Y','V','1','2' ) ) ) )
{
/* Make postproc */
#if LIBAVCODEC_BUILD >= 4641
/* Make postproc */
p_vdec->p_pp->pf_postprocess( p_pic,
p_vdec->p_ff_pic->qscale_table,
p_vdec->p_ff_pic->qstride,
p_vdec->i_pp_mode );
#elif LIBAVCODEC_BUILD >= 4633
p_vdec->p_pp->pf_postprocess( p_pic,
p_vdec->p_context->display_qscale_table,
// p_vdec->p_context->current_qscale_table,
p_vdec->p_context->qstride,
p_vdec->i_pp_mode );
}
#endif
}
}
#if LIBAVCODEC_BUILD >= 4641
/*****************************************************************************
* ffmpeg_GetFrameBuf: callback used by ffmpeg to get a frame buffer.
* (used for direct rendering)
*****************************************************************************/
static int ffmpeg_GetFrameBuf( struct AVCodecContext *avctx, int width,
int height, int pict_type )
static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context,
AVVideoFrame *p_ff_pic )
{
#if LIBAVCODEC_BUILD > 4615
vdec_thread_t *p_vdec = (vdec_thread_t *)avctx->opaque;
vdec_thread_t *p_vdec = (vdec_thread_t *)p_context->opaque;
picture_t *p_pic;
/* Check our vout */
/* Check and (re)create if needed our vout */
p_vdec->p_vout = ffmpeg_CreateVout( p_vdec, p_vdec->p_context );
if( !p_vdec->p_vout )
{
......@@ -839,6 +836,7 @@ static int ffmpeg_GetFrameBuf( struct AVCodecContext *avctx, int width,
p_vdec->p_fifo->b_error = 1; /* abort */
return -1;
}
p_vdec->p_vout->render.b_allow_modify_pics = 0;
/* Get a new picture */
while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
......@@ -849,32 +847,47 @@ static int ffmpeg_GetFrameBuf( struct AVCodecContext *avctx, int width,
}
msleep( VOUT_OUTMEM_SLEEP );
}
p_vdec->p_context->draw_horiz_band= NULL;
p_ff_pic->opaque = (void*)p_pic;
p_ff_pic->data[0] = p_pic->p[0].p_pixels;
p_ff_pic->data[1] = p_pic->p[1].p_pixels;
p_ff_pic->data[2] = p_pic->p[2].p_pixels;
p_ff_pic->data[3] = NULL; /* alpha channel but I'm not sure */
p_ff_pic->linesize[0] = p_pic->p[0].i_pitch;
p_ff_pic->linesize[1] = p_pic->p[1].i_pitch;
p_ff_pic->linesize[2] = p_pic->p[2].i_pitch;
p_ff_pic->linesize[3] = 0;
if( p_ff_pic->reference != 0 )
{
vout_LinkPicture( p_vdec->p_vout, p_pic );
}
/* FIXME what is that, should give good value */
p_ff_pic->age = 256*256*256*64; // FIXME FIXME from ffmpeg
/* FIXME: We keep the last picture linked until the current one is decoded,
* this trick won't work with streams with B frames though. */
vout_LinkPicture( p_vdec->p_vout, p_pic );
if( p_vdec->p_secondlastpic )
vout_UnlinkPicture( p_vdec->p_vout, p_vdec->p_secondlastpic );
p_vdec->p_secondlastpic = p_vdec->p_lastpic;
p_vdec->p_lastpic = p_pic;
return( 0 );
}
static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *p_context,
AVVideoFrame *p_ff_pic )
{
vdec_thread_t *p_vdec = (vdec_thread_t *)p_context->opaque;
picture_t *p_pic;
avctx->draw_horiz_band= NULL;
avctx->dr_buffer[0]= p_pic->p[0].p_pixels;
avctx->dr_buffer[1]= p_pic->p[1].p_pixels;
avctx->dr_buffer[2]= p_pic->p[2].p_pixels;
//msg_Dbg( p_vdec->p_fifo, "ffmpeg_ReleaseFrameBuf" );
p_pic = (picture_t*)p_ff_pic->opaque;
avctx->dr_stride = p_pic->p[0].i_pitch;
avctx->dr_uvstride = p_pic->p[1].i_pitch;
p_ff_pic->data[0] = NULL;
p_ff_pic->data[1] = NULL;
p_ff_pic->data[2] = NULL;
p_ff_pic->data[3] = NULL;
avctx->dr_opaque_frame = p_pic;
vout_UnlinkPicture( p_vdec->p_vout, p_pic );
}
/* This variable is used to determine if a macro-block to be written
* can be skipped. The idea behind this is that if a macro-block hasn't
* changed and all the frame-buffers already have the value of this
* macro-block, then we don't need to write it again. */
avctx->dr_ip_buffer_count = p_vdec->p_vout->render.i_pictures;
p_vdec->p_vout->render.b_allow_modify_pics = 0;
return 0;
#endif
}
......@@ -2,7 +2,7 @@
* video.h: video decoder using ffmpeg library
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: video.h,v 1.4 2002/11/27 12:41:45 fenrir Exp $
* $Id: video.h,v 1.5 2002/12/06 11:53:45 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
......@@ -24,7 +24,11 @@
typedef struct vdec_thread_s
{
DECODER_THREAD_COMMON
#if LIBAVCODEC_BUILD >= 4641
AVVideoFrame *p_ff_pic;
#else
AVPicture ff_pic, *p_ff_pic;
#endif
BITMAPINFOHEADER *p_format;
vout_thread_t *p_vout;
......@@ -43,8 +47,6 @@ typedef struct vdec_thread_s
/* for direct rendering */
int b_direct_rendering;
picture_t *p_lastpic;
picture_t *p_secondlastpic;
} vdec_thread_t;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment