mirror of
https://github.com/mpv-player/mpv
synced 2024-08-28 05:46:13 +02:00
xvmc support
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@10363 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
25a5f06b64
commit
e405703e68
@ -47,6 +47,15 @@ LIBVD_EXTERN(ffmpeg)
|
|||||||
#define PIX_FMT_RGBA32 PIX_FMT_BGRA32
|
#define PIX_FMT_RGBA32 PIX_FMT_BGRA32
|
||||||
#endif
|
#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;
|
int avcodec_inited=0;
|
||||||
|
|
||||||
#if defined(FF_POSTPROCESS) && defined(MBR)
|
#if defined(FF_POSTPROCESS) && defined(MBR)
|
||||||
@ -79,6 +88,14 @@ typedef struct {
|
|||||||
static int get_buffer(AVCodecContext *avctx, AVFrame *pic);
|
static int get_buffer(AVCodecContext *avctx, AVFrame *pic);
|
||||||
static void release_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_workaround_bugs= FF_BUG_AUTODETECT;
|
||||||
static int lavc_param_error_resilience=2;
|
static int lavc_param_error_resilience=2;
|
||||||
static int lavc_param_error_concealment=3;
|
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;
|
AVCodecContext *avctx = ctx->avctx;
|
||||||
switch(cmd){
|
switch(cmd){
|
||||||
case VDCTRL_QUERY_FORMAT:
|
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:
|
// possible conversions:
|
||||||
switch( (*((int*)arg)) ){
|
switch( format ){
|
||||||
case IMGFMT_YV12:
|
case IMGFMT_YV12:
|
||||||
case IMGFMT_IYUV:
|
case IMGFMT_IYUV:
|
||||||
case IMGFMT_I420:
|
case IMGFMT_I420:
|
||||||
@ -119,6 +142,7 @@ static int control(sh_video_t *sh,int cmd,void* arg,...){
|
|||||||
}
|
}
|
||||||
return CONTROL_FALSE;
|
return CONTROL_FALSE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return CONTROL_UNKNOWN;
|
return CONTROL_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,6 +188,17 @@ static int init(sh_video_t *sh){
|
|||||||
ctx->avctx = avcodec_alloc_context();
|
ctx->avctx = avcodec_alloc_context();
|
||||||
avctx = ctx->avctx;
|
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){
|
if(ctx->do_dr1){
|
||||||
avctx->flags|= CODEC_FLAG_EMU_EDGE;
|
avctx->flags|= CODEC_FLAG_EMU_EDGE;
|
||||||
avctx->get_buffer= get_buffer;
|
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_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_RGB24 : ctx->best_csp=IMGFMT_BGR24;break; //huffyuv
|
||||||
case PIX_FMT_RGBA32: ctx->best_csp=IMGFMT_BGR32;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:
|
default:
|
||||||
ctx->best_csp=0;
|
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
|
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->draw_horiz_band=NULL;
|
||||||
avctx->opaque=sh;
|
avctx->opaque=sh;
|
||||||
if(ctx->vo_inited && !(flags&3) && !dr1){
|
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;
|
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
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user