一 取亮度块数据
编码块结构
Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y |
Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y |
Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y |
Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y |
Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y |
Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y |
Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y |
Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y |
Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y |
Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y |
Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y |
Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y |
Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y |
Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y |
Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y |
Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y |
u | u | u | u | u | u | u | u | v | v | v | v | v | v | v | v |
u | u | u | u | u | u | u | u | v | v | v | v | v | v | v | v |
u | u | u | u | u | u | u | u | v | v | v | v | v | v | v | v |
u | u | u | u | u | u | u | u | v | v | v | v | v | v | v | v |
u | u | u | u | u | u | u | u | v | v | v | v | v | v | v | v |
u | u | u | u | u | u | u | u | v | v | v | v | v | v | v | v |
u | u | u | u | u | u | u | u | v | v | v | v | v | v | v | v |
u | u | u | u | u | u | u | u | v | v | v | v | v | v | v | v |
重建块结构
计算残差
static inline void pixel_sub_wxh( dctcoef *diff, int i_size,
pixel *pix1, int i_pix1, pixel *pix2, int i_pix2 )
{
for( int y = 0; y < i_size; y++ )
{
for( int x = 0; x < i_size; x++ )
diff[x + y*i_size] = pix1[x] - pix2[x];
pix1 += i_pix1; //编码块偏移一行
pix2 += i_pix2; //重建块偏移一行
}
}
static void sub4x4_dct( dctcoef dct[16], pixel *pix1, pixel *pix2 )
{
dctcoef d[16];
dctcoef tmp[16];
pixel_sub_wxh( d, 4, pix1, FENC_STRIDE, pix2, FDEC_STRIDE );
for( int i = 0; i < 4; i++ )
{
int s03 = d[i*4+0] + d[i*4+3];
int s12 = d[i*4+1] + d[i*4+2];
int d03 = d[i*4+0] - d[i*4+3];
int d12 = d[i*4+1] - d[i*4+2];
/*
s03 = d[0][0] + d[0][3]
s12 = d[0][1] + d[0][2]
d03 = d[0][0] - d[0][3]
d12 = d[0][1] - d[0][2]
*/
tmp[0*4+i] = s03 + s12;
tmp[1*4+i] = 2*d03 + d12;
tmp[2*4+i] = s03 - s12;
tmp[3*4+i] = d03 - 2*d12;
/* 矩阵系数为
1 1 1 1
2 1 -1 -2
1 -1 -1 1
1 -2 2 -1
*/
}
for( int i = 0; i < 4; i++ )
{
int s03 = tmp[i*4+0] + tmp[i*4+3];
int s12 = tmp[i*4+1] + tmp[i*4+2];
int d03 = tmp[i*4+0] - tmp[i*4+3];
int d12 = tmp[i*4+1] - tmp[i*4+2];
/*
s03 = d[0][0] + d[0][3]
s12 = d[0][1] + d[0][2]
d03 = d[0][0] - d[0][3]
d12 = d[0][1] - d[0][2]
*/
dct[i*4+0] = s03 + s12;
dct[i*4+1] = 2*d03 + d12;
dct[i*4+2] = s03 - s12;
dct[i*4+3] = d03 - 2*d12;
/* 矩阵是上面的转置
1 2 1 1
1 1 -1 -2
1 -1 -1 2
1 -2 1 -1
*/
}
}
三 simd汇编实现
00000000000001c0 <s264_8_sub4x4_dct_mmx>:
1c0: 0f 6e 06 movd (%rsi),%mm0 // 编码块存16字节到xmm0
1c3: 0f 6e 22 movd (%rdx),%mm4 //重建块存16字节到xmm4
1c6: 0f 60 c5 punpcklbw %mm5,%mm0 // xmm0 低64 bit padding ->xmm0 到w int16, 用来存储符号
1c9: 0f 60 e5 punpcklbw %mm5,%mm4 // 和上面一样
1cc: 0f f9 c4 psubw %mm4,%mm0 // 计算一行的sad 带符号的
1cf: 0f 6e 5e 30 movd 0x30(%rsi),%mm3 //偏移取像素数据 fenc
1d3: 0f 6e 62 60 movd 0x60(%rdx),%mm4 //偏移取重建数据
//第4行相减
1d7: 0f 60 dd punpcklbw %mm5,%mm3
1da: 0f 60 e5 punpcklbw %mm5,%mm4
1dd: 0f f9 dc psubw %mm4,%mm3
1e0: 0f 6e 4e 10 movd 0x10(%rsi),%mm1
1e4: 0f 6e 62 20 movd 0x20(%rdx),%mm4
1e8: 0f 60 cd punpcklbw %mm5,%mm1
1eb: 0f 60 e5 punpcklbw %mm5,%mm4
1ee: 0f f9 cc psubw %mm4,%mm1
// 第二行相减
1f1: 0f 6e 56 20 movd 0x20(%rsi),%mm2
1f5: 0f 6e 62 40 movd 0x40(%rdx),%mm4
1f9: 0f 60 d5 punpcklbw %mm5,%mm2
1fc: 0f 60 e5 punpcklbw %mm5,%mm4
1ff: 0f f9 d4 psubw %mm4,%mm2
//第三行相减
//结果分别存入xmm0,1,2,3
202: 0f 6f e3 movq %mm3,%mm4 //xmm3 -> xmm4
205: 0f fd d8 paddw %mm0,%mm3 //xmm0 + xmm3->xmm3
208: 0f f9 c4 psubw %mm4,%mm0 //xmm0 - xmm4->xmm0
20b: 0f 6f e2 movq %mm2,%mm4 //xmm2->xmm4
20e: 0f fd d1 paddw %mm1,%mm2 //xmm1 + xmm2 ->xmm2
211: 0f f9 cc psubw %mm4,%mm1 //xmm1 - xmm4->xmm1
214: 0f 6f e2 movq %mm2,%mm4 //xmm2->xmm4
217: 0f fd d3 paddw %mm3,%mm2 //xmm3 + xmm2->xmm2
21a: 0f f9 dc psubw %mm4,%mm3 //xmm3 - xmm4->xmm3
21d: 0f 6f e0 movq %mm0,%mm4 //xmm0 -> xmm4
220: 0f f9 e1 psubw %mm1,%mm4 //xmm4 - xmm1->xmm4
223: 0f f9 e1 psubw %mm1,%mm4
226: 0f fd c0 paddw %mm0,%mm0
229: 0f fd c1 paddw %mm1,%mm0
22c: 0f 6f ca movq %mm2,%mm1
22f: 0f 61 d0 punpcklwd %mm0,%mm2
232: 0f 69 c8 punpckhwd %mm0,%mm1
235: 0f 6f c3 movq %mm3,%mm0
238: 0f 61 dc punpcklwd %mm4,%mm3
23b: 0f 69 c4 punpckhwd %mm4,%mm0
23e: 0f 6f e2 movq %mm2,%mm4
241: 0f 62 d3 punpckldq %mm3,%mm2
244: 0f 6a e3 punpckhdq %mm3,%mm4
247: 0f 6f d9 movq %mm1,%mm3
24a: 0f 62 c8 punpckldq %mm0,%mm1
24d: 0f 6a d8 punpckhdq %mm0,%mm3
250: 0f 6f c3 movq %mm3,%mm0
253: 0f fd da paddw %mm2,%mm3
256: 0f f9 d0 psubw %mm0,%mm2
259: 0f 6f c1 movq %mm1,%mm0
25c: 0f fd cc paddw %mm4,%mm1
25f: 0f f9 e0 psubw %mm0,%mm4
262: 0f 6f c1 movq %mm1,%mm0
265: 0f fd cb paddw %mm3,%mm1
268: 0f f9 d8 psubw %mm0,%mm3
26b: 0f 6f c2 movq %mm2,%mm0
26e: 0f f9 c4 psubw %mm4,%mm0
271: 0f f9 c4 psubw %mm4,%mm0
274: 0f fd d2 paddw %mm2,%mm2
277: 0f fd d4 paddw %mm4,%mm2
27a: 0f 7f 0f movq %mm1,(%rdi)
27d: 0f 7f 57 08 movq %mm2,0x8(%rdi)
281: 0f 7f 5f 10 movq %mm3,0x10(%rdi)
285: 0f 7f 47 18 movq %mm0,0x18(%rdi)
289: c3 retq
28a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)