H.264对帧内或帧间预测的残差(residual)进行DCT变换编码。为了克服浮点运算带来的硬件设计复杂,更重要的是舍入误差造成的编码器和解码器之间不匹配(mismatch)的问题,新标准对DCT的定义做了修改,使得变换仅用整数加减法和移位操作即可实现,这样在不考虑量化影响的情况下,解码端的输出可以准确地恢复编码端的输入。当然这样做的代价是压缩性能的略微下降。此外,该变换是针对4×4块进行的,这也有助于减少块效应。
为了进一步利用图像的空间相关性,在对chroma的预测残差和16×16帧内预测的预测残差进行上述整数DCT变换之后,标准还将每个4×4变换系数块中的DC系数组成2×2或4×4大小的块,进一步做哈达玛(Hadamard)变换。
是Hadamard矩阵成立的充要条件。
1阶和2阶的Hadamard矩阵
在H.264中使用了4阶和8阶的Hadamard变换来计算SATD,其变换矩阵为:
Int SATD (int* diff, int use_hadamard) { int k, satd = 0, m[16], dd, *d=diff;
if (use_hadamard) { /*===== hadamard transform =====*/ ------------------------第一阶段计算------------------------ m[ 0] = d[ 0] + d[12]; m[ 4] = d[ 4] + d[ 8]; m[ 8] = d[ 4] - d[ 8]; m[12] = d[ 0] - d[12]; m[ 1] = d[ 1] + d[13]; m[ 5] = d[ 5] + d[ 9]; m[ 9] = d[ 5] - d[ 9]; m[13] = d[ 1] - d[13]; m[ 2] = d[ 2] + d[14]; m[ 6] = d[ 6] + d[10]; m[10] = d[ 6] - d[10]; m[14] = d[ 2] - d[14]; m[ 3] = d[ 3] + d[15]; m[ 7] = d[ 7] + d[11]; m[11] = d[ 7] - d[11]; m[15] = d[ 3] - d[15];
d[ 0] = m[ 0] + m[ 4]; -> d[ 0] + d[12]+ d[ 4] + d[ 8] d[ 8] = m[ 0] - m[ 4]; -> d[ 0] + d[12]-( d[ 4] + d[ 8]) d[ 4] = m[ 8] + m[12]; -> d[ 4] - d[ 8]+ d[ 0] - d[12] d[12] = m[12] - m[ 8]; -> d[ 0] - d[12] - d[ 4] +d[ 8] d[ 1] = m[ 1] + m[ 5]; -> d[ 1] + d[13] + d[ 5] + d[ 9] d[ 9] = m[ 1] - m[ 5]; -> d[ 5] + d[ 9] - d[ 1] + d[13] d[ 5] = m[ 9] + m[13]; -> d[ 5] - d[ 9] + d[ 1] - d[13] d[13] = m[13] - m[ 9]; -> d[ 1] - d[13] - d[ 5] - d[ 9] d[ 2] = m[ 2] + m[ 6]; -> d[ 2] + d[14] + d[ 6] + d[10] d[10] = m[ 2] - m[ 6]; d[ 6] = m[10] + m[14]; d[14] = m[14] - m[10]; d[ 3] = m[ 3] + m[ 7]; d[11] = m[ 3] - m[ 7]; d[ 7] = m[11] + m[15]; d[15] = m[15] - m[11]; --------------------第二阶段计算----------------- m[ 0] = d[ 0] + d[ 3]; m[ 1] = d[ 1] + d[ 2]; m[ 2] = d[ 1] - d[ 2]; m[ 3] = d[ 0] - d[ 3]; m[ 4] = d[ 4] + d[ 7]; m[ 5] = d[ 5] + d[ 6]; m[ 6] = d[ 5] - d[ 6]; m[ 7] = d[ 4] - d[ 7]; m[ 8] = d[ 8] + d[11]; m[ 9] = d[ 9] + d[10]; m[10] = d[ 9] - d[10]; m[11] = d[ 8] - d[11]; m[12] = d[12] + d[15]; m[13] = d[13] + d[14]; m[14] = d[13] - d[14]; m[15] = d[12] - d[15];
d[ 0] = m[ 0] + m[ 1]; d[ 1] = m[ 0] - m[ 1]; d[ 2] = m[ 2] + m[ 3]; d[ 3] = m[ 3] - m[ 2]; d[ 4] = m[ 4] + m[ 5]; d[ 5] = m[ 4] - m[ 5]; d[ 6] = m[ 6] + m[ 7]; d[ 7] = m[ 7] - m[ 6]; d[ 8] = m[ 8] + m[ 9]; d[ 9] = m[ 8] - m[ 9]; d[10] = m[10] + m[11]; d[11] = m[11] - m[10]; d[12] = m[12] + m[13]; d[13] = m[12] - m[13]; d[14] = m[14] + m[15]; d[15] = m[15] - m[14];
/*===== sum up =====*/ for (dd=diff[k=0]; k<16; dd=diff[++k]) { satd += (dd < 0 ? -dd : dd); } satd >>= 1; } else { /*===== sum up =====*/ for (k = 0; k < 16; k++) { satd += byte_abs [diff [k]]; } }
return satd; } |