x265中dct8函数的向量实现

摘要

上一篇文章已经基本讲明DCT系列函数的实现原理,同尺寸的IDCT(DCT反变换)、DST(离散正弦变换)、IDST的实现方法基本相同。本篇文章将要讲述8x8矩阵DCT变换的向量实现。原理类似,但仅仅因为尺寸扩展为8x8,导致数据的构造方式完全不同,而且变换系数的规律的不同也对其造成一定的影响。本文将详细描述其数据构造方式。

正文

原理

8x8的变换系数矩阵为 。

[ 64 64 64 64 64 64 64 64 89 75 50 18 − 18 − 50 − 75 − 89 83 36 − 36 − 83 − 83 − 36 36 83 75 − 18 − 89 − 50 50 89 18 − 75 64 − 64 − 64 64 64 − 64 − 64 64 50 − 89 18 75 − 75 − 18 89 − 50 36 − 83 83 − 36 − 36 83 − 83 36 18 − 50 75 − 89 89 − 75 50 − 18 ] \begin{bmatrix} 64&64&64&64&64&64&64&64\\ 89&75&50&18&-18&-50&-75&-89\\ 83&36&-36&-83&-83&-36&36&83\\ 75&-18&-89&-50&50&89&18&-75\\ 64&-64&-64&64&64&-64&-64&64\\ 50&-89&18&75&-75&-18&89&-50\\ 36&-83&83&-36&-36&83&-83&36\\ 18&-50&75&-89&89&-75&50&-18\\ \end{bmatrix} 64898375645036186475361864898350645036896418837564188350647536896418835064753689645036896418837564753618648983506489837564503618

变换公式就不列出来了,仍以行变换为例。观察该变换系数的规律,它的奇数行和偶数行的规律还存在差异。首先来看偶数行(第一行为 r o w 0 row0 row0),其计算公式可以简化为下式。

64 ∗ ( r o w 0 + r o w 7 + r o w 3 + r o w 4 ) + 64 ∗ ( r o w 1 + r o w 6 + r o w 2 + r o w 5 ) 64*(row0+row7+row3+row4)+64*(row1+row6+row2+row5) 64(row0+row7+row3+row4)+64(row1+row6+row2+row5)
83 ∗ ( r o w 0 + r o w 7 − r o w 3 − r o w 4 ) + 36 ∗ ( r o w 1 + r o w 6 − r o w 2 − r o w 5 ) 83*(row0+row7-row3-row4)+36*(row1+row6-row2-row5) 83(row0+row7row3row4)+36(row1+row6row2row5)
64 ∗ ( r o w 0 + r o w 7 + r o w 3 + r o w 4 ) − 64 ∗ ( r o w 1 + r o w 6 + r o w 2 + r o w 5 ) 64*(row0+row7+row3+row4)-64*(row1+row6+row2+row5) 64(row0+row7+row3+row4)64(row1+row6+row2+row5)
36 ∗ ( r o w 0 + r o w 7 − r o w 3 − r o w 4 ) − 83 ∗ ( r o w 1 + r o w 6 − r o w 2 − r o w 5 ) 36*(row0+row7-row3-row4)-83*(row1+row6-row2-row5) 36(row0+row7row3row4)83(row1+row6row2row5)

分两个步骤就是首先得到括号内的四种数据加减组合。其次完成括号外的乘法加减操作。

然后是奇数行,计算公式如下。

