📄 swscale.c
字号:
{ double A= param ? -param*0.01 : -0.60; // Equation is from VirtualDub if(d<1.0) coeff = (1.0 - (A+3.0)*d*d + (A+2.0)*d*d*d); else if(d<2.0) coeff = (-4.0*A + 8.0*A*d - 5.0*A*d*d + A*d*d*d); else coeff=0.0; }/* else if(flags & SWS_X) { double p= param ? param*0.01 : 0.3; coeff = d ? sin(d*PI)/(d*PI) : 1.0; coeff*= pow(2.0, - p*d*d); }*/ else if(flags & SWS_X) { double A= param ? param*0.1 : 1.0; if(d<1.0) coeff = cos(d*PI); else coeff=-1.0; if(coeff<0.0) coeff= -pow(-coeff, A); else coeff= pow( coeff, A); coeff= coeff*0.5 + 0.5; } else if(flags & SWS_AREA) { double srcPixelSize= 1.0/xInc1; if(d + srcPixelSize/2 < 0.5) coeff= 1.0; else if(d - srcPixelSize/2 < 0.5) coeff= (0.5-d)/srcPixelSize + 0.5; else coeff=0.0; } else if(flags & SWS_GAUSS) { double p= param ? param*0.1 : 3.0; coeff = pow(2.0, - p*d*d); } else if(flags & SWS_SINC) { coeff = d ? sin(d*PI)/(d*PI) : 1.0; } else if(flags & SWS_LANCZOS) { double p= param ? param : 3.0; coeff = d ? sin(d*PI)*sin(d*PI/p)/(d*d*PI*PI/p) : 1.0; if(d>p) coeff=0; } else if(flags & SWS_BILINEAR) { coeff= 1.0 - d; if(coeff<0) coeff=0; } else if(flags & SWS_SPLINE) { double p=-2.196152422706632; coeff = getSplineCoeff(1.0, 0.0, p, -p-1.0, d); } else { coeff= 0.0; //GCC warning killer ASSERT(0) } filter[i*filterSize + j]= coeff; xx++; } xDstInSrc+= xInc1; } } /* apply src & dst Filter to filter -> filter2 free(filter); */ ASSERT(filterSize>0) filter2Size= filterSize; if(srcFilter) filter2Size+= srcFilter->length - 1; if(dstFilter) filter2Size+= dstFilter->length - 1; ASSERT(filter2Size>0) filter2= (double*)memalign(8, filter2Size*dstW*sizeof(double)); for(i=0; i<dstW; i++) { int j; SwsVector scaleFilter; SwsVector *outVec; scaleFilter.coeff= filter + i*filterSize; scaleFilter.length= filterSize; if(srcFilter) outVec= sws_getConvVec(srcFilter, &scaleFilter); else outVec= &scaleFilter; ASSERT(outVec->length == filter2Size) //FIXME dstFilter for(j=0; j<outVec->length; j++) { filter2[i*filter2Size + j]= outVec->coeff[j]; } (*filterPos)[i]+= (filterSize-1)/2 - (filter2Size-1)/2; if(outVec != &scaleFilter) sws_freeVec(outVec); } free(filter); filter=NULL; /* try to reduce the filter-size (step1 find size and shift left) */ // Assume its near normalized (*0.5 or *2.0 is ok but * 0.001 is not) minFilterSize= 0; for(i=dstW-1; i>=0; i--) { int min= filter2Size; int j; double cutOff=0.0; /* get rid off near zero elements on the left by shifting left */ for(j=0; j<filter2Size; j++) { int k; cutOff += ABS(filter2[i*filter2Size]); if(cutOff > SWS_MAX_REDUCE_CUTOFF) break; /* preserve Monotonicity because the core can't handle the filter otherwise */ if(i<dstW-1 && (*filterPos)[i] >= (*filterPos)[i+1]) break; // Move filter coeffs left for(k=1; k<filter2Size; k++) filter2[i*filter2Size + k - 1]= filter2[i*filter2Size + k]; filter2[i*filter2Size + k - 1]= 0.0; (*filterPos)[i]++; } cutOff=0.0; /* count near zeros on the right */ for(j=filter2Size-1; j>0; j--) { cutOff += ABS(filter2[i*filter2Size + j]); if(cutOff > SWS_MAX_REDUCE_CUTOFF) break; min--; } if(min>minFilterSize) minFilterSize= min; } if (flags & SWS_CPU_CAPS_ALTIVEC) { // we can handle the special case 4, // so we don't want to go to the full 8 if (minFilterSize < 5) filterAlign = 4; // we really don't want to waste our time // doing useless computation, so fall-back on // the scalar C code for very small filter. // vectorizing is worth it only if you have // decent-sized vector. if (minFilterSize < 3) filterAlign = 1; } ASSERT(minFilterSize > 0) filterSize= (minFilterSize +(filterAlign-1)) & (~(filterAlign-1)); ASSERT(filterSize > 0) filter= (double*)memalign(8, filterSize*dstW*sizeof(double)); *outFilterSize= filterSize; if(flags&SWS_PRINT_INFO) MSG_INFO("SwScaler: reducing / aligning filtersize %d -> %d\n", filter2Size, filterSize); /* try to reduce the filter-size (step2 reduce it) */ for(i=0; i<dstW; i++) { int j; for(j=0; j<filterSize; j++) { if(j>=filter2Size) filter[i*filterSize + j]= 0.0; else filter[i*filterSize + j]= filter2[i*filter2Size + j]; } } free(filter2); filter2=NULL; //FIXME try to align filterpos if possible //fix borders for(i=0; i<dstW; i++) { int j; if((*filterPos)[i] < 0) { // Move filter coeffs left to compensate for filterPos for(j=1; j<filterSize; j++) { int left= MAX(j + (*filterPos)[i], 0); filter[i*filterSize + left] += filter[i*filterSize + j]; filter[i*filterSize + j]=0; } (*filterPos)[i]= 0; } if((*filterPos)[i] + filterSize > srcW) { int shift= (*filterPos)[i] + filterSize - srcW; // Move filter coeffs right to compensate for filterPos for(j=filterSize-2; j>=0; j--) { int right= MIN(j + shift, filterSize-1); filter[i*filterSize +right] += filter[i*filterSize +j]; filter[i*filterSize +j]=0; } (*filterPos)[i]= srcW - filterSize; } } // Note the +1 is for the MMXscaler which reads over the end *outFilter= (int16_t*)memalign(8, *outFilterSize*(dstW+1)*sizeof(int16_t)); memset(*outFilter, 0, *outFilterSize*(dstW+1)*sizeof(int16_t)); /* Normalize & Store in outFilter */ for(i=0; i<dstW; i++) { int j; double error=0; double sum=0; double scale= one; for(j=0; j<filterSize; j++) { sum+= filter[i*filterSize + j]; } scale/= sum; for(j=0; j<*outFilterSize; j++) { double v= filter[i*filterSize + j]*scale + error; int intV= floor(v + 0.5); (*outFilter)[i*(*outFilterSize) + j]= intV; error = v - intV; } } (*filterPos)[dstW]= (*filterPos)[dstW-1]; // the MMX scaler will read over the end for(i=0; i<*outFilterSize; i++) { int j= dstW*(*outFilterSize); (*outFilter)[j + i]= (*outFilter)[j + i - (*outFilterSize)]; } free(filter);}#ifdef ARCH_X86static void initMMX2HScaler(int dstW, int xInc, uint8_t *funnyCode, int16_t *filter, int32_t *filterPos, int numSplits){ uint8_t *fragmentA; int imm8OfPShufW1A; int imm8OfPShufW2A; int fragmentLengthA; uint8_t *fragmentB; int imm8OfPShufW1B; int imm8OfPShufW2B; int fragmentLengthB; int fragmentPos; int xpos, i; // create an optimized horizontal scaling routine //code fragment asm volatile( "jmp 9f \n\t" // Begin "0: \n\t" "movq (%%edx, %%eax), %%mm3 \n\t" "movd (%%ecx, %%esi), %%mm0 \n\t" "movd 1(%%ecx, %%esi), %%mm1 \n\t" "punpcklbw %%mm7, %%mm1 \n\t" "punpcklbw %%mm7, %%mm0 \n\t" "pshufw $0xFF, %%mm1, %%mm1 \n\t" "1: \n\t" "pshufw $0xFF, %%mm0, %%mm0 \n\t" "2: \n\t" "psubw %%mm1, %%mm0 \n\t" "movl 8(%%ebx, %%eax), %%esi \n\t" "pmullw %%mm3, %%mm0 \n\t" "psllw $7, %%mm1 \n\t" "paddw %%mm1, %%mm0 \n\t" "movq %%mm0, (%%edi, %%eax) \n\t" "addl $8, %%eax \n\t" // End "9: \n\t"// "int $3\n\t" "leal 0b, %0 \n\t" "leal 1b, %1 \n\t" "leal 2b, %2 \n\t" "decl %1 \n\t" "decl %2 \n\t" "subl %0, %1 \n\t" "subl %0, %2 \n\t" "leal 9b, %3 \n\t" "subl %0, %3 \n\t" :"=r" (fragmentA), "=r" (imm8OfPShufW1A), "=r" (imm8OfPShufW2A), "=r" (fragmentLengthA) ); asm volatile( "jmp 9f \n\t" // Begin "0: \n\t" "movq (%%edx, %%eax), %%mm3 \n\t" "movd (%%ecx, %%esi), %%mm0 \n\t" "punpcklbw %%mm7, %%mm0 \n\t" "pshufw $0xFF, %%mm0, %%mm1 \n\t" "1: \n\t" "pshufw $0xFF, %%mm0, %%mm0 \n\t" "2: \n\t" "psubw %%mm1, %%mm0 \n\t" "movl 8(%%ebx, %%eax), %%esi \n\t" "pmullw %%mm3, %%mm0 \n\t" "psllw $7, %%mm1 \n\t" "paddw %%mm1, %%mm0 \n\t" "movq %%mm0, (%%edi, %%eax) \n\t" "addl $8, %%eax \n\t" // End "9: \n\t"// "int $3\n\t" "leal 0b, %0 \n\t" "leal 1b, %1 \n\t" "leal 2b, %2 \n\t" "decl %1 \n\t" "decl %2 \n\t" "subl %0, %1 \n\t" "subl %0, %2 \n\t" "leal 9b, %3 \n\t" "subl %0, %3 \n\t" :"=r" (fragmentB), "=r" (imm8OfPShufW1B), "=r" (imm8OfPShufW2B), "=r" (fragmentLengthB) ); xpos= 0; //lumXInc/2 - 0x8000; // difference between pixel centers fragmentPos=0; for(i=0; i<dstW/numSplits; i++) { int xx=xpos>>16; if((i&3) == 0) { int a=0; int b=((xpos+xInc)>>16) - xx; int c=((xpos+xInc*2)>>16) - xx; int d=((xpos+xInc*3)>>16) - xx; filter[i ] = (( xpos & 0xFFFF) ^ 0xFFFF)>>9; filter[i+1] = (((xpos+xInc ) & 0xFFFF) ^ 0xFFFF)>>9; filter[i+2] = (((xpos+xInc*2) & 0xFFFF) ^ 0xFFFF)>>9; filter[i+3] = (((xpos+xInc*3) & 0xFFFF) ^ 0xFFFF)>>9; filterPos[i/2]= xx; if(d+1<4) { int maxShift= 3-(d+1); int shift=0; memcpy(funnyCode + fragmentPos, fragmentB, fragmentLengthB); funnyCode[fragmentPos + imm8OfPShufW1B]= (a+1) | ((b+1)<<2) | ((c+1)<<4) | ((d+1)<<6); funnyCode[fragmentPos + imm8OfPShufW2B]= a | (b<<2) | (c<<4) | (d<<6); if(i+3>=dstW) shift=maxShift; //avoid overread else if((filterPos[i/2]&3) <= maxShift) shift=filterPos[i/2]&3; //Align if(shift && i>=shift) { funnyCode[fragmentPos + imm8OfPShufW1B]+= 0x55*shift; funnyCode[fragmentPos + imm8OfPShufW2B]+= 0x55*shift; filterPos[i/2]-=shift; } fragmentPos+= fragmentLengthB; } else { int maxShift= 3-d; int shift=0; memcpy(funnyCode + fragmentPos, fragmentA, fragmentLengthA); funnyCode[fragmentPos + imm8OfPShufW1A]= funnyCode[fragmentPos + imm8OfPShufW2A]= a | (b<<2) | (c<<4) | (d<<6); if(i+4>=dstW) shift=maxShift; //avoid overread else if((filterPos[i/2]&3) <= maxShift) shift=filterPos[i/2]&3; //partial align if(shift && i>=shift) { funnyCode[fragmentPos + imm8OfPShufW1A]+= 0x55*shift; funnyCode[fragmentPos + imm8OfPShufW2A]+= 0x55*shift; filterPos[i/2]-=shift; } fragmentPos+= fragmentLengthA; } funnyCode[fragmentPos]= RET; } xpos+=xInc; } filterPos[i/2]= xpos>>16; // needed to jump to the next part}#endif // ARCH_X86static void globalInit(){ // generating tables: int i; for(i=0; i<768; i++){ int c= MIN(MAX(i-256, 0), 255); clip_table[i]=c; }}static SwsFunc getSwsFunc(int flags){ #ifdef RUNTIME_CPUDETECT#ifdef ARCH_X86 // ordered per speed fasterst first if(flags & SWS_CPU_CAPS_MMX2) return swScale_MMX2; else if(flags & SWS_CPU_CAPS_3DNOW)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -