aboutsummaryrefslogtreecommitdiffstats
path: root/postproc/swscale.c
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2002-06-23 10:36:18 +0000
committerMichael Niedermayer <michaelni@gmx.at>2002-06-23 10:36:18 +0000
commitc7a810cc25bd0a6f9c784e20895d833a8dfa3119 (patch)
treeef78cb0ff5cf32b5be676346b10fbe8323a1f077 /postproc/swscale.c
parent390dffc5ad72886292603f2715d73f6e591a6e49 (diff)
downloadffmpeg-c7a810cc25bd0a6f9c784e20895d833a8dfa3119.tar.gz
selftest support
bugfixes Originally committed as revision 6518 to svn://svn.mplayerhq.hu/mplayer/trunk/postproc
Diffstat (limited to 'postproc/swscale.c')
-rw-r--r--postproc/swscale.c208
1 files changed, 179 insertions, 29 deletions
diff --git a/postproc/swscale.c b/postproc/swscale.c
index 96ea6ea7f6..5b4953c02c 100644
--- a/postproc/swscale.c
+++ b/postproc/swscale.c
@@ -266,6 +266,124 @@ void in_asm_used_var_warning_killer()
}
#endif
+static int testFormat[]={
+IMGFMT_YV12,
+//IMGFMT_IYUV,
+IMGFMT_I420,
+IMGFMT_BGR15,
+IMGFMT_BGR16,
+IMGFMT_BGR24,
+IMGFMT_BGR32,
+//IMGFMT_Y8,
+IMGFMT_Y800,
+//IMGFMT_YUY2,
+0
+};
+
+static uint64_t getSSD(uint8_t *src1, uint8_t *src2, int stride1, int stride2, int w, int h){
+ int x,y;
+ uint64_t ssd=0;
+
+ for(y=0; y<h; y++){
+ for(x=0; x<w; x++){
+ int d= src1[x + y*stride1] - src2[x + y*stride2];
+ ssd+= d*d;
+ }
+ }
+ return ssd;
+}
+
+// test by ref -> src -> dst -> out & compare out against ref
+// ref & out are YV12
+static void doTest(uint8_t *ref[3], int refStride[3], int w, int h, int srcFormat, int dstFormat,
+ int srcW, int srcH, int dstW, int dstH, int flags){
+ uint8_t *src[3];
+ uint8_t *dst[3];
+ uint8_t *out[3];
+ int srcStride[3], dstStride[3];
+ int i;
+ uint64_t ssdY, ssdU, ssdV;
+ SwsContext *srcContext, *dstContext, *outContext;
+
+ for(i=0; i<3; i++){
+ srcStride[i]= srcW*4;
+ dstStride[i]= dstW*4;
+ src[i]= malloc(srcStride[i]*srcH);
+ dst[i]= malloc(dstStride[i]*dstH);
+ out[i]= malloc(refStride[i]*h);
+ }
+
+ srcContext= getSwsContext(w, h, IMGFMT_YV12, srcW, srcH, srcFormat, flags, NULL, NULL);
+ dstContext= getSwsContext(srcW, srcH, srcFormat, dstW, dstH, dstFormat, flags, NULL, NULL);
+ outContext= getSwsContext(dstW, dstH, dstFormat, w, h, IMGFMT_YV12, flags, NULL, NULL);
+ if(srcContext==NULL ||dstContext==NULL ||outContext==NULL){
+ printf("Failed allocating swsContext\n");
+ goto end;
+ }
+// printf("test %X %X %X -> %X %X %X\n", (int)ref[0], (int)ref[1], (int)ref[2],
+// (int)src[0], (int)src[1], (int)src[2]);
+
+ srcContext->swScale(srcContext, ref, refStride, 0, h , src, srcStride);
+ dstContext->swScale(dstContext, src, srcStride, 0, srcH, dst, dstStride);
+ outContext->swScale(outContext, dst, dstStride, 0, dstH, out, refStride);
+
+ ssdY= getSSD(ref[0], out[0], refStride[0], refStride[0], w, h);
+ ssdU= getSSD(ref[1], out[1], refStride[1], refStride[1], (w+1)>>1, (h+1)>>1);
+ ssdV= getSSD(ref[2], out[2], refStride[2], refStride[2], (w+1)>>1, (h+1)>>1);
+
+ if(isGray(srcFormat) || isGray(dstFormat)) ssdU=ssdV=0; //FIXME check that output is really gray
+
+ ssdY/= w*h;
+ ssdU/= w*h/4;
+ ssdV/= w*h/4;
+
+ if(ssdY>10 || ssdU>10 || ssdV>10){
+ printf(" %s %dx%d -> %s %4dx%4d flags=%2d SSD=%5lld,%5lld,%5lld\n",
+ vo_format_name(srcFormat), srcW, srcH,
+ vo_format_name(dstFormat), dstW, dstH,
+ flags,
+ ssdY, ssdU, ssdV);
+ }
+
+ end:
+
+ freeSwsContext(srcContext);
+ freeSwsContext(dstContext);
+ freeSwsContext(outContext);
+
+ for(i=0; i<3; i++){
+ free(src[i]);
+ free(dst[i]);
+ free(out[i]);
+ }
+}
+
+static void selfTest(uint8_t *src[3], int stride[3], int w, int h){
+ int srcFormat, dstFormat, srcFormatIndex, dstFormatIndex;
+ int srcW, srcH, dstW, dstH;
+ int flags;
+
+ for(srcFormatIndex=0; ;srcFormatIndex++){
+ srcFormat= testFormat[srcFormatIndex];
+ if(!srcFormat) break;
+ for(dstFormatIndex=0; ;dstFormatIndex++){
+ dstFormat= testFormat[dstFormatIndex];
+ if(!dstFormat) break;
+ if(!isSupportedOut(dstFormat)) continue;
+
+ srcW= w+w/3;
+ srcH= h+h/3;
+ for(dstW=w; dstW<w*2; dstW+= dstW/3){
+ for(dstH=h; dstH<h*2; dstH+= dstH/3){
+ for(flags=1; flags<33; flags*=2)
+ doTest(src, stride, w, h, srcFormat, dstFormat,
+ srcW, srcH, dstW, dstH, flags);
+ }
+ }
+ }
+ }
+}
+
static inline void yuv2yuvXinC(int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize,
int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize,
uint8_t *dest, uint8_t *uDest, uint8_t *vDest, int dstW)
@@ -1540,21 +1658,21 @@ static void bgr24toyv12Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], i
/**
* bring pointers in YUV order instead of YVU
*/
-static inline void orderYUV(SwsContext *c, uint8_t * sortedP[], int sortedStride[], uint8_t * p[], int stride[]){
- if(c->srcFormat == IMGFMT_YV12){
+static inline void orderYUV(int format, uint8_t * sortedP[], int sortedStride[], uint8_t * p[], int stride[]){
+ if(format == IMGFMT_YV12){
sortedP[0]= p[0];
sortedP[1]= p[1];
sortedP[2]= p[2];
- sortedStride[0]= sortedStride[0];
- sortedStride[1]= sortedStride[1];
- sortedStride[2]= sortedStride[2];
+ sortedStride[0]= stride[0];
+ sortedStride[1]= stride[1];
+ sortedStride[2]= stride[2];
}
- else if(isPacked(c->srcFormat) || isGray(c->srcFormat))
+ else if(isPacked(format) || isGray(format))
{
sortedP[0]= p[0];
sortedP[1]=
sortedP[2]= NULL;
- sortedStride[0]= sortedStride[0];
+ sortedStride[0]= stride[0];
sortedStride[1]=
sortedStride[2]= 0;
}
@@ -1563,9 +1681,9 @@ static inline void orderYUV(SwsContext *c, uint8_t * sortedP[], int sortedStride
sortedP[0]= p[0];
sortedP[1]= p[2];
sortedP[2]= p[1];
- sortedStride[0]= sortedStride[0];
- sortedStride[1]= sortedStride[2];
- sortedStride[2]= sortedStride[1];
+ sortedStride[0]= stride[0];
+ sortedStride[1]= stride[2];
+ sortedStride[2]= stride[1];
}
}
@@ -1578,8 +1696,8 @@ static void simpleCopy(SwsContext *c, uint8_t* srcParam[], int srcStrideParam[],
uint8_t *src[3];
uint8_t *dst[3];
- orderYUV(c, src, srcStride, srcParam, srcStrideParam);
- orderYUV(c, dst, dstStride, dstParam, dstStrideParam);
+ orderYUV(c->srcFormat, src, srcStride, srcParam, srcStrideParam);
+ orderYUV(c->dstFormat, dst, dstStride, dstParam, dstStrideParam);
if(isPacked(c->srcFormat))
{
@@ -1650,6 +1768,28 @@ static int remove_dup_fourcc(int fourcc)
}
}
+static void getSubSampleFactors(int *h, int *v, int format){
+ switch(format){
+ case IMGFMT_YUY2:
+ *h=1;
+ *v=0;
+ break;
+ case IMGFMT_YV12:
+ case IMGFMT_I420:
+ *h=1;
+ *v=1;
+ break;
+ case IMGFMT_YVU9:
+ *h=2;
+ *v=2;
+ break;
+ default:
+ *h=0;
+ *v=0;
+ break;
+ }
+}
+
SwsContext *getSwsContext(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat, int flags,
SwsFilter *srcFilter, SwsFilter *dstFilter){
@@ -1925,30 +2065,40 @@ SwsContext *getSwsContext(int srcW, int srcH, int srcFormat, int dstW, int dstH,
else
c->canMMX2BeUsed=0;
+ getSubSampleFactors(&c->chrSrcHSubSample, &c->chrSrcVSubSample, srcFormat);
+ getSubSampleFactors(&c->chrDstHSubSample, &c->chrDstVSubSample, dstFormat);
- /* dont use full vertical UV input/internaly if the source doesnt even have it */
- if(isHalfChrV(srcFormat)) c->flags= flags= flags&(~SWS_FULL_CHR_V);
- /* dont use full horizontal UV input if the source doesnt even have it */
- if(isHalfChrH(srcFormat)) c->flags= flags= flags&(~SWS_FULL_CHR_H_INP);
- /* dont use full horizontal UV internally if the destination doesnt even have it */
- if(isHalfChrH(dstFormat)) c->flags= flags= flags&(~SWS_FULL_CHR_H_INT);
+ // reuse chroma for 2 pixles rgb/bgr unless user wants full chroma interpolation
+ if((isBGR(dstFormat) || isRGB(dstFormat)) && !(flags&SWS_FULL_CHR_H_INT)) c->chrDstHSubSample=1;
- if(flags&SWS_FULL_CHR_H_INP) c->chrSrcW= srcW;
- else c->chrSrcW= (srcW+1)>>1;
+ // drop eery 2. pixel for chroma calculation unless user wants full chroma
+ if((isBGR(srcFormat) || isRGB(srcFormat) || srcFormat==IMGFMT_YUY2) && !(flags&SWS_FULL_CHR_V))
+ c->chrSrcVSubSample=1;
- if(flags&SWS_FULL_CHR_H_INT) c->chrDstW= dstW;
- else c->chrDstW= (dstW+1)>>1;
-
- if(flags&SWS_FULL_CHR_V) c->chrSrcH= srcH;
- else c->chrSrcH= (srcH+1)>>1;
-
- if(isHalfChrV(dstFormat)) c->chrDstH= (dstH+1)>>1;
- else c->chrDstH= dstH;
+ // drop eery 2. pixel for chroma calculation unless user wants full chroma
+ if((isBGR(srcFormat) || isRGB(srcFormat)) && !(flags&SWS_FULL_CHR_H_INP))
+ c->chrSrcHSubSample=1;
+ c->chrIntHSubSample= c->chrDstHSubSample;
+ c->chrIntVSubSample= c->chrSrcVSubSample;
+
+ // note the -((-x)>>y) is so that we allways round toward +inf
+ c->chrSrcW= -((-srcW) >> c->chrSrcHSubSample);
+ c->chrSrcH= -((-srcH) >> c->chrSrcVSubSample);
+ c->chrDstW= -((-dstW) >> c->chrDstHSubSample);
+ c->chrDstH= -((-dstH) >> c->chrDstVSubSample);
+/* printf("%d %d %d %d / %d %d %d %d //\n",
+ c->chrSrcW,
+c->chrSrcH,
+c->chrDstW,
+c->chrDstH,
+srcW,
+srcH,
+dstW,
+dstH);*/
c->chrXInc= ((c->chrSrcW<<16) + (c->chrDstW>>1))/c->chrDstW;
c->chrYInc= ((c->chrSrcH<<16) + (c->chrDstH>>1))/c->chrDstH;
-
// match pixel 0 of the src to pixel 0 of dst and match pixel n-2 of src to pixel n-2 of dst
// but only for the FAST_BILINEAR mode otherwise do correct scaling
// n-2 is the last chrominance sample available