89 ∗ ( r o w 0 − 7 ) + 75 ∗ ( r o w 1 − 6 ) + 50 ∗ ( r o w 2 − 5 ) + 18 ∗ ( r o w 3 − 4 ) 89*(row0-7)+75*(row1-6)+50*(row2-5)+18*(row3-4) 89(row07)+75(row16)+50(row25)+18(row34)
75 ∗ ( r o w 0 − 7 ) − 18 ∗ ( r o w 1 − 6 ) − 89 ∗ ( r o w 2 − 5 ) − 50 ∗ ( r o w 3 − 4 ) 75*(row0-7)-18*(row1-6)-89*(row2-5)-50*(row3-4) 75(row07)18(row16)89(row25)50(row34)
50 ∗ ( r o w 0 − 7 ) − 89 ∗ ( r o w 1 − 6 ) + 18 ∗ ( r o w 2 − 5 ) + 75 ∗ ( r o w 3 − 4 ) 50*(row0-7)-89*(row1-6)+18*(row2-5)+75*(row3-4) 50(row07)89(row16)+18(row25)+75(row34)
18 ∗ ( r o w 0 − 7 ) − 50 ∗ ( r o w 1 − 6 ) + 75 ∗ ( r o w 2 − 5 ) − 89 ∗ ( r o w 3 − 4 ) 18*(row0-7)-50*(row1-6)+75*(row2-5)-89*(row3-4) 18(row07)50(row16)+75(row25)89(row34)

同样分两个步骤,首先得到括号内的,其次是括号外的操作。下文的实现就是以上述公式为基础,构造数据格式。

实现
行变换

在具体的实现中,对于奇数行和偶数行的变换系数,采用不同的处理过程,两者是分开处理的。下文也将分开讲述,但首先先讲明起始共用的处理过程。

首先使用ld指令获取所有原始数据。数据表示方法与上文相同。得到数据

{ r o w n [ c o l 7 , c o l 6 , c o l 5 , c o l 4 , c o l 3 , c o l 2 , c o l 1 , c o l 0 ] } \{row_n[col7, col6, col5, col4, col3, col2, col1,col0]\} {rown[col7,col6,col5,col4,col3,col2,col1,col0]}

然后使用ilvrilvl交错指令,以16位为交错单位,将相邻两行交错,拿第一行和第二行举例,得到

{ c o l 3 [ r o w 1 , r o w 0 ] , c o l 2 [ r o w 1 , r o w 0 ] , c o l 1 [ r o w 1 , r o w 0 ] , c o l 0 [ r o w 1 , r o w 0 ] } \{col3[row1, row0], col2[row1, row0], col1[row1, row0], col0[row1, row0]\} {col3[row1,row0],col2[row1,row0],col1[row1,row0],col0[row1,row0]}
{ c o l 7 [ r o w 1 , r o w 0 ] , c o l 6 [ r o w 1 , r o w 0 ] , c o l 5 [ r o w 1 , r o w 0 ] , c o l 4 [ r o w 1 , r o w 0 ] } \{col7[row1, row0], col6[row1, row0], col5[row1, row0], col4[row1, row0]\} {col7[row1,row0],col6[row1,row0],col5[row1,row0],col4[row1,row0]}

然后再将两行的交错结果与相邻两行的交错结果继续交错,指令相同,但以32位为交错单位。拿第一二行和三四行作为例子,得到

{ c o l 1 [ r o w 3 , r o w 2 , r o w 1 , r o w 0 ] , c o l 0 [ r o w 3 , r o w 2 , r o w 1 , r o w 0 ] } \{col1[row3, row2, row1, row0], col0[row3, row2, row1, row0]\} {col1[row3,row2,row1,row0],col0[row3,row2,row1,row0]}
{ c o l 3 [ r o w 3 , r o w 2 , r o w 1 , r o w 0 ] , c o l 2 [ r o w 3 , r o w 2 , r o w 1 , r o w 0 ] } \{col3[row3, row2, row1, row0], col2[row3, row2, row1, row0]\} {col3[row3,row2,row1,row0],col2[row3,row2,row1,row0]}

{ c o l 5 [ r o w 3 , r o w 2 , r o w 1 , r o w 0 ] , c o l 4 [ r o w 3 , r o w 2 , r o w 1 , r o w 0 ] } \{col5[row3, row2, row1, row0], col4[row3, row2, row1, row0]\} {col5[row3,row2,row1,row0],col4[row3,row2,row1,row0]}
{ c o l 7 [ r o w 3 , r o w 2 , r o w 1 , r o w 0 ] , c o l 6 [ r o w 3 , r o w 2 , r o w 1 , r o w 0 ] } \{col7[row3, row2, row1, row0], col6[row3, row2, row1, row0]\} {col7[row3,row2,row1,row0],col6[row3,row2,row1,row0]}

