📄 postprocess_template.c
字号:
"pmaxub %%mm0, %%mm6 \n\t"
#else
#define REAL_FIND_MIN_MAX(addr)\
"movq " #addr ", %%mm0 \n\t"\
"movq %%mm7, %%mm1 \n\t"\
"psubusb %%mm0, %%mm6 \n\t"\
"paddb %%mm0, %%mm6 \n\t"\
"psubusb %%mm0, %%mm1 \n\t"\
"psubb %%mm1, %%mm7 \n\t"
#endif
#define FIND_MIN_MAX(addr) REAL_FIND_MIN_MAX(addr)
FIND_MIN_MAX((%%REGa))
FIND_MIN_MAX((%%REGa, %1))
FIND_MIN_MAX((%%REGa, %1, 2))
FIND_MIN_MAX((%0, %1, 4))
FIND_MIN_MAX((%%REGd))
FIND_MIN_MAX((%%REGd, %1))
FIND_MIN_MAX((%%REGd, %1, 2))
FIND_MIN_MAX((%0, %1, 8))
"movq %%mm7, %%mm4 \n\t"
"psrlq $8, %%mm7 \n\t"
#ifdef HAVE_MMX2
"pminub %%mm4, %%mm7 \n\t" // min of pixels
"pshufw $0xF9, %%mm7, %%mm4 \n\t"
"pminub %%mm4, %%mm7 \n\t" // min of pixels
"pshufw $0xFE, %%mm7, %%mm4 \n\t"
"pminub %%mm4, %%mm7 \n\t"
#else
"movq %%mm7, %%mm1 \n\t"
"psubusb %%mm4, %%mm1 \n\t"
"psubb %%mm1, %%mm7 \n\t"
"movq %%mm7, %%mm4 \n\t"
"psrlq $16, %%mm7 \n\t"
"movq %%mm7, %%mm1 \n\t"
"psubusb %%mm4, %%mm1 \n\t"
"psubb %%mm1, %%mm7 \n\t"
"movq %%mm7, %%mm4 \n\t"
"psrlq $32, %%mm7 \n\t"
"movq %%mm7, %%mm1 \n\t"
"psubusb %%mm4, %%mm1 \n\t"
"psubb %%mm1, %%mm7 \n\t"
#endif
"movq %%mm6, %%mm4 \n\t"
"psrlq $8, %%mm6 \n\t"
#ifdef HAVE_MMX2
"pmaxub %%mm4, %%mm6 \n\t" // max of pixels
"pshufw $0xF9, %%mm6, %%mm4 \n\t"
"pmaxub %%mm4, %%mm6 \n\t"
"pshufw $0xFE, %%mm6, %%mm4 \n\t"
"pmaxub %%mm4, %%mm6 \n\t"
#else
"psubusb %%mm4, %%mm6 \n\t"
"paddb %%mm4, %%mm6 \n\t"
"movq %%mm6, %%mm4 \n\t"
"psrlq $16, %%mm6 \n\t"
"psubusb %%mm4, %%mm6 \n\t"
"paddb %%mm4, %%mm6 \n\t"
"movq %%mm6, %%mm4 \n\t"
"psrlq $32, %%mm6 \n\t"
"psubusb %%mm4, %%mm6 \n\t"
"paddb %%mm4, %%mm6 \n\t"
#endif
"movq %%mm6, %%mm0 \n\t" // max
"psubb %%mm7, %%mm6 \n\t" // max - min
"movd %%mm6, %%ecx \n\t"
"cmpb "MANGLE(deringThreshold)", %%cl \n\t"
" jb 1f \n\t"
"lea -24(%%"REG_SP"), %%"REG_c" \n\t"
"and "ALIGN_MASK", %%"REG_c" \n\t"
PAVGB(%%mm0, %%mm7) // a=(max + min)/2
"punpcklbw %%mm7, %%mm7 \n\t"
"punpcklbw %%mm7, %%mm7 \n\t"
"punpcklbw %%mm7, %%mm7 \n\t"
"movq %%mm7, (%%"REG_c") \n\t"
"movq (%0), %%mm0 \n\t" // L10
"movq %%mm0, %%mm1 \n\t" // L10
"movq %%mm0, %%mm2 \n\t" // L10
"psllq $8, %%mm1 \n\t"
"psrlq $8, %%mm2 \n\t"
"movd -4(%0), %%mm3 \n\t"
"movd 8(%0), %%mm4 \n\t"
"psrlq $24, %%mm3 \n\t"
"psllq $56, %%mm4 \n\t"
"por %%mm3, %%mm1 \n\t" // L00
"por %%mm4, %%mm2 \n\t" // L20
"movq %%mm1, %%mm3 \n\t" // L00
PAVGB(%%mm2, %%mm1) // (L20 + L00)/2
PAVGB(%%mm0, %%mm1) // (L20 + L00 + 2L10)/4
"psubusb %%mm7, %%mm0 \n\t"
"psubusb %%mm7, %%mm2 \n\t"
"psubusb %%mm7, %%mm3 \n\t"
"pcmpeqb "MANGLE(b00)", %%mm0 \n\t" // L10 > a ? 0 : -1
"pcmpeqb "MANGLE(b00)", %%mm2 \n\t" // L20 > a ? 0 : -1
"pcmpeqb "MANGLE(b00)", %%mm3 \n\t" // L00 > a ? 0 : -1
"paddb %%mm2, %%mm0 \n\t"
"paddb %%mm3, %%mm0 \n\t"
"movq (%%"REG_a"), %%mm2 \n\t" // L11
"movq %%mm2, %%mm3 \n\t" // L11
"movq %%mm2, %%mm4 \n\t" // L11
"psllq $8, %%mm3 \n\t"
"psrlq $8, %%mm4 \n\t"
"movd -4(%%"REG_a"), %%mm5 \n\t"
"movd 8(%%"REG_a"), %%mm6 \n\t"
"psrlq $24, %%mm5 \n\t"
"psllq $56, %%mm6 \n\t"
"por %%mm5, %%mm3 \n\t" // L01
"por %%mm6, %%mm4 \n\t" // L21
"movq %%mm3, %%mm5 \n\t" // L01
PAVGB(%%mm4, %%mm3) // (L21 + L01)/2
PAVGB(%%mm2, %%mm3) // (L21 + L01 + 2L11)/4
"psubusb %%mm7, %%mm2 \n\t"
"psubusb %%mm7, %%mm4 \n\t"
"psubusb %%mm7, %%mm5 \n\t"
"pcmpeqb "MANGLE(b00)", %%mm2 \n\t" // L11 > a ? 0 : -1
"pcmpeqb "MANGLE(b00)", %%mm4 \n\t" // L21 > a ? 0 : -1
"pcmpeqb "MANGLE(b00)", %%mm5 \n\t" // L01 > a ? 0 : -1
"paddb %%mm4, %%mm2 \n\t"
"paddb %%mm5, %%mm2 \n\t"
// 0, 2, 3, 1
#define REAL_DERING_CORE(dst,src,ppsx,psx,sx,pplx,plx,lx,t0,t1) \
"movq " #src ", " #sx " \n\t" /* src[0] */\
"movq " #sx ", " #lx " \n\t" /* src[0] */\
"movq " #sx ", " #t0 " \n\t" /* src[0] */\
"psllq $8, " #lx " \n\t"\
"psrlq $8, " #t0 " \n\t"\
"movd -4" #src ", " #t1 " \n\t"\
"psrlq $24, " #t1 " \n\t"\
"por " #t1 ", " #lx " \n\t" /* src[-1] */\
"movd 8" #src ", " #t1 " \n\t"\
"psllq $56, " #t1 " \n\t"\
"por " #t1 ", " #t0 " \n\t" /* src[+1] */\
"movq " #lx ", " #t1 " \n\t" /* src[-1] */\
PAVGB(t0, lx) /* (src[-1] + src[+1])/2 */\
PAVGB(sx, lx) /* (src[-1] + 2src[0] + src[+1])/4 */\
PAVGB(lx, pplx) \
"movq " #lx ", 8(%%"REG_c") \n\t"\
"movq (%%"REG_c"), " #lx " \n\t"\
"psubusb " #lx ", " #t1 " \n\t"\
"psubusb " #lx ", " #t0 " \n\t"\
"psubusb " #lx ", " #sx " \n\t"\
"movq "MANGLE(b00)", " #lx " \n\t"\
"pcmpeqb " #lx ", " #t1 " \n\t" /* src[-1] > a ? 0 : -1*/\
"pcmpeqb " #lx ", " #t0 " \n\t" /* src[+1] > a ? 0 : -1*/\
"pcmpeqb " #lx ", " #sx " \n\t" /* src[0] > a ? 0 : -1*/\
"paddb " #t1 ", " #t0 " \n\t"\
"paddb " #t0 ", " #sx " \n\t"\
\
PAVGB(plx, pplx) /* filtered */\
"movq " #dst ", " #t0 " \n\t" /* dst */\
"movq " #t0 ", " #t1 " \n\t" /* dst */\
"psubusb %3, " #t0 " \n\t"\
"paddusb %3, " #t1 " \n\t"\
PMAXUB(t0, pplx)\
PMINUB(t1, pplx, t0)\
"paddb " #sx ", " #ppsx " \n\t"\
"paddb " #psx ", " #ppsx " \n\t"\
"#paddb "MANGLE(b02)", " #ppsx " \n\t"\
"pand "MANGLE(b08)", " #ppsx " \n\t"\
"pcmpeqb " #lx ", " #ppsx " \n\t"\
"pand " #ppsx ", " #pplx " \n\t"\
"pandn " #dst ", " #ppsx " \n\t"\
"por " #pplx ", " #ppsx " \n\t"\
"movq " #ppsx ", " #dst " \n\t"\
"movq 8(%%"REG_c"), " #lx " \n\t"
#define DERING_CORE(dst,src,ppsx,psx,sx,pplx,plx,lx,t0,t1) \
REAL_DERING_CORE(dst,src,ppsx,psx,sx,pplx,plx,lx,t0,t1)
/*
0000000
1111111
1111110
1111101
1111100
1111011
1111010
1111001
1111000
1110111
*/
//DERING_CORE(dst,src ,ppsx ,psx ,sx ,pplx ,plx ,lx ,t0 ,t1)
DERING_CORE((%%REGa),(%%REGa, %1) ,%%mm0,%%mm2,%%mm4,%%mm1,%%mm3,%%mm5,%%mm6,%%mm7)
DERING_CORE((%%REGa, %1),(%%REGa, %1, 2) ,%%mm2,%%mm4,%%mm0,%%mm3,%%mm5,%%mm1,%%mm6,%%mm7)
DERING_CORE((%%REGa, %1, 2),(%0, %1, 4) ,%%mm4,%%mm0,%%mm2,%%mm5,%%mm1,%%mm3,%%mm6,%%mm7)
DERING_CORE((%0, %1, 4),(%%REGd) ,%%mm0,%%mm2,%%mm4,%%mm1,%%mm3,%%mm5,%%mm6,%%mm7)
DERING_CORE((%%REGd),(%%REGd, %1) ,%%mm2,%%mm4,%%mm0,%%mm3,%%mm5,%%mm1,%%mm6,%%mm7)
DERING_CORE((%%REGd, %1), (%%REGd, %1, 2),%%mm4,%%mm0,%%mm2,%%mm5,%%mm1,%%mm3,%%mm6,%%mm7)
DERING_CORE((%%REGd, %1, 2),(%0, %1, 8) ,%%mm0,%%mm2,%%mm4,%%mm1,%%mm3,%%mm5,%%mm6,%%mm7)
DERING_CORE((%0, %1, 8),(%%REGd, %1, 4) ,%%mm2,%%mm4,%%mm0,%%mm3,%%mm5,%%mm1,%%mm6,%%mm7)
"1: \n\t"
: : "r" (src), "r" ((long)stride), "m" (c->pQPb), "m"(c->pQPb2)
: "%"REG_a, "%"REG_d, "%"REG_c
);
#else
int y;
int min=255;
int max=0;
int avg;
uint8_t *p;
int s[10];
const int QP2= c->QP/2 + 1;
for(y=1; y<9; y++)
{
int x;
p= src + stride*y;
for(x=1; x<9; x++)
{
p++;
if(*p > max) max= *p;
if(*p < min) min= *p;
}
}
avg= (min + max + 1)>>1;
if(max - min <deringThreshold) return;
for(y=0; y<10; y++)
{
int t = 0;
if(src[stride*y + 0] > avg) t+= 1;
if(src[stride*y + 1] > avg) t+= 2;
if(src[stride*y + 2] > avg) t+= 4;
if(src[stride*y + 3] > avg) t+= 8;
if(src[stride*y + 4] > avg) t+= 16;
if(src[stride*y + 5] > avg) t+= 32;
if(src[stride*y + 6] > avg) t+= 64;
if(src[stride*y + 7] > avg) t+= 128;
if(src[stride*y + 8] > avg) t+= 256;
if(src[stride*y + 9] > avg) t+= 512;
t |= (~t)<<16;
t &= (t<<1) & (t>>1);
s[y] = t;
}
for(y=1; y<9; y++)
{
int t = s[y-1] & s[y] & s[y+1];
t|= t>>16;
s[y-1]= t;
}
for(y=1; y<9; y++)
{
int x;
int t = s[y-1];
p= src + stride*y;
for(x=1; x<9; x++)
{
p++;
if(t & (1<<x))
{
int f= (*(p-stride-1)) + 2*(*(p-stride)) + (*(p-stride+1))
+2*(*(p -1)) + 4*(*p ) + 2*(*(p +1))
+(*(p+stride-1)) + 2*(*(p+stride)) + (*(p+stride+1));
f= (f + 8)>>4;
#ifdef DEBUG_DERING_THRESHOLD
asm volatile("emms\n\t":);
{
static long long numPixels=0;
if(x!=1 && x!=8 && y!=1 && y!=8) numPixels++;
// if((max-min)<20 || (max-min)*QP<200)
// if((max-min)*QP < 500)
// if(max-min<QP/2)
if(max-min < 20)
{
static int numSkiped=0;
static int errorSum=0;
static int worstQP=0;
static int worstRange=0;
static int worstDiff=0;
int diff= (f - *p);
int absDiff= ABS(diff);
int error= diff*diff;
if(x==1 || x==8 || y==1 || y==8) continue;
numSkiped++;
if(absDiff > worstDiff)
{
worstDiff= absDiff;
worstQP= QP;
worstRange= max-min;
}
errorSum+= error;
if(1024LL*1024LL*1024LL % numSkiped == 0)
{
printf( "sum:%1.3f, skip:%d, wQP:%d, "
"wRange:%d, wDiff:%d, relSkip:%1.3f\n",
(float)errorSum/numSkiped, numSkiped, worstQP, worstRange,
worstDiff, (float)numSkiped/numPixels);
}
}
}
#endif
if (*p + QP2 < f) *p= *p + QP2;
else if(*p - QP2 > f) *p= *p - QP2;
else *p=f;
}
}
}
#ifdef DEBUG_DERING_THRESHOLD
if(max-min < 20)
{
for(y=1; y<9; y++)
{
int x;
int t = 0;
p= src + stride*y;
for(x=1; x<9; x++)
{
p++;
*p = MIN(*p + 20, 255);
}
}
// src[0] = src[7]=src[stride*7]=src[stride*7 + 7]=255;
}
#endif
#endif
}
#endif //HAVE_ALTIVEC
/**
* Deinterlaces the given block by linearly interpolating every second line.
* will be called for every 8x8 block and can read & write from line 4-15
* lines 0-3 have been passed through the deblock / dering filters allready, but can be read too
* lines 4-12 will be read into the deblocking filter and should be deinterlaced
*/
static inline void RENAME(deInterlaceInterpolateLinear)(uint8_t src[], int stride)
{
#if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
src+= 4*stride;
asm volatile(
"lea (%0, %1), %%"REG_a" \n\t"
"lea (%%"REG_a", %1, 4), %%"REG_c" \n\t"
// 0 1 2 3 4 5 6 7 8 9
// %0 eax eax+%1 eax+2%1 %0+4%1 ecx ecx+%1 ecx+2%1 %0+8%1 ecx+4%1
"movq (%0), %%mm0 \n\t"
"movq (%%"REG_a", %1), %%mm1 \n\t"
PAVGB(%%mm1, %%mm0)
"movq %%mm0, (%%"REG_a") \n\t"
"movq (%0, %1, 4), %%mm0 \n\t"
PAVGB(%%mm0, %%mm1)
"movq %%mm1, (%%"REG_a", %1, 2) \n\t"
"movq (%%"REG_c", %1), %%mm1 \n\t"
PAVGB(%%mm1, %%mm0)
"movq %%mm0, (%%"REG_c") \n\t"
"movq (%0, %1, 8), %%mm0 \n\t"
PAVGB(%%mm0, %%mm1)
"movq %%mm1, (%%"REG_c", %1, 2) \n\t"
: : "r" (src), "r" ((long)stride)
: "%"REG_a, "%"REG_c
);
#else
int a, b, x;
src+= 4*stride;
for(x=0; x<2; x++){
a= *(uint32_t*)&src[stride*0];
b= *(uint32_t*)&src[stride*2];
*(uint32_t*)&src[stride*1]= (a|b) - (((a^b)&0xFEFEFEFEUL)>>1);
a= *(uint32_t*)&src[stride*4];
*(uint32_t*)&src[stride*3]= (a|b) - (((a^b)&0xFEFEFEFEUL)>>1);
b= *(uint32_t*)&src[stride*6];
*(uint32_t*)&src[stride*5]= (a|b) - (((a^b)&0xFEFEFEFEUL)>>1);
a= *(uint32_t*)&src[stride*8];
*(uint32_t*)&src[stride*7]= (a|b) - (((a^b)&0xFEFEFEFEUL)>>1);
src += 4;
}
#endif
}
/**
* Deinterlaces the given block by cubic interpolating every second line.
* will be called for every 8x8 block and can read & write from line 4-15
* lines 0-3 have been passed through the deblock / dering filters allready, but can be read too
* lines 4-12 will be read into the deblocking filter and should be deinterlaced
* this filter will read lines 3-15 and write 7-13
*/
static inline void RENAME(deInterlaceInterpolateCubic)(uint8_t src[], int stride)
{
#if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
src+= stride*3;
asm volatile(
"lea (%0, %1), %%"REG_a" \n\t"
"lea (%%"REG_a", %1, 4), %%"REG_d" \n\t"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -