changeset 5565:0b301fec999a

capabilities support -> automatic insertion of scale, expand, pp
author arpi
date Thu, 11 Apr 2002 20:56:17 +0000
parents efe856039f8f
children e01c664def74
files libmpcodecs/vd.c libmpcodecs/ve_lavc.c libmpcodecs/ve_rawrgb.c libmpcodecs/ve_vfw.c libmpcodecs/vf.c libmpcodecs/vf.h libmpcodecs/vf_crop.c libmpcodecs/vf_fame.c libmpcodecs/vf_flip.c libmpcodecs/vf_format.c libmpcodecs/vf_pp.c libmpcodecs/vf_scale.c libmpcodecs/vf_vo.c libmpcodecs/vf_yuy2.c
diffstat 14 files changed, 179 insertions(+), 47 deletions(-) [+]
line wrap: on
line diff
--- a/libmpcodecs/vd.c	Thu Apr 11 20:55:10 2002 +0000
+++ b/libmpcodecs/vd.c	Thu Apr 11 20:56:17 2002 +0000
@@ -112,6 +112,7 @@
 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 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 @@
 	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 @@
 	    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...
 
--- a/libmpcodecs/ve_lavc.c	Thu Apr 11 20:55:10 2002 +0000
+++ b/libmpcodecs/ve_lavc.c	Thu Apr 11 20:56:17 2002 +0000
@@ -178,7 +178,7 @@
     case IMGFMT_YV12:
     case IMGFMT_IYUV:
     case IMGFMT_I420:
-	return 1;
+	return VFCAP_CSP_SUPPORTED | VFCAP_ACCEPT_STRIDE;
     }
     return 0;
 }
--- a/libmpcodecs/ve_rawrgb.c	Thu Apr 11 20:55:10 2002 +0000
+++ b/libmpcodecs/ve_rawrgb.c	Thu Apr 11 20:56:17 2002 +0000
@@ -40,7 +40,7 @@
 }
 
 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;
 }
 
--- a/libmpcodecs/ve_vfw.c	Thu Apr 11 20:55:10 2002 +0000
+++ b/libmpcodecs/ve_vfw.c	Thu Apr 11 20:56:17 2002 +0000
@@ -53,7 +53,7 @@
 }
 
 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;
 }
 
--- a/libmpcodecs/vf.c	Thu Apr 11 20:55:10 2002 +0000
+++ b/libmpcodecs/vf.c	Thu Apr 11 20:56:17 2002 +0000
@@ -162,6 +162,8 @@
     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 @@
 
 //============================================================================
 
+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_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){
--- a/libmpcodecs/vf.h	Thu Apr 11 20:55:10 2002 +0000
+++ b/libmpcodecs/vf.h	Thu Apr 11 20:56:17 2002 +0000
@@ -34,6 +34,9 @@
     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 @@
 #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_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,
--- a/libmpcodecs/vf_crop.c	Thu Apr 11 20:55:10 2002 +0000
+++ b/libmpcodecs/vf_crop.c	Thu Apr 11 20:56:17 2002 +0000
@@ -61,6 +61,7 @@
 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=
--- a/libmpcodecs/vf_fame.c	Thu Apr 11 20:55:10 2002 +0000
+++ b/libmpcodecs/vf_fame.c	Thu Apr 11 20:56:17 2002 +0000
@@ -81,7 +81,7 @@
     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;
 }
--- a/libmpcodecs/vf_flip.c	Thu Apr 11 20:55:10 2002 +0000
+++ b/libmpcodecs/vf_flip.c	Thu Apr 11 20:56:17 2002 +0000
@@ -69,6 +69,7 @@
 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;
 }
--- a/libmpcodecs/vf_format.c	Thu Apr 11 20:55:10 2002 +0000
+++ b/libmpcodecs/vf_format.c	Thu Apr 11 20:56:17 2002 +0000
@@ -35,6 +35,7 @@
 	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 @@
     "force output format",
     "format",
     "A'rpi",
-    "",
+    "FIXME! get_image()/put_image()",
     open
 };
 
--- a/libmpcodecs/vf_pp.c	Thu Apr 11 20:55:10 2002 +0000
+++ b/libmpcodecs/vf_pp.c	Thu Apr 11 20:56:17 2002 +0000
@@ -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 @@
     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 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 @@
 
 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;
--- a/libmpcodecs/vf_scale.c	Thu Apr 11 20:55:10 2002 +0000
+++ b/libmpcodecs/vf_scale.c	Thu Apr 11 20:56:17 2002 +0000
@@ -32,12 +32,9 @@
     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){
+static unsigned int find_best_out(vf_instance_t *vf){
+    unsigned int best=0;
     unsigned int* p=outfmt_list;
-    unsigned int best=0;
-    
     // find the best outfmt:
     while(*p){
 	int ret=vf_next_query_format(vf,*p);
@@ -46,10 +43,43 @@
 	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 @@
     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){
--- a/libmpcodecs/vf_vo.c	Thu Apr 11 20:55:10 2002 +0000
+++ b/libmpcodecs/vf_vo.c	Thu Apr 11 20:56:17 2002 +0000
@@ -47,7 +47,12 @@
 }
 
 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,
--- a/libmpcodecs/vf_yuy2.c	Thu Apr 11 20:55:10 2002 +0000
+++ b/libmpcodecs/vf_yuy2.c	Thu Apr 11 20:56:17 2002 +0000
@@ -51,7 +51,7 @@
     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;
 }