然后使用shf混洗指令,将第二个和第三个寄存器中,高低64位置换。目的是为了将col0col7对齐、col1col6对齐、2和5、还有3和4。得到

{ c o l 4 [ r o w 3 , r o w 2 , r o w 1 , r o w 0 ] , c o l 5 [ r o w 3 , r o w 2 , r o w 1 , r o w 0 ] } \{col4[row3, row2, row1, row0], col5[row3, row2, row1, row0]\} {col4[row3,row2,row1,row0],col5[row3,row2,row1,row0]}
{ c o l 6 [ r o w 3 , r o w 2 , r o w 1 , r o w 0 ] , c o l 7 [ r o w 3 , r o w 2 , r o w 1 , r o w 0 ] } \{col6[row3, row2, row1, row0], col7[row3, row2, row1, row0]\} {col6[row3,row2,row1,row0],col7[row3,row2,row1,row0]}

到此,第一步的数据格式构造完毕,后续将开始进行加减操作。而为什么需要构造出这样的一种格式,有几点需要说明。首先是我们要进行行变换,需要一行中不同元素的加减操作,这在单个寄存器中是无法完成的。因此我们需要将一行中需要加减的元素置于两个寄存器的对应位置。也就得到上述的以col打头的数据格式。其次是为什么以四行为一个单位进行操作。因为对于奇数行的操作,单行中有四个不同的乘系数。因此在做乘法之前,只需要给每一行提供四个单位的存储空间,并行度和寄存器使用率的平衡点就在于此。以四行为单位进行交错,就可以得到该平衡点。

开始加减操作,使用subvaddv指令,完成向量加减操作,得到。

{ ( c o l 1 + c o l 6 ) [ r o w 3 , r o w 2 , r o w 1 , r o w 0 ] , ( c o l 0 + c o l 7 ) [ . . . ] } \{(col1+col6)[row3, row2, row1,row0], (col0+col7)[...]\} {(col1+col6)[row3,row2,row1,row0],(col0+col7)[...]}
{ ( c o l 3 + c o l 4 ) [ . . . ] , ( c o l 2 + c o l 5 ) [ . . . ] } \{(col3+col4)[...], (col2+col5)[...]\} {(col3+col4)[...],(col2+col5)[...]}

{ ( c o l 1 − c o l 6 ) [ . . . ] , ( c o l 0 − c o l 7 ) [ . . . ] } \{(col1-col6)[...], (col0-col7)[...]\} {(col1col6)[...],(col0col7)[...]}
{ ( c o l 3 − c o l 4 ) [ . . . ] , ( c o l 2 − c o l 5 ) [ . . . ] } \{(col3-col4)[...], (col2-col5)[...]\} {(col3col4)[...],(col2col5)[...]}

此处就是分歧点,对于奇数行和偶数行变换系数,分别开始进行不同的操作。

奇数行

对于奇数行的变换系数,目前已经得到了第一步的计算结果,之后将进行第二步的乘法加减操作。为方便使用dotp点乘指令,需要变更一下数据格式。使用ilvlilvr交错指令,仍以前四行的处理作为例子,得到。

{ r o w 3 [ c o l 2 − c o l 5 , c o l 0 − c o l 7 ] , r o w 2 [ . . . ] , r o w 1 [ . . . ] , r o w 0 [ . . . ] } \{row3[col2-col5, col0-col7], row2[...], row1[...], row0[...] \} {row3[col2col5,col0col7],row2[...],row1[...],row0[...]}
{ r o w 3 [ c o l 3 − c o l 4 , c o l 1 − c o l 6 ] , r o w 2 [ . . . ] , r o w 1 [ . . . ] , r o w 0 [ . . . ] } \{row3[col3-col4, col1-col6], row2[...], row1[...], row0[...] \} {row3[col3col4,col1col6],row2[...],row1[...],row0[...]}

