capabilities support -> automatic insertion of scale, expand, pp

git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@5566 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
arpi 2002-04-11 20:56:17 +00:00
parent a2ac318928
commit 39e3a780ce
14 changed files with 179 additions and 47 deletions

View File

@ -112,6 +112,7 @@ int vo_flags=0;
int vd_use_slices=1;
extern vd_functions_t* mpvdec; // FIXME!
extern int divx_quality;
int mpcodecs_config_vo(sh_video_t *sh, int w, int h, unsigned int preferred_outfmt){
int i,j;
@ -120,6 +121,7 @@ int mpcodecs_config_vo(sh_video_t *sh, int w, int h, unsigned int preferred_outf
int screen_size_y=0;//SCREEN_SIZE_Y;
// vo_functions_t* video_out=sh->video_out;
vf_instance_t* vf=sh->vfilter;
unsigned int fmtlist[CODECS_MAX_OUTFMT+1];
#if 1
if(!(sh->disp_w && sh->disp_h))
@ -137,28 +139,40 @@ int mpcodecs_config_vo(sh_video_t *sh, int w, int h, unsigned int preferred_outf
w,h,vo_format_name(preferred_outfmt));
if(!vf) return 1; // temp hack
if(get_video_quality_max(sh)<=0 && divx_quality){
// user wants postprocess but no pp filter yet:
sh->vfilter=vf=vf_open_filter(vf,"pp",NULL);
}
// check if libvo and codec has common outfmt (no conversion):
csp_again:
j=-1;
for(i=0;i<CODECS_MAX_OUTFMT;i++){
int flags;
out_fmt=sh->codec->outfmt[i];
if(out_fmt==(signed int)0xFFFFFFFF) continue;
vo_flags=vf->query_format(vf,out_fmt);
mp_msg(MSGT_CPLAYER,MSGL_V,"vo_debug: query(%s) returned 0x%X (i=%d) \n",vo_format_name(out_fmt),vo_flags,i);
if((vo_flags&2) || (vo_flags && j<0)){
flags=vf->query_format(vf,out_fmt);
mp_msg(MSGT_CPLAYER,MSGL_V,"vo_debug: query(%s) returned 0x%X (i=%d) \n",vo_format_name(out_fmt),flags,i);
if((flags&2) || (flags && j<0)){
// check (query) if codec really support this outfmt...
if(mpvdec->control(sh,VDCTRL_QUERY_FORMAT,&out_fmt)==CONTROL_FALSE)
continue;
j=i; if(vo_flags&2) break;
j=i; vo_flags=flags; if(flags&2) break;
}
}
if(j<0){
// TODO: no match - we should use conversion...
if(strcmp(vf->info->name,"scale")){
vf=vf_open_filter(vf,"scale",NULL);
goto csp_again;
}
mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_VOincompCodec);
return 0; // failed
}
out_fmt=sh->codec->outfmt[j];
sh->outfmtidx=j;
sh->vfilter=vf;
// autodetect flipping
if(flip==-1){
@ -167,6 +181,11 @@ int mpcodecs_config_vo(sh_video_t *sh, int w, int h, unsigned int preferred_outf
if(!(sh->codec->outflags[j]&CODECS_FLAG_NOFLIP))
flip=1;
}
if(vo_flags&VFCAP_FLIPPED) flip^=1;
if(flip && !(vo_flags&VFCAP_FLIP)){
// we need to flip, but no flipping filter avail.
sh->vfilter=vf=vf_open_filter(vf,"flip",NULL);
}
// time to do aspect ratio corrections...

View File

@ -178,7 +178,7 @@ static int query_format(struct vf_instance_s* vf, unsigned int fmt){
case IMGFMT_YV12:
case IMGFMT_IYUV:
case IMGFMT_I420:
return 1;
return VFCAP_CSP_SUPPORTED | VFCAP_ACCEPT_STRIDE;
}
return 0;
}

View File

@ -40,7 +40,7 @@ static int control(struct vf_instance_s* vf, int request, void* data){
}
static int query_format(struct vf_instance_s* vf, unsigned int fmt){
if(fmt==IMGFMT_BGR24) return 1;
if(fmt==IMGFMT_BGR24) return 3;
return 0;
}

View File

@ -53,7 +53,7 @@ static int control(struct vf_instance_s* vf, int request, void* data){
}
static int query_format(struct vf_instance_s* vf, unsigned int fmt){
if(fmt==IMGFMT_BGR24) return 1;
if(fmt==IMGFMT_BGR24) return 3 | VFCAP_FLIPPED;
return 0;
}

View File

@ -162,6 +162,8 @@ vf_instance_t* vf_open_plugin(vf_info_t** filter_list, vf_instance_t* next, char
vf->control=vf_next_control;
vf->query_format=vf_next_query_format;
vf->put_image=vf_next_put_image;
vf->default_caps=VFCAP_ACCEPT_STRIDE;
vf->default_reqs=0;
if(vf->info->open(vf,args)>0) return vf; // Success!
free(vf);
mp_msg(MSGT_VFILTER,MSGL_ERR,"Couldn't open video filter '%s'\n",name);
@ -174,10 +176,66 @@ vf_instance_t* vf_open_filter(vf_instance_t* next, char *name, char *args){
//============================================================================
unsigned int vf_match_csp(vf_instance_t** vfp,unsigned int* list,unsigned int preferred){
vf_instance_t* vf=*vfp;
unsigned int* p;
unsigned int best=0;
int ret;
if((p=list)) while(*p){
ret=vf->query_format(vf,*p);
mp_msg(MSGT_VFILTER,MSGL_V,"[%s] query(%s) -> %d\n",vf->info->name,vo_format_name(*p),ret&3);
if(ret&2){ best=*p; break;} // no conversion -> bingo!
if(ret&1 && !best) best=*p; // best with conversion
++p;
}
if(best) return best; // bingo, they have common csp!
// ok, then try with scale:
if(vf->info == &vf_info_scale) return 0; // avoid infinite recursion!
vf=vf_open_filter(vf,"scale",NULL);
if(!vf) return 0; // failed to init "scale"
// try the preferred csp first:
if(preferred && vf->query_format(vf,preferred)) best=preferred; else
// try the list again, now with "scaler" :
if((p=list)) while(*p){
ret=vf->query_format(vf,*p);
mp_msg(MSGT_VFILTER,MSGL_V,"[%s] query(%s) -> %d\n",vf->info->name,vo_format_name(*p),ret&3);
if(ret&2){ best=*p; break;} // no conversion -> bingo!
if(ret&1 && !best) best=*p; // best with conversion
++p;
}
if(best) *vfp=vf; // else uninit vf !FIXME!
return best;
}
int vf_next_config(struct vf_instance_s* vf,
int width, int height, int d_width, int d_height,
unsigned int flags, unsigned int outfmt){
return vf->next->config(vf->next,width,height,d_width,d_height,flags,outfmt);
unsigned int voflags, unsigned int outfmt){
int miss;
int flags=vf->next->query_format(vf->next,outfmt);
if(!flags){
// hmm. colorspace mismatch!!!
// let's insert the 'scale' filter, it does the job for us:
vf_instance_t* vf2;
if(vf->next->info==&vf_info_scale) return 0; // scale->scale
vf2=vf_open_filter(vf->next,"scale",NULL);
if(!vf2) return 0; // shouldn't happen!
vf->next=vf2;
flags=vf->next->query_format(vf->next,outfmt);
if(!flags){
mp_msg(MSGT_VFILTER,MSGL_ERR,"Cannot find common colorspace, even by inserting 'scale' :(\n");
return 0; // FAIL
}
}
printf("REQ: flags=0x%X req=0x%X \n",flags,vf->default_reqs);
miss=vf->default_reqs - (flags&vf->default_reqs);
if(miss&VFCAP_ACCEPT_STRIDE){
// vf requires stride support but vf->next doesn't support it!
// let's insert the 'expand' filter, it does the job for us:
vf_instance_t* vf2=vf_open_filter(vf->next,"expand",NULL);
if(!vf2) return 0; // shouldn't happen!
vf->next=vf2;
}
return vf->next->config(vf->next,width,height,d_width,d_height,voflags,outfmt);
}
int vf_next_control(struct vf_instance_s* vf, int request, void* data){
@ -185,7 +243,9 @@ int vf_next_control(struct vf_instance_s* vf, int request, void* data){
}
int vf_next_query_format(struct vf_instance_s* vf, unsigned int fmt){
return vf->next->query_format(vf->next,fmt);
int flags=vf->next->query_format(vf->next,fmt);
if(flags) flags|=vf->default_caps;
return flags;
}
void vf_next_put_image(struct vf_instance_s* vf,mp_image_t *mpi){

View File

@ -34,6 +34,9 @@ typedef struct vf_instance_s {
void (*draw_slice)(struct vf_instance_s* vf,
unsigned char* src, int* stride, int w,int h, int x, int y);
void (*uninit)(struct vf_instance_s* vf);
// caps:
unsigned int default_caps; // used by default query_format()
unsigned int default_reqs; // used by default config()
// data:
vf_image_context_t imgctx;
struct vf_instance_s* next;
@ -47,29 +50,7 @@ typedef struct vf_instance_s {
#define VFCTRL_SET_PP_LEVEL 5 /* set postprocessing level */
#define VFCTRL_SET_EQUALIZER 6 /* set color options (brightness,contrast etc) */
// VFCAP_* values: they are flags, returned by query_format():
// set, if the given colorspace is supported (with or without conversion)
#define VFCAP_CSP_SUPPORTED 0x1
// set, if the given colorspace is supported _without_ conversion
#define VFCAP_CSP_SUPPORTED_BY_HW 0x2
// set if the driver/filter can draw OSD
#define VFCAP_OSD 0x4
// set if the driver/filter can handle compressed SPU stream
#define VFCAP_SPU 0x8
// scaling up/down by hardware, or software:
#define VFCAP_HWSCALE_UP 0x10
#define VFCAP_HWSCALE_DOWN 0x20
#define VFCAP_SWSCALE 0x40
// driver/filter can do vertical flip (upside-down)
#define VFCAP_FLIP 0x80
// driver/hardware handles timing (blocking)
#define VFCAP_TIMER 0x100
// driver _always_ flip image upside-down (for ve_vfw)
#define VFCAP_FLIPPED 0x200
// driver accept stride: (put_image/draw_frame)
#define VFCAP_ACCEPT_STRIDE 0x400
#include "vfcap.h"
// functions:
mp_image_t* vf_get_image(vf_instance_t* vf, unsigned int outfmt, int mp_imgtype, int mp_imgflag, int w, int h);
@ -78,6 +59,8 @@ vf_instance_t* vf_open_plugin(vf_info_t** filter_list, vf_instance_t* next, char
vf_instance_t* vf_open_filter(vf_instance_t* next, char *name, char *args);
vf_instance_t* vf_open_encoder(vf_instance_t* next, char *name, char *args);
unsigned int vf_match_csp(vf_instance_t** vfp,unsigned int* list,unsigned int preferred);
// default wrappers:
int vf_next_config(struct vf_instance_s* vf,
int width, int height, int d_width, int d_height,

View File

@ -61,6 +61,7 @@ static void put_image(struct vf_instance_s* vf, mp_image_t *mpi){
static int open(vf_instance_t *vf, char* args){
vf->config=config;
vf->put_image=put_image;
vf->default_reqs=VFCAP_ACCEPT_STRIDE;
vf->priv=malloc(sizeof(struct vf_priv_s));
// TODO: parse args ->
vf->priv->crop_x=

View File

@ -81,7 +81,7 @@ static int query_format(struct vf_instance_s* vf, unsigned int fmt){
case IMGFMT_YV12:
case IMGFMT_I420:
case IMGFMT_IYUV:
return 3; //vf_next_query_format(vf,fmt);
return (vf_next_query_format(vf,fmt) & (~VFCAP_CSP_SUPPORTED_BY_HW));
}
return 0;
}

View File

@ -69,6 +69,7 @@ static void put_image(struct vf_instance_s* vf, mp_image_t *mpi){
static int open(vf_instance_t *vf, char* args){
vf->get_image=get_image;
vf->put_image=put_image;
vf->default_reqs=VFCAP_ACCEPT_STRIDE;
vf->priv=malloc(sizeof(struct vf_priv_s));
return 1;
}

View File

@ -35,6 +35,7 @@ static int open(vf_instance_t *vf, char* args){
if(!strcasecmp(args,"bgr24")) vf->priv->fmt=IMGFMT_BGR24; else
if(!strcasecmp(args,"bgr32")) vf->priv->fmt=IMGFMT_BGR32; else
if(!strcasecmp(args,"bgr16")) vf->priv->fmt=IMGFMT_BGR16; else
if(!strcasecmp(args,"bgr15")) vf->priv->fmt=IMGFMT_BGR15; else
{ printf("Unknown format name: '%s'\n",args);return 0;}
} else
vf->priv->fmt=IMGFMT_YUY2;
@ -46,7 +47,7 @@ vf_info_t vf_info_format = {
"force output format",
"format",
"A'rpi",
"",
"FIXME! get_image()/put_image()",
open
};

View File

@ -14,16 +14,23 @@
struct vf_priv_s {
unsigned int pp;
mp_image_t *dmpi;
unsigned int outfmt;
};
//===========================================================================//
static int config(struct vf_instance_s* vf,
int width, int height, int d_width, int d_height,
unsigned int voflags, unsigned int outfmt){
return vf_next_config(vf,width,height,d_width,d_height,voflags,vf->priv->outfmt);
}
static int query_format(struct vf_instance_s* vf, unsigned int fmt){
switch(fmt){
case IMGFMT_YV12:
case IMGFMT_I420:
case IMGFMT_IYUV:
return vf_next_query_format(vf,fmt);
return vf_next_query_format(vf,vf->priv->outfmt);
}
return 0;
}
@ -43,6 +50,8 @@ static void get_image(struct vf_instance_s* vf, mp_image_t *mpi){
if(vf->priv->pp&0xFFFF) return; // non-local filters enabled
if((mpi->type==MP_IMGTYPE_IPB || vf->priv->pp) &&
mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
if(!(mpi->flags&MP_IMGFLAG_ACCEPT_STRIDE) && mpi->imgfmt!=vf->priv->outfmt)
return; // colorspace differ
// ok, we can do pp in-place (or pp disabled):
vf->priv->dmpi=vf_get_image(vf->next,mpi->imgfmt,
mpi->type, mpi->flags, mpi->w, mpi->h);
@ -61,7 +70,7 @@ static void get_image(struct vf_instance_s* vf, mp_image_t *mpi){
static void put_image(struct vf_instance_s* vf, mp_image_t *mpi){
if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
// no DR, so get a new image! hope we'll get DR buffer:
vf->priv->dmpi=vf_get_image(vf->next,mpi->imgfmt,
vf->priv->dmpi=vf_get_image(vf->next,vf->priv->outfmt,
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_ALIGNED_STRIDE,
mpi->w,mpi->h);
}
@ -82,13 +91,27 @@ static void put_image(struct vf_instance_s* vf, mp_image_t *mpi){
extern int divx_quality;
static unsigned int fmt_list[]={
IMGFMT_YV12,
IMGFMT_I420,
IMGFMT_IYUV,
NULL
};
static int open(vf_instance_t *vf, char* args){
char *endptr;
vf->query_format=query_format;
vf->control=control;
vf->config=config;
vf->get_image=get_image;
vf->put_image=put_image;
vf->default_caps=VFCAP_ACCEPT_STRIDE|VFCAP_POSTPROC;
vf->priv=malloc(sizeof(struct vf_priv_s));
// check csp:
vf->priv->outfmt=vf_match_csp(&vf->next,fmt_list,IMGFMT_YV12);
if(!vf->priv->outfmt) return 0; // no csp match :(
if(args){
vf->priv->pp=strtol(args, &endptr, 0);
if(!(*endptr)) return 1;

View File

@ -32,12 +32,9 @@ static unsigned int outfmt_list[]={
NULL
};
static int config(struct vf_instance_s* vf,
int width, int height, int d_width, int d_height,
unsigned int flags, unsigned int outfmt){
unsigned int* p=outfmt_list;
static unsigned int find_best_out(vf_instance_t *vf){
unsigned int best=0;
unsigned int* p=outfmt_list;
// find the best outfmt:
while(*p){
int ret=vf_next_query_format(vf,*p);
@ -46,10 +43,43 @@ static int config(struct vf_instance_s* vf,
if(ret&1 && !best) best=*p; // best with conversion
++p;
}
return best;
}
static int config(struct vf_instance_s* vf,
int width, int height, int d_width, int d_height,
unsigned int flags, unsigned int outfmt){
unsigned int best=find_best_out(vf);
int vo_flags;
if(!best){
printf("SwScale: no supported outfmt found :(\n");
return 0;
}
vo_flags=vf->next->query_format(vf->next,best);
// scaling to dwidth*d_height, if all these TRUE:
// - option -zoom
// - no other sw/hw up/down scaling avail.
// - we're after postproc
// - user didn't set w:h
if(!(vo_flags&VFCAP_POSTPROC) && (flags&4) &&
vf->priv->w<0 && vf->priv->h<0){ // -zoom
int x=(vo_flags&VFCAP_SWSCALE) ? 0 : 1;
if(d_width<width || d_height<height){
// downscale!
if(vo_flags&VFCAP_HWSCALE_DOWN) x=0;
} else {
// upscale:
if(vo_flags&VFCAP_HWSCALE_UP) x=0;
}
if(x){
// user wants sw scaling! (-zoom)
vf->priv->w=d_width;
vf->priv->h=d_height;
}
}
// calculate the missing parameters:
if(vf->priv->w<=0) vf->priv->w=width;
@ -110,10 +140,19 @@ static int query_format(struct vf_instance_s* vf, unsigned int fmt){
case IMGFMT_BGR15:
case IMGFMT_RGB32:
case IMGFMT_RGB24:
case IMGFMT_Y800:
return 3; //vf_next_query_format(vf,fmt);
case IMGFMT_Y800: {
unsigned int best=find_best_out(vf);
int flags;
if(!best) return 0; // no matching out-fmt
flags=vf_next_query_format(vf,best);
if(!(flags&3)) return 0; // huh?
if(fmt!=best) flags&=~VFCAP_CSP_SUPPORTED_BY_HW;
// do not allow scaling, if we are before the PP fliter!
if(!(flags&VFCAP_POSTPROC)) flags|=VFCAP_SWSCALE;
return flags;
}
}
return 0;
return 0; // nomatching in-fmt
}
static int open(vf_instance_t *vf, char* args){

View File

@ -47,7 +47,12 @@ static int control(struct vf_instance_s* vf,
}
static int query_format(struct vf_instance_s* vf, unsigned int fmt){
return video_out->control(VOCTRL_QUERY_FORMAT,&fmt);
int flags=video_out->control(VOCTRL_QUERY_FORMAT,&fmt);
// draw_slice() accepts stride, draw_frame() doesn't:
if(flags)
if(fmt==IMGFMT_YV12 || fmt==IMGFMT_I420 || fmt==IMGFMT_IYUV)
flags|=VFCAP_ACCEPT_STRIDE;
return flags;
}
static void get_image(struct vf_instance_s* vf,

View File

@ -51,7 +51,7 @@ static int query_format(struct vf_instance_s* vf, unsigned int fmt){
case IMGFMT_YV12:
case IMGFMT_I420:
case IMGFMT_IYUV:
return 3; //vf_next_query_format(vf,fmt);
return vf_next_query_format(vf,IMGFMT_YUY2) & (~VFCAP_CSP_SUPPORTED_BY_HW);
}
return 0;
}