在TI 的DSP 平台下优化AVS 的 IDCT 反变换的方法和代码
来源:互联网 发布:淘宝素材中心作用 编辑:程序博客网 时间:2024/04/28 14:55
一, AVS标准规定的IDCT反变换
本条定义将8´8变换系数矩阵CoeffMatrix转换为8´8残差样值矩阵ResidueMatrix的过程,步骤如下:
00001—— 首先,对变换系数矩阵进行如下水平反变换:
H¢ = CoeffMatrix ´ T8T
其中,T 8是8´8反变换矩阵,T 8T是T8的转置矩阵, H¢ 表示水平反变换后的中间结果。从符合本部分的比特流中解码得到的H¢矩阵元素取值范围应为 –215~215–5。
8 10 10 9 8 6 4 2
8 9 4 -2 -8 -10 -10 -6
8 6 -4 -10 -8 2 10 9
8 2 -10 -6 8 9 -4 -10
T8 = 8 -2 -10 6 8 -9 -4 10
8 -6 -4 10 -8 -2 10 -9
8 -9 4 2 -8 10 -10 6
8 -10 10 -9 8 -6 4 -2
00002—— 第二步,对矩阵H¢中的每个系数加4再右移3位,得到矩阵H¢¢。
00003—— 第三步,对矩阵H¢¢进行如下垂直反变换:
H = T8 ´ H¢¢
其中,H表示反变换后的8´8矩阵。从符合本部分的比特流中解码得到的H矩阵元素取值范围应为 –215~215–65。
00004—— 第四步,残差样值矩阵ResidueMatrix的元素rij计算如下:
rij = (hij + 26) >> 7 i, j = 0..7
其中hij是H矩阵的元素。
二, C语言实现
void idct_c_dsp(short* blk)
{
int i, j;
short* b = blk;
short x[8];
int r[12];
int z[8];
for(i=0; i<8; i++, b+=8) // horizontal transform
{
for(j=0; j<8; j++)
{
x[j] = b[j];
}
r[0] = 8 * x[0] + 8 * x[4];
r[1] = 8 * x[0] - 8 * x[4];
r[2] = 10 * x[1] + 6 * x[5];
r[3] = 9 * x[1] - 10 * x[5];
r[4] = 6 * x[1] + 2 * x[5];
r[5] = 2 * x[1] + 9 * x[5];
r[6] = 10 * x[2] + 4 * x[6];
r[7] = 4 * x[2] - 10 * x[6];
r[8] = 9 * x[3] + 2 * x[7];
r[9] = 2 * x[3] + 6 * x[7];
r[10]= 10 * x[3] - 9 * x[7];
r[11]= 6 * x[3] + 10 * x[7];
z[0] = r[0] + r[6];
z[1] = r[2] + r[8];
z[2] = r[1] + r[7];
z[3] = r[3] - r[9];
z[4] = r[1] - r[7];
z[5] = r[4] - r[10];
z[6] = r[0] - r[6];
z[7] = r[5] - r[11];
b[0] = (short) (CLIP3(-32768, 32767, (z[0] + z[1] + 4)) >> 3);
b[1] = (short) (CLIP3(-32768, 32767, (z[2] + z[3] + 4)) >> 3);
b[2] = (short) (CLIP3(-32768, 32767, (z[4] + z[5] + 4)) >> 3);
b[3] = (short) (CLIP3(-32768, 32767, (z[6] + z[7] + 4)) >> 3);
b[4] = (short) (CLIP3(-32768, 32767, (z[6] - z[7] + 4)) >> 3);
b[5] = (short) (CLIP3(-32768, 32767, (z[4] - z[5] + 4)) >> 3);
b[6] = (short) (CLIP3(-32768, 32767, (z[2] - z[3] + 4)) >> 3);
b[7] = (short) (CLIP3(-32768, 32767, (z[0] - z[1] + 4)) >> 3);
}
b = blk;
for(i=0; i<8; i++, b+=1) // vertical transform
{
for(j=0; j<8; j++)
{
x[j] = b[j*8];
}
r[0] = 8 * x[0] + 8 * x[4]; // 0x080008
r[1] = 8 * x[0] - 8 * x[4]; // 0x080008
r[2] = 10 * x[1] + 6 * x[5]; // 0x0a0006
r[3] = 9 * x[1] - 10 * x[5]; // 0x09000a
r[4] = 6 * x[1] + 2 * x[5]; // 0x060002
r[5] = 2 * x[1] + 9 * x[5]; // 0x020009
r[6] = 10 * x[2] + 4 * x[6]; // 0x0a0004
r[7] = 4 * x[2] - 10 * x[6]; // 0x04000a
r[8] = 9 * x[3] + 2 * x[7]; // 0x090002
r[9] = 2 * x[3] + 6 * x[7]; // 0x020006
r[10]= 10 * x[3] - 9 * x[7]; // 0x0a0009
r[11]= 6 * x[3] + 10 * x[7]; // 0x06000a
z[0] = r[0] + r[6];
z[1] = r[2] + r[8];
z[2] = r[1] + r[7];
z[3] = r[3] - r[9];
z[4] = r[1] - r[7];
z[5] = r[4] - r[10];
z[6] = r[0] - r[6];
z[7] = r[5] - r[11];
b[0*8] = (short) (CLIP3(-32768, 32767, (z[0] + z[1] + 64)) >> 7);
b[1*8] = (short) (CLIP3(-32768, 32767, (z[2] + z[3] + 64)) >> 7);
b[2*8] = (short) (CLIP3(-32768, 32767, (z[4] + z[5] + 64)) >> 7);
b[3*8] = (short) (CLIP3(-32768, 32767, (z[6] + z[7] + 64)) >> 7);
b[4*8] = (short) (CLIP3(-32768, 32767, (z[6] - z[7] + 64)) >> 7);
b[5*8] = (short) (CLIP3(-32768, 32767, (z[4] - z[5] + 64)) >> 7);
b[6*8] = (short) (CLIP3(-32768, 32767, (z[2] - z[3] + 64)) >> 7);
b[7*8] = (short) (CLIP3(-32768, 32767, (z[0] - z[1] + 64)) >> 7);
}
}
三,C语言实现的算法分析
仔细分析系数矩阵可以看到特点:偶数列上的上四行和下四行是对称的,奇数列上的上四行和下四行是反对称的。这样就可以得出十二个基本项,就是c代码中的r[12],进而得到8个值z[8],最后得到反变换的值。仔细阅读代码就会清楚的明白了。
需要注意的是,CLIP3函数实际是用来求16位的有符号数的饱和计算。在理想情况下系数矩阵经过变换后是不会出现超出16位可表示的数值的,但在实际中还是会出现极少数情况超出,为了优化又需要在16位之内计算,因此,采用折中的办法将超出进行饱和处理,保证IDCT的精度损失较小。
四,基于TI 的6000系列DSP优化
1,利用dsp的乘加指令和32位加载伪指令进行初步优化,代码实现如下
void idct_intrinsic_dsp(short* blk)
{
int i;
short* b = blk;
int x[4];
int r[12];
int z[8];
_nassert(((int)(blk) & 0x03) == 0);
for(i=0; i<8; i++, b+=8) // horizontal transform
{
x[0] = _mem4(&b[0]); // b[1] b[0] , little endian
x[1] = _mem4(&b[2]); // b[3] b[2]
x[2] = _mem4(&b[4]); // b[5] b[4]
x[3] = _mem4(&b[6]); // b[7] b[6]
r[0] = x[0]; // save x[0]
r[1] = x[1]; // save x[1]
x[0] = _pack2 (r[0], x[2]); // b[0] b[4]
x[1] = _packh2(r[0], x[2]); // b[1] b[5]
x[2] = _pack2 (r[1], x[3]); // b[2] b[6]
x[3] = _packh2(r[1], x[3]); // b[3] b[7]
r[0] = _dotp2 (0x080008, x[0]); // r[0] = 8 * x[0] + 8 * x[4]; // 0x080008
r[1] = _dotpn2(0x080008, x[0]); // r[1] = 8 * x[0] - 8 * x[4]; // 0x08fff8
r[2] = _dotp2 (0x0a0006, x[1]); // r[2] = 10 * x[1] + 6 * x[5]; // 0x0a0006
r[3] = _dotpn2(0x09000a, x[1]); // r[3] = 9 * x[1] - 10 * x[5]; // 0x09000a
r[4] = _dotp2 (0x060002, x[1]); // r[4] = 6 * x[1] + 2 * x[5]; // 0x060002
r[5] = _dotp2 (0x020009, x[1]); // r[5] = 2 * x[1] + 9 * x[5]; // 0x020009
r[6] = _dotp2 (0x0a0004, x[2]); // r[6] = 10 * x[2] + 4 * x[6]; // 0x0a0004
r[7] = _dotpn2(0x04000a, x[2]); // r[7] = 4 * x[2] - 10 * x[6]; // 0x04000a
r[8] = _dotp2 (0x090002, x[3]); // r[8] = 9 * x[3] + 2 * x[7]; // 0x090002
r[9] = _dotp2 (0x020006, x[3]); // r[9] = 2 * x[3] + 6 * x[7]; // 0x020006
r[10]= _dotpn2(0x0a0009, x[3]); // r[10]= 10 * x[3] - 9 * x[7]; // 0x0a0009
r[11]= _dotp2 (0x06000a, x[3]); // r[11]= 6 * x[3] + 10 * x[7]; // 0x06000a
z[0] = r[0] + r[6];
z[1] = r[2] + r[8];
z[2] = r[1] + r[7];
z[3] = r[3] - r[9];
z[4] = r[1] - r[7];
z[5] = r[4] - r[10];
z[6] = r[0] - r[6];
z[7] = r[5] - r[11];
b[0] = (short)(CLIP3(-32768, 32767, (z[0] + z[1] + 4)) >> 3);
b[1] = (short)(CLIP3(-32768, 32767, (z[2] + z[3] + 4)) >> 3);
b[2] = (short)(CLIP3(-32768, 32767, (z[4] + z[5] + 4)) >> 3);
b[3] = (short)(CLIP3(-32768, 32767, (z[6] + z[7] + 4)) >> 3);
b[4] = (short)(CLIP3(-32768, 32767, (z[6] - z[7] + 4)) >> 3);
b[5] = (short)(CLIP3(-32768, 32767, (z[4] - z[5] + 4)) >> 3);
b[6] = (short)(CLIP3(-32768, 32767, (z[2] - z[3] + 4)) >> 3);
b[7] = (short)(CLIP3(-32768, 32767, (z[0] - z[1] + 4)) >> 3);
}
b = blk;
for(i=0; i<8; i++, b+=1) // horizontal transform
{
short* p = (short*)x;
p[0] = b[4*8];
p[1] = b[0*8];
p[2] = b[5*8];
p[3] = b[1*8];
p[4] = b[6*8];
p[5] = b[2*8];
p[6] = b[7*8];
p[7] = b[3*8];
r[0] = _dotp2 (0x080008, x[0]); // r[0] = 8 * x[0] + 8 * x[4]; // 0x080008
r[1] = _dotpn2(0x080008, x[0]); // r[1] = 8 * x[0] - 8 * x[4]; // 0x08fff8
r[2] = _dotp2 (0x0a0006, x[1]); // r[2] = 10 * x[1] + 6 * x[5]; // 0x0a0006
r[3] = _dotpn2(0x09000a, x[1]); // r[3] = 9 * x[1] - 10 * x[5]; // 0x09000a
r[4] = _dotp2 (0x060002, x[1]); // r[4] = 6 * x[1] + 2 * x[5]; // 0x060002
r[5] = _dotp2 (0x020009, x[1]); // r[5] = 2 * x[1] + 9 * x[5]; // 0x020009
r[6] = _dotp2 (0x0a0004, x[2]); // r[6] = 10 * x[2] + 4 * x[6]; // 0x0a0004
r[7] = _dotpn2(0x04000a, x[2]); // r[7] = 4 * x[2] - 10 * x[6]; // 0x04000a
r[8] = _dotp2 (0x090002, x[3]); // r[8] = 9 * x[3] + 2 * x[7]; // 0x090002
r[9] = _dotp2 (0x020006, x[3]); // r[9] = 2 * x[3] + 6 * x[7]; // 0x020006
r[10]= _dotpn2(0x0a0009, x[3]); // r[10]= 10 * x[3] - 9 * x[7]; // 0x0a0009
r[11]= _dotp2 (0x06000a, x[3]); // r[11]= 6 * x[3] + 10 * x[7]; // 0x06000a
z[0] = r[0] + r[6];
z[1] = r[2] + r[8];
z[2] = r[1] + r[7];
z[3] = r[3] - r[9];
z[4] = r[1] - r[7];
z[5] = r[4] - r[10];
z[6] = r[0] - r[6];
z[7] = r[5] - r[11];
b[0*8] = (short)(CLIP3(-32768, 32767, (z[0] + z[1] + 64)) >> 7);
b[1*8] = (short)(CLIP3(-32768, 32767, (z[2] + z[3] + 64)) >> 7);
b[2*8] = (short)(CLIP3(-32768, 32767, (z[4] + z[5] + 64)) >> 7);
b[3*8] = (short)(CLIP3(-32768, 32767, (z[6] + z[7] + 64)) >> 7);
b[4*8] = (short)(CLIP3(-32768, 32767, (z[6] - z[7] + 64)) >> 7);
b[5*8] = (short)(CLIP3(-32768, 32767, (z[4] - z[5] + 64)) >> 7);
b[6*8] = (short)(CLIP3(-32768, 32767, (z[2] - z[3] + 64)) >> 7);
b[7*8] = (short)(CLIP3(-32768, 32767, (z[0] - z[1] + 64)) >> 7);
}
}
从代码实现可以看出利用dsp的乘加指令实现求r数组的12个基本值比较简洁,但是,注意到,关键的内存加载部分代码优化效果一般,而存储部分还没有改变。下面,着重说明该部分的优化方法。
2,存储优化分析
注意:由于语言表达不太清楚,请仔细看矩阵的行列坐标,和代码就很容易理解这样做的好处了。
设CoeffMatrix 为, 其中,x01 代表第0行,第1列的元素, 以此类推,以下的矩阵推导中都是用x表示的,只是为了写起来方便,实际上每次变换后,值都是改变的。
x00 x01 x02 x03 x04 x05 x06 x07
x10 x11 x12 x13 x14 x15 x16 x17
x20 x21 x22 x23 x24 x25 x26 x27
x30 x31 x32 x33 x34 x35 x36 x37
x40 x41 x42 x43 x44 x45 x46 x47
x50 x51 x52 x53 x54 x55 x56 x57
x60 x61 x62 x63 x64 x65 x66 x67
x70 x71 x72 x73 x74 x75 x76 x77
通过改变frame或者field的扫描矩阵改变CoeffMatrix 的存储方式,这样做是为了加载和计算时快捷,改变后如下,
x04 x00 x05 x01 x06 x02 x07 x03
x44 x40 x45 x41 x46 x42 x47 x43
x14 x10 x15 x11 x16 x12 x17 x13
x54 x50 x55 x51 x56 x52 x57 x53
x24 x20 x25 x21 x26 x22 x27 x23
x64 x60 x65 x61 x66 x62 x67 x63
x34 x30 x35 x31 x36 x32 x37 x33
x74 x70 x75 x71 x76 x72 x77 x73
对上面的矩阵0,1两行,2,3两行,4,5两行,6,7两行,同时进行行变换,之后进行饱和及压缩,存储, 得到的矩阵如下,
x40 x00 x50 x10 x60 x20 x70 x30
x41 x01 x51 x11 x61 x21 x71 x31
x42 x02 x52 x12 x62 x22 x72 x32
x43 x03 x53 x13 x63 x23 x73 x33
x44 x04 x54 x14 x64 x24 x74 x34
x45 x05 x55 x15 x65 x25 x75 x35
x46 x06 x56 x16 x66 x26 x76 x36
x47 x07 x57 x17 x67 x27 x77 x37
进行完上面的行变换后,进行列变换,上面矩阵的每一行,就是原来的要变换的列,而且也已经是按4 0 5 1 6 2 7 3的顺序排列的,同时对两行 进行变换,也就是原来的列变换,或者说是垂直变换也行。把变换后的值存储在原来的残差矩阵的对应位置,
x00 x01 x02 x03 x04 x05 x06 x07
x10 x11 x12 x13 x14 x15 x16 x17
x20 x21 x22 x23 x24 x25 x26 x27
x30 x31 x32 x33 x34 x35 x36 x37
x40 x41 x42 x43 x44 x45 x46 x47
x50 x51 x52 x53 x54 x55 x56 x57
x60 x61 x62 x63 x64 x65 x66 x67
x70 x71 x72 x73 x74 x75 x76 x77
通过以上变换方法,就实现了加载和存储全都是按整数进行的,并减少了原来要调整数据进行的_pack2和_packh2操作来。
用到的dsp内联指令有,_pack2, _packh2, _amemd8_const, _dotp2, _dotpn2, _spack2, _shr2等。
3, 按照上述想法,优化的代码如下
void idct_intrinsic_dsp(short* blk)
{
int i;
int x[4] , n[4] ;
int r[12], p[12];
int z[8] , m[8] ;
int t[8][4];
short* b = blk;
_nassert(((int)(blk) & 0x03) == 0);
for(i=0; i<4; i++, b+=16) // horizontal transform
{
// 取第0行的系数值,假定原始系数值是按 b[4] b[0] b[5] b[1] b[6] b[2] b[7] b[3] 排列的
// high | low
x[0] = _lo(_amemd8_const(b)); // b[0] b[4]
x[1] = _hi(_amemd8_const(b)); // b[1] b[5]
x[2] = _lo(_amemd8_const(b+4)); // b[2] b[6]
x[3] = _hi(_amemd8_const(b+4)); // b[3] b[7]
// 取第1行的系数值
n[0] = _lo(_amemd8_const(b+8)); // b[0] b[4]
n[1] = _hi(_amemd8_const(b+8)); // b[1] b[5]
n[2] = _lo(_amemd8_const(b+12));// b[2] b[6]
n[3] = _hi(_amemd8_const(b+12));// b[3] b[7]
r[0] = _dotp2 (0x080008, x[0]); // r[0] = 8 * x[0] + 8 * x[4]; // 0x080008
r[1] = _dotpn2(0x080008, x[0]); // r[1] = 8 * x[0] - 8 * x[4]; // 0x08fff8
r[2] = _dotp2 (0x0a0006, x[1]); // r[2] = 10 * x[1] + 6 * x[5]; // 0x0a0006
r[3] = _dotpn2(0x09000a, x[1]); // r[3] = 9 * x[1] - 10 * x[5]; // 0x09000a
r[4] = _dotp2 (0x060002, x[1]); // r[4] = 6 * x[1] + 2 * x[5]; // 0x060002
r[5] = _dotp2 (0x020009, x[1]); // r[5] = 2 * x[1] + 9 * x[5]; // 0x020009
r[6] = _dotp2 (0x0a0004, x[2]); // r[6] = 10 * x[2] + 4 * x[6]; // 0x0a0004
r[7] = _dotpn2(0x04000a, x[2]); // r[7] = 4 * x[2] - 10 * x[6]; // 0x04000a
r[8] = _dotp2 (0x090002, x[3]); // r[8] = 9 * x[3] + 2 * x[7]; // 0x090002
r[9] = _dotp2 (0x020006, x[3]); // r[9] = 2 * x[3] + 6 * x[7]; // 0x020006
r[10]= _dotpn2(0x0a0009, x[3]); // r[10]= 10 * x[3] - 9 * x[7]; // 0x0a0009
r[11]= _dotp2 (0x06000a, x[3]); // r[11]= 6 * x[3] + 10 * x[7]; // 0x06000a
p[0] = _dotp2 (0x080008, n[0]); // r[0] = 8 * x[0] + 8 * x[4]; // 0x080008
p[1] = _dotpn2(0x080008, n[0]); // r[1] = 8 * x[0] - 8 * x[4]; // 0x08fff8
p[2] = _dotp2 (0x0a0006, n[1]); // r[2] = 10 * x[1] + 6 * x[5]; // 0x0a0006
p[3] = _dotpn2(0x09000a, n[1]); // r[3] = 9 * x[1] - 10 * x[5]; // 0x09000a
p[4] = _dotp2 (0x060002, n[1]); // r[4] = 6 * x[1] + 2 * x[5]; // 0x060002
p[5] = _dotp2 (0x020009, n[1]); // r[5] = 2 * x[1] + 9 * x[5]; // 0x020009
p[6] = _dotp2 (0x0a0004, n[2]); // r[6] = 10 * x[2] + 4 * x[6]; // 0x0a0004
p[7] = _dotpn2(0x04000a, n[2]); // r[7] = 4 * x[2] - 10 * x[6]; // 0x04000a
p[8] = _dotp2 (0x090002, n[3]); // r[8] = 9 * x[3] + 2 * x[7]; // 0x090002
p[9] = _dotp2 (0x020006, n[3]); // r[9] = 2 * x[3] + 6 * x[7]; // 0x020006
p[10]= _dotpn2(0x0a0009, n[3]); // r[10]= 10 * x[3] - 9 * x[7]; // 0x0a0009
p[11]= _dotp2 (0x06000a, n[3]); // r[11]= 6 * x[3] + 10 * x[7]; // 0x06000a
z[0] = r[0] + r[6];
z[1] = r[2] + r[8];
z[2] = r[1] + r[7];
z[3] = r[3] - r[9];
z[4] = r[1] - r[7];
z[5] = r[4] - r[10];
z[6] = r[0] - r[6];
z[7] = r[5] - r[11];
m[0] = p[0] + p[6];
m[1] = p[2] + p[8];
m[2] = p[1] + p[7];
m[3] = p[3] - p[9];
m[4] = p[1] - p[7];
m[5] = p[4] - p[10];
m[6] = p[0] - p[6];
m[7] = p[5] - p[11];
// high | low
t[0][i] = _shr2(_spack2(z[0]+z[1]+4, m[0]+m[1]+4), 3); // x00 x40
t[1][i] = _shr2(_spack2(z[2]+z[3]+4, m[2]+m[3]+4), 3); // x01 x41
t[2][i] = _shr2(_spack2(z[4]+z[5]+4, m[4]+m[5]+4), 3); // x02 x42
t[3][i] = _shr2(_spack2(z[6]+z[7]+4, m[6]+m[7]+4), 3); // x03 x43
t[4][i] = _shr2(_spack2(z[6] -z[7]+4, m[6] -m[7]+4), 3); // x04 x44
t[5][i] = _shr2(_spack2(z[2] -z[3]+4, m[2] -m[3]+4), 3); // x05 x45
t[6][i] = _shr2(_spack2(z[4] -z[5]+4, m[4] -m[5]+4), 3); // x46 x46
t[7][i] = _shr2(_spack2(z[0] -z[1]+4, m[0] -m[1]+4), 3); // x47 x47
}
b = blk;
for(i=0; i<4; i++, b+=2) // horizontal transform
{
// 取第0行的系数值 // high | low
x[0] = _lo(_amemd8_const(&t[2*i+0][0])); // b[0] b[4]
x[1] = _hi(_amemd8_const(&t[2*i+0][0])); // b[1] b[5]
x[2] = _lo(_amemd8_const(&t[2*i+0][2])); // b[2] b[6]
x[3] = _hi(_amemd8_const(&t[2*i+0][2])); // b[3] b[7]
// 取第1行的系数值
n[0] = _lo(_amemd8_const(&t[2*i+1][0])); // b[0] b[4]
n[1] = _hi(_amemd8_const(&t[2*i+1][0])); // b[1] b[5]
n[2] = _lo(_amemd8_const(&t[2*i+1][2])); // b[2] b[6]
n[3] = _hi(_amemd8_const(&t[2*i+1][2])); // b[3] b[7]
r[0] = _dotp2 (0x080008, x[0]); // r[0] = 8 * x[0] + 8 * x[4]; // 0x080008
r[1] = _dotpn2(0x080008, x[0]); // r[1] = 8 * x[0] - 8 * x[4]; // 0x08fff8
r[2] = _dotp2 (0x0a0006, x[1]); // r[2] = 10 * x[1] + 6 * x[5]; // 0x0a0006
r[3] = _dotpn2(0x09000a, x[1]); // r[3] = 9 * x[1] - 10 * x[5]; // 0x09000a
r[4] = _dotp2 (0x060002, x[1]); // r[4] = 6 * x[1] + 2 * x[5]; // 0x060002
r[5] = _dotp2 (0x020009, x[1]); // r[5] = 2 * x[1] + 9 * x[5]; // 0x020009
r[6] = _dotp2 (0x0a0004, x[2]); // r[6] = 10 * x[2] + 4 * x[6]; // 0x0a0004
r[7] = _dotpn2(0x04000a, x[2]); // r[7] = 4 * x[2] - 10 * x[6]; // 0x04000a
r[8] = _dotp2 (0x090002, x[3]); // r[8] = 9 * x[3] + 2 * x[7]; // 0x090002
r[9] = _dotp2 (0x020006, x[3]); // r[9] = 2 * x[3] + 6 * x[7]; // 0x020006
r[10]= _dotpn2(0x0a0009, x[3]); // r[10]= 10 * x[3] - 9 * x[7]; // 0x0a0009
r[11]= _dotp2 (0x06000a, x[3]); // r[11]= 6 * x[3] + 10 * x[7]; // 0x06000a
p[0] = _dotp2 (0x080008, n[0]); // r[0] = 8 * x[0] + 8 * x[4]; // 0x080008
p[1] = _dotpn2(0x080008, n[0]); // r[1] = 8 * x[0] - 8 * x[4]; // 0x08fff8
p[2] = _dotp2 (0x0a0006, n[1]); // r[2] = 10 * x[1] + 6 * x[5]; // 0x0a0006
p[3] = _dotpn2(0x09000a, n[1]); // r[3] = 9 * x[1] - 10 * x[5]; // 0x09000a
p[4] = _dotp2 (0x060002, n[1]); // r[4] = 6 * x[1] + 2 * x[5]; // 0x060002
p[5] = _dotp2 (0x020009, n[1]); // r[5] = 2 * x[1] + 9 * x[5]; // 0x020009
p[6] = _dotp2 (0x0a0004, n[2]); // r[6] = 10 * x[2] + 4 * x[6]; // 0x0a0004
p[7] = _dotpn2(0x04000a, n[2]); // r[7] = 4 * x[2] - 10 * x[6]; // 0x04000a
p[8] = _dotp2 (0x090002, n[3]); // r[8] = 9 * x[3] + 2 * x[7]; // 0x090002
p[9] = _dotp2 (0x020006, n[3]); // r[9] = 2 * x[3] + 6 * x[7]; // 0x020006
p[10]= _dotpn2(0x0a0009, n[3]); // r[10]= 10 * x[3] - 9 * x[7]; // 0x0a0009
p[11]= _dotp2 (0x06000a, n[3]); // r[11]= 6 * x[3] + 10 * x[7]; // 0x06000a
z[0] = r[0] + r[6];
z[1] = r[2] + r[8];
z[2] = r[1] + r[7];
z[3] = r[3] - r[9];
z[4] = r[1] - r[7];
z[5] = r[4] - r[10];
z[6] = r[0] - r[6];
z[7] = r[5] - r[11];
m[0] = p[0] + p[6];
m[1] = p[2] + p[8];
m[2] = p[1] + p[7];
m[3] = p[3] - p[9];
m[4] = p[1] - p[7];
m[5] = p[4] - p[10];
m[6] = p[0] - p[6];
m[7] = p[5] - p[11];
_amem4(&b[0*8]) = _shr2(_spack2(m[0]+m[1]+64, z[0]+z[1]+64), 7); // x10 x00
_amem4(&b[1*8]) = _shr2(_spack2(m[2]+m[3]+64, z[2]+z[3]+64), 7); // x11 x01
_amem4(&b[2*8]) = _shr2(_spack2(m[4]+m[5]+64, z[4]+z[5]+64), 7); // x12 x02
_amem4(&b[3*8]) = _shr2(_spack2(m[6]+m[7]+64, z[6]+z[7]+64), 7); // x13 x03
_amem4(&b[4*8]) = _shr2(_spack2(m[6]- m[7]+64, z[6]-z[7]+64), 7); // x14 x04
_amem4(&b[5*8]) = _shr2(_spack2(m[4]- m[5]+64, z[4]-z[5]+64), 7); // x15 x05
_amem4(&b[6*8]) = _shr2(_spack2(m[2]- m[3]+64, z[2]-z[3]+64), 7); // x16 x06
_amem4(&b[7*8]) = _shr2(_spack2(m[0]- m[1]+64, z[0]-z[1]+64), 7); // x17 x07
}
}
五,结果对比
优化效果显著!!!
望对dsp优化有经验的的大侠多多指点,看看有没有更好的方法进行优化,及代码写法方面的问题。
刘春龙:欢迎转载!
- 在TI 的DSP 平台下优化AVS 的 IDCT 反变换的方法和代码
- AVS解码器在DSP平台上的优化
- AVS解码器在DSP平台上的优化
- 关于T264代码中IDCT模块在DSP上的汇编优化
- [DSP(TI)]dm642的优化
- [DSP(TI)]dm642的优化
- neon优化h264的idct 代码
- 基于SIMD的AVS整数反变换算法设计与优化
- TI DM64x/C64x的代码优化方法
- TI DM64x/C64x的代码优化方法
- 高速率AVS整数变换的汇编实现与优化
- AVS游程解码、反扫描、反量化和反变换优化设计
- TI DSP--内存空间的分配和指定
- 基于DSP平台的音视频编解码C代码优化方法
- 基于DSP平台的音视频编解码C代码优化方法
- 搭建Matlab/Simulink下针对TI的DSP的代码自动生成环境
- TI ARM和DSP双核平台的一个编译例程
- AVS软件解码器的优化
- 哈哈,终于在bboss aop中实现了rpc(远程服务调用)功能,
- 最差的产品是马桶还是Outlook
- C语言例题20:
- C语言例题21:
- C语言例题22:
- 在TI 的DSP 平台下优化AVS 的 IDCT 反变换的方法和代码
- C语言例题23:
- C语言例题24:
- javascript刷新本页
- C语言例题25:
- 采用DC画比例尺
- 执行力差到底是谁的责任
- 关于cookie
- Windows XP下QT4的安装与环境变量设置(详细)