然后使用dotp指令与常数向量点乘,对应位置相乘,相邻位置求和。常数向量以第一行为例,表明其构造方式。构造出两个寄存器,分别是。

{ 50 , 89 , 50 , 89 , 50 , 89 , 50 , 89 } \{50,89,50,89,50,89,50,89\} {50,89,50,89,50,89,50,89}
{ 18 , 75 , 18 , 75 , 18 , 75 , 18 , 75 } \{18,75,18,75,18,75,18,75\} {18,75,18,75,18,75,18,75}

点乘得到

{ r o w 3 [ 50 ∗ ( c o l 2 − c o l 5 ) + 89 ∗ ( c o l 0 − c o l 7 ) ] , r o w 2 [ . . . ] , r o w 1 [ . . . ] , r o w 0 [ . . . ] } \{row3[50*(col2-col5)+89*(col0-col7)],row2[...], row1[...], row0[...] \} {row3[50(col2col5)+89(col0col7)],row2[...],row1[...],row0[...]}
{ r o w 3 [ 18 ∗ ( c o l 3 − c o l 4 ) + 75 ∗ ( c o l 1 − c o l 6 ) ] , r o w 2 [ . . . ] , r o w 1 [ . . . ] , r o w 0 [ . . . ] } \{row3[18*(col3-col4)+75*(col1-col6)],row2[...], row1[...], row0[...] \} {row3[18(col3col4)+75(col1col6)],row2[...],row1[...],row0[...]}

使用addv向量求和指令得到。

{ r o w 3 [ 50 ∗ ( c o l 2 − c o l 5 ) + 89 ∗ ( c o l 0 − c o l 7 ) + 18 ∗ ( c o l 3 − c o l 4 ) + 75 ∗ ( c o l 1 − c o l 6 ) ] , r o w 2 [ . . . ] , r o w 1 [ . . . ] , r o w 0 [ . . . ] } \{row3[50*(col2-col5)+89*(col0-col7)+18*(col3-col4)+75*(col1-col6)],row2[...], row1[...], row0[...] \} {row3[50(col2col5)+89(col0col7)+18(col3col4)+75(col1col6)],row2[...],row1[...],row0[...]}

当前得到的就是经过行变换后,得到的第一列(奇数)的前四个元素。对于其他的元素只是所使用的变换系数和原始数据不同, 处理过程完全相同。对应关系是,后四行的原始数据对应行变换后列的后四个元素,使用不同行的变换系数对应变换后不同的列。

偶数行

起始数据是

{ ( c o l 1 + c o l 6 ) [ r o w 3 , r o w 2 , r o w 1 , r o w 0 ] , ( c o l 0 + c o l 7 ) [ . . . ] } \{(col1+col6)[row3, row2, row1,row0], (col0+col7)[...]\} {(col1+col6)[row3,row2,row1,row0],(col0+col7)[...]}
{ ( c o l 3 + c o l 4 ) [ . . . ] , ( c o l 2 + c o l 5 ) [ . . . ] } \{(col3+col4)[...], (col2+col5)[...]\} {(col3+col4)[...],(col2+col5)[...]}

为完成第一步骤的操作,还需要继续加减操作,首先将 ( c o l 0 + c o l 7 ) (col0+col7) (col0+col7) ( c o l 3 + c o l 4 ) (col3+col4) (col3+col4) ( c o l 1 + c o l 6 ) (col1+col6) (col1+col6) ( c o l 2 + c o l 5 ) (col2+col5) (col2+col5)对齐。使用shf混洗指令,置换第二个寄存器的高低64位。得到

