xvmc support

git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@10363 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
iive 2003-07-01 22:05:46 +00:00
parent 25a5f06b64
commit e405703e68
1 changed files with 178 additions and 2 deletions

View File

@ -47,6 +47,15 @@ LIBVD_EXTERN(ffmpeg)
#define PIX_FMT_RGBA32 PIX_FMT_BGRA32
#endif
//!!TODO!! when ffmpeg is patched set correct version number
#if LIBAVCODEC_BUILD < 4669
#undef HAVE_XVMC
#endif
#ifdef HAVE_XVMC
#include "xvmc_render.h"
#endif
int avcodec_inited=0;
#if defined(FF_POSTPROCESS) && defined(MBR)
@ -79,6 +88,14 @@ typedef struct {
static int get_buffer(AVCodecContext *avctx, AVFrame *pic);
static void release_buffer(AVCodecContext *avctx, AVFrame *pic);
#ifdef HAVE_XVMC
static int mc_get_buffer(AVCodecContext *avctx, AVFrame *pic);
static void mc_release_buffer(AVCodecContext *avctx, AVFrame *pic);
static void mc_render_slice(struct AVCodecContext *s,
uint8_t **src, int linesize,
int y, int width, int height);
#endif
static int lavc_param_workaround_bugs= FF_BUG_AUTODETECT;
static int lavc_param_error_resilience=2;
static int lavc_param_error_concealment=3;
@ -106,9 +123,15 @@ static int control(sh_video_t *sh,int cmd,void* arg,...){
AVCodecContext *avctx = ctx->avctx;
switch(cmd){
case VDCTRL_QUERY_FORMAT:
if( (*((int*)arg)) == ctx->best_csp ) return CONTROL_TRUE;//supported
{
int format =(*((int*)arg));
if( format == ctx->best_csp ) return CONTROL_TRUE;//supported
#ifdef HAVE_XVMC
if( (avctx->pix_fmt == PIX_FMT_XVMC) && IMGFMT_IS_XVMC(format) )
return CONTROL_TRUE;
#endif
// possible conversions:
switch( (*((int*)arg)) ){
switch( format ){
case IMGFMT_YV12:
case IMGFMT_IYUV:
case IMGFMT_I420:
@ -119,6 +142,7 @@ static int control(sh_video_t *sh,int cmd,void* arg,...){
}
return CONTROL_FALSE;
}
}
return CONTROL_UNKNOWN;
}
@ -164,6 +188,17 @@ static int init(sh_video_t *sh){
ctx->avctx = avcodec_alloc_context();
avctx = ctx->avctx;
#ifdef HAVE_XVMC
if(lavc_codec->id == CODEC_ID_MPEG2VIDEO_XVMC){
printf("vd_ffmpeg: XVMC accelerated MPEG2\n");
assert(ctx->do_dr1);//these are must to!
assert(ctx->do_slices); //it is (vo_)ffmpeg bug if this fails
avctx->flags|= CODEC_FLAG_EMU_EDGE;//do i need that??!!
avctx->get_buffer= mc_get_buffer;
avctx->release_buffer= mc_release_buffer;
avctx->draw_horiz_band = mc_render_slice;
}else
#endif
if(ctx->do_dr1){
avctx->flags|= CODEC_FLAG_EMU_EDGE;
avctx->get_buffer= get_buffer;
@ -359,6 +394,11 @@ static int init_vo(sh_video_t *sh){
case PIX_FMT_YUV422: ctx->best_csp=IMGFMT_YUY2;break; //huffyuv perhaps in the future
case PIX_FMT_RGB24 : ctx->best_csp=IMGFMT_BGR24;break; //huffyuv
case PIX_FMT_RGBA32: ctx->best_csp=IMGFMT_BGR32;break; //huffyuv
#ifdef HAVE_XVMC
case PIX_FMT_XVMC: //ctx->best_csp=IMGFMT_XVMC_MPEG2;
ctx->best_csp=sh->codec->outfmt[sh->outfmtidx];//!!maybe!!??
break;
#endif
default:
ctx->best_csp=0;
}
@ -527,6 +567,11 @@ static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags){
if(len<=0) return NULL; // skipped frame
#ifdef HAVE_XVMC
// in fact if(!dr1) should be the only condition, but this way we hide an
//ffmpeg interlace (mpeg2) bug. use -noslices to avoid it.
if( (avctx->pix_fmt != PIX_FMT_XVMC) )// && (!dr1) )
#endif
avctx->draw_horiz_band=NULL;
avctx->opaque=sh;
if(ctx->vo_inited && !(flags&3) && !dr1){
@ -683,4 +728,135 @@ static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags){
return mpi;
}
#ifdef HAVE_XVMC
static int mc_get_buffer(AVCodecContext *avctx, AVFrame *pic){
sh_video_t * sh = avctx->opaque;
vd_ffmpeg_ctx *ctx = sh->context;
mp_image_t* mpi=NULL;
xvmc_render_state_t * render;
int flags= MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_PREFER_ALIGNED_STRIDE|
MP_IMGFLAG_DRAW_CALLBACK;
// printf("vd_ffmpeg::mc_get_buffer (xvmc) %d %d %d\n", pic->reference, ctx->ip_count, ctx->b_count);
if(avctx->pix_fmt != PIX_FMT_XVMC){
printf("vd_ffmpeg::mc_get_buffer should work only with XVMC format!!!");
assert(0);
exit(1);
}
assert(avctx->draw_horiz_band == mc_render_slice);
assert(avctx->release_buffer == mc_release_buffer);
if(verbose > 4)
printf("vd_ffmpeg::mc_get_buffer\n");
if(init_vo(sh)<0){
printf("vd_ffmpeg: Unexpected init_vo error\n");
exit(1);
}
if(!pic->reference){
ctx->b_count++;
}else{
ctx->ip_count++;
flags|= MP_IMGFLAG_PRESERVE|MP_IMGFLAG_READABLE;
}
mpi= mpcodecs_get_image(sh, MP_IMGTYPE_IPB,flags ,
avctx->width, avctx->height);
if(mpi==NULL){
printf("Unrecoverable error, render buffers not taken\n");
assert(0);
exit(1);
};
if( (mpi->flags & MP_IMGFLAG_DIRECT) == 0){
printf("Only buffers allocated by vo_xvmc allowed\n");
assert(0);
exit(1);
}
pic->data[0]= mpi->planes[0];
pic->data[1]= mpi->planes[1];
pic->data[2]= mpi->planes[2];
/* Note, some (many) codecs in libavcodec must have stride1==stride2 && no changes between frames
* lavc will check that and die with an error message, if its not true
*/
pic->linesize[0]= mpi->stride[0];
pic->linesize[1]= mpi->stride[1];
pic->linesize[2]= mpi->stride[2];
pic->opaque = mpi;
if(pic->reference){
//I or P frame
pic->age= ctx->ip_age[0];
ctx->ip_age[0]= ctx->ip_age[1]+1;
ctx->ip_age[1]= 1;
ctx->b_age++;
}else{
//B frame
pic->age= ctx->b_age;
ctx->ip_age[0]++;
ctx->ip_age[1]++;
ctx->b_age=1;
}
#if LIBAVCODEC_BUILD >= 4644
pic->type= FF_BUFFER_TYPE_USER;
#endif
render=(xvmc_render_state_t*)mpi->priv;//same as data[2]
assert(render != 0);
assert(render->magic == MP_XVMC_RENDER_MAGIC);
render->state |= MP_XVMC_STATE_PREDICTION;
return 0;
}
static void mc_release_buffer(AVCodecContext *avctx, AVFrame *pic){
mp_image_t* mpi= pic->opaque;
sh_video_t * sh = avctx->opaque;
vd_ffmpeg_ctx *ctx = sh->context;
xvmc_render_state_t * render;
int i;
if(ctx->ip_count <= 2 && ctx->b_count<=1){
if(mpi->flags&MP_IMGFLAG_PRESERVE)
ctx->ip_count--;
else
ctx->b_count--;
}
//printf("R%X %X\n", pic->linesize[0], pic->data[0]);
//mark the surface as not requared for prediction
render=(xvmc_render_state_t*)pic->data[2];//same as mpi->priv
assert(render!=NULL);
assert(render->magic==MP_XVMC_RENDER_MAGIC);
render->state&=~MP_XVMC_STATE_PREDICTION;
if(verbose > 4)
printf("vd_ffmpeg::mc_release buffer (render=%p)\n",render);
for(i=0; i<4; i++){
pic->data[i]= NULL;
}
}
static void mc_render_slice(struct AVCodecContext *s,
uint8_t **src, int linesize,
int y, int width, int height){
sh_video_t * sh = s->opaque;
int stride[3];
assert(linesize==0);
stride[0]=stride[1]=stride[2]=linesize;
mpcodecs_draw_slice (sh,src, stride, width, height, 0, y);
}
#endif // HAVE_XVMC
#endif