{ ( c o l 2 + c o l 5 ) [ r o w 3 , r o w 2 , r o w 1 , r o w 0 ] , ( c o l 3 + c o l 4 ) [ . . . ] } \{(col2+col5)[row3, row2, row1,row0], (col3+col4)[...]\} {(col2+col5)[row3,row2,row1,row0],(col3+col4)[...]}

然后使用addvsubv指令进行加减操作。得到

{ ( c o l 1 + c o l 6 + c o l 2 + c o l 5 ) [ . . . ] , ( c o l 0 + c o l 7 + c o l 3 + c o l 4 ) [ . . . ] } \{(col1+col6+col2+col5)[...], (col0+col7+col3+col4)[...]\} {(col1+col6+col2+col5)[...],(col0+col7+col3+col4)[...]}
{ ( c o l 1 + c o l 6 − c o l 2 − c o l 5 ) [ . . . ] , ( c o l 0 + c o l 7 − c o l 3 − c o l 4 ) [ . . . ] } \{(col1+col6-col2-col5)[...], (col0+col7-col3-col4)[...]\} {(col1+col6col2col5)[...],(col0+col7col3col4)[...]}

至此已经完成了第一步骤的操作,后续进行乘法加减操作。但要使用dotp点乘指令,需要将同行的数据放置于寄存器的相邻位置。使用混洗指令,shf 32位基本单位混洗,然后16位基本单位混洗得到。

t m p 1 = { r o w 3 [ c o l 1 + c o l 6 + c o l 2 + c o l 5 , c o l 0 + c o l 7 + c o l 3 + c o l 4 ] , r o w 2 [ . . . ] , r o w 1 [ . . . ] , r o w 0 [ . . . ] } tmp1 = \{row3[col1+col6+col2+col5, col0+col7+col3+col4], row2[...], row1[...], row0[...]\} tmp1={row3[col1+col6+col2+col5,col0+col7+col3+col4],row2[...],row1[...],row0[...]}

t m p 2 = { r o w 3 [ c o l 1 + c o l 6 − c o l 2 − c o l 5 , c o l 0 + c o l 7 − c o l 3 − c o l 4 ] , r o w 2 [ . . . ] , r o w 1 [ . . . ] , r o w 0 [ . . . ] } tmp2 = \{row3[col1+col6-col2-col5, col0+col7-col3-col4], row2[...], row1[...], row0[...]\} tmp2={row3[col1+col6col2col5,col0+col7col3col4],row2[...],row1[...],row0[...]}

这里要用到四个常量,分别表示变换系数偶数行的4行系数,分别是

c o n 1 = { 64 , 64 , 64 , 64 , 64 , 64 , 64 , 64 } con1 = \{64,64,64,64,64,64,64,64\} con1={64,64,64,64,64,64,64,64}
c o n 2 = { 36 , 83 , 36 , 83 , 36 , 83 , 36 , 83 } con2 = \{36, 83, 36, 83, 36, 83, 36, 83\} con2={36,83,36,83,36,83,36,83}
c o n 3 = { 64 , − 64 , 64 , − 64 , 64 , − 64 , 64 , − 64 } con3 = \{64, -64, 64, -64, 64, -64, 64, -64\} con3={64,64,64,64,64,64,64,64}
c o n 4 = { − 83 , 36 , − 83 , 36 , − 83 , 36 , − 83 , 36 } con4 = \{-83, 36, -83, 36, -83, 36, -83, 36\} con4={83,36,83,36,83,36,83,36}

t m p 1 tmp1 tmp1 c o n 1 con1 con1点乘,得到第零列(偶数顺序)、 t m p 2 tmp2 tmp2 c o n 2 con2 con2点乘,得到第二列、 t m p 1 tmp1 tmp1 c o n 3 con3 con3点乘,得到第四列、 t m p 2 tmp2 tmp2 c o n 4 con4 con4点乘,得到第六列。且都是前四个元素。至此完成了行变换。

列变换

dct8函数的列变换不同于dct4函数的实现,dct4是直接进行和行变换相同的过程。但这对于dct8函数是无法实现的。因为经过行变换后,得到的临时数据占用了16个寄存器。后续如果采用同等并行度进行计算,必定导致寄存器过载,出现大量的堆栈操作,这显然是不被允许的。但这种实现方法也会导致最后得到的数据是以列的形式呈现的,也就是说最后的访存是以步长为间隔进行访问,访存空间局部性差,该问题仍需要进行权衡。

因此当前过程需要降低并行度。但一旦降低,整个过程就完全不同于行变换。大致思想是,先完成部分原始数据的变换。当前权衡得到的是以两列元素为单位进行列变换,过程中得到结果直接保存。以第一列和第二列为例,进行详细说明。

首先来看列变换的初始数据格式。有四个寄存器,其中数据都为32位。

{ c o l 0 [ r o w 3 , r o w 2 , r o w 1 , r o w 0 ] } \{col0[row3, row2, row1, row0]\} {col0[row3,row2,row1,row0]}
{ c o l 0 [ r o w 4 , r o w 5 , r o w 6 , r o w 7 ] } \{col0[row4, row5, row6, row7]\} {col0[row4,row5,row6,row7]}

{ c o l 1 [ r o w 3 , r o w 2 , r o w 1 , r o w 0 ] } \{col1[row3, row2, row1, row0]\} {col1[row3,row2,row1,row0]}
{ c o l 1 [ r o w 4 , r o w 5 , r o w 6 , r o w 7 ] } \{col1[row4, row5, row6, row7]\} {col1[row4,row5,row6,row7]}

然后使用addvsubv指令,完成变换第一步骤的操作。得到

{ c o l 0 [ r o w 3 + r o w 4 , r o w 2 + r o w 5 , r o w 1 + r o w 6 , r o w 0 + r o w 7 ] } \{col0[row3+row4, row2+row5, row1+row6, row0+row7]\} {col0[row3+row4,row2+row5,row1+row6,row0+row7]}
{ c o l 0 [ r o w 3 − r o w 4 , r o w 2 − r o w 5 , r o w 1 − r o w 6 , r o w 0 − r o w 7 ] } \{col0[row3-row4, row2-row5, row1-row6, row0-row7]\} {col0[row3row4,row2row5,row1row6,row0row7]}

{ c o l 1 [ r o w 3 + r o w 4 , r o w 2 + r o w 5 , r o w 1 + r o w 6 , r o w 0 + r o w 7 ] } \{col1[row3+row4, row2+row5, row1+row6, row0+row7]\} {col1[row3+row4,row2+row5,row1+row6,row0+row7]}
{ c o l 1 [ r o w 3 − r o w 4 , r o w 2 − r o w 5 , r o w 1 − r o w 6 , r o w 0 − r o w 7 ] } \{col1[row3-row4, row2-row5, row1-row6, row0-row7]\} {col1[row3row4,row2row5,row1row6,row0row7]}

列变换中,仍然需要将奇偶行的变换系数分开处理,并且此处就是分歧点。

奇数行

对于奇数行的变换系数,当前已经完成了第一步骤的操作。后续使用dotp点乘指令,完成第二步操作。这里需要四个常量寄存器,表示奇数行的变换系数。以第一行作为例子。

{ 18 , 50 , 75 , 89 } \{18,50,75,89\} {18,50,75,89}

数据宽度为32位,其实就是奇数行变换系数的前四个元素。然后使用dotppckev的指令组合,完成点乘以及组合的操作。得到

{ c o l 1 [ 18 ∗ ( r o w 3 − r o w 4 ) + 50 ∗ ( r o w 2 − r o w 5 ) , 75 ∗ ( r o w 1 − r o w 6 ) + 89 ∗ ( r o w 0 − r o w 7 ) ] , c o l 0 [ . . . ] } \{col1[18*(row3-row4)+50*(row2-row5), 75*(row1-row6)+89*(row0-row7)], col0[...]\} {col1[18(row3row4)+50(row2row5),75(row1row6)+89(row0row7)],col0[...]}

然后使用hadd横向加指令,得到

{ c o l 1 [ 18 ∗ ( r o w 3 − r o w 4 ) + 50 ∗ ( r o w 2 − r o w 5 ) + 75 ∗ ( r o w 1 − r o w 6 ) + 89 ∗ ( r o w 0 − r o w 7 ) ] , c o l 0 [ . . . ] } \{col1[18*(row3-row4)+50*(row2-row5)+75*(row1-row6)+89*(row0-row7)], col0[...]\} {col1[18(row3row4)+50(row2row5)+75(row1row6)+89(row0row7)],col0[...]}

当前得到了变换部分最终数据,为第一行的第零和第一个元素,然后在特定位置存入数据即可。

偶数行

需要继续完成第一步骤的操作,首先需要混洗,将使用相同变换系数的数据置于寄存器的相邻位置, 且需要构造适合横向减法操作的数据结构。得到

{ c o l 0 [ r o w 0 + r o w 7 , r o w 3 + r o w 4 , r o w 1 + r o w 6 , r o w 2 + r o w 5 ] } \{col0[row0+row7,row3+row4, row1+row6,row2+row5]\} {col0[row0+row7,row3+row4,row1+row6,row2+row5]}
{ c o l 1 [ r o w 0 + r o w 7 , r o w 3 + r o w 4 , r o w 1 + r o w 6 , r o w 2 + r o w 5 ] } \{col1[row0+row7,row3+row4, row1+row6,row2+row5]\} {col1[row0+row7,row3+row4,row1+row6,row2+row5]}

然后使用haddhsubpckev指令,横向加减,然后寄存器组合。得到

{ c o l 1 [ r o w 0 + r o w 7 + r o w 3 + r o w 4 , r o w 1 + r o w 6 + r o w 2 + r o w 5 ] , c o l 0 [ . . ] } \{col1[row0+row7+row3+row4, row1+row6+row2+row5],col0[..]\} {col1[row0+row7+row3+row4,row1+row6+row2+row5],col0[..]}
{ c o l 1 [ r o w 0 + r o w 7 − r o w 3 − r o w 4 , r o w 1 + r o w 6 − r o w 2 − r o w 5 ] , c o l 0 [ . . ] } \{col1[row0+row7-row3-row4, row1+row6-row2-row5],col0[..]\} {col1[row0+row7row3row4,row1+row6row2row5],col0[..]}

然后使用dotp指令,所使用的常量那第二、六行变换系数为例, 表示其结构。

{ 83 , 36 , 83 , 36 } \{83,36,83,36\} {83,36,83,36}
{ 36 , − 83 , 36 , − 83 } \{36,-83,36,-83\} {36,83,36,83}

每个数据宽度是32位,其实就是每行的前两个变换系数的组合。点乘得到结果。

{ c o l 1 [ 83 ∗ ( r o w 0 + r o w 7 − r o w 3 − r o w 4 ) + 36 ∗ ( r o w 1 + r o w 6 − r o w 2 − r o w 5 ) ] , c o l 0 [ . . ] } \{col1[83*(row0+row7-row3-row4)+36*(row1+row6-row2-row5)],col0[..]\} {col1[83(row0+row7row3row4)+36(row1+row6row2row5)],col0[..]}
{ c o l 1 [ 36 ∗ ( r o w 0 + r o w 7 − r o w 3 − r o w 4 ) − 83 ∗ ( r o w 1 + r o w 6 − r o w 2 − r o w 5 ) ] , c o l 0 [ . . ] } \{col1[36*(row0+row7-row3-row4)-83*(row1+row6-row2-row5)],col0[..]\} {col1[36(row0+row7row3row4)83(row1+row6row2row5)],col0[..]}

分别是变换后最终数据中的第二行前两个元素和第六行前两个元素,特定位置保存。以上内容就是整个dct8函数的实现过程。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值