【编解码】视频编解码--关键帧压缩编解码
【现场实操追-女孩视频】【Q/Q:⒈016.x.952б】 一、编码
?将原始图像数据分块为8*8大小,并将RGB三通道数据分离。由于DCT的数据范围是-128~+127,而RGB的数据范围是0~255,所以这里分块时就先将RGB各通道值减去128。
?将所有8*8的数据块做DCT。8*8的二维数据经过DCT之后,就得到了8*8的变换系数矩阵,其中(0,0)元素是直流分量或称DC系数,剩下的63个元素是交流分量或称AC系数。DCT变换后的8*8系数矩阵中,低频分量集中在矩阵的左上角,高频成分集中在右下角。高频分量一般是可丢弃的信息。
?由于DCT的乘加次数多,计算量大,所以在计算中一般要采用快速离散余弦变换。
3. Zigzag扫描和量化
?DCT之后结合量化丢弃右下角的高频信息,可以得到很多0,这在后面的各种熵编码会得到很大的压缩。但是8*8的数据是一行一行线性存放的,每一行的结尾点和下一行的开始点没有联系。如果按照下图的顺序存储数据,则前一行的结尾点和下一行的开始点就建立了联系。
代码中按照下表读取DCT之后的系数矩阵就可以完成Zigzag扫描。 const static uchar FZBT[64] = 0, 1, 5, 6, 14,15,27,28, 2, 4, 7, 13,16,26,29,42,
3, 8, 12,17,25,30,41,43, 9, 11,18,24,31,40,44,53, 10,19,23,32,39,45,52,54, 20,22,33,38,46,51,55,60, 21,34,37,47,50,56,59,61, 35,36,48,49,57,58,62,63
JPEG处理YUV数据时,Y通道和UV通道使用各自的标准量化表。YUV格式的数据Y通道亮度数据比较重要,所以在此处理RGB格式数据时三通道均采用JPEG的标准亮度信号量化模板std_Y_QT,如下:
const static uchar std_Y_QT[64] = 16, 11, 10, 16, 24, 40, 51, 61, 12, 12, 14, 19, 26, 58, 60, 55, 14, 13, 16, 24, 40, 57, 69, 56, 14, 17, 22, 29, 51, 87, 80, 62, 18, 22, 37, 56, 68, 109,103,77, 24, 35, 55, 64, 81, 104,113,92, 49, 64, 78, 87, 103,121,120,101, 72, 92, 95, 98, 112,100,103,99
实际上可以将ZigZag扫描与量化合成一步完成。以Z表的值做为量化后存储数据的下标索引即可。
4. 游程编码
?游程编码属于无损压缩编码,对二指图像非常有效,编解码都很简单。
?游程编码的原理:?用一个符号值或串长代替具有相同值的连续符号,使符号长度少于原始数据长度。
?例如:5555557777733322221111111
?经过游程编码后的序列为:(5,6)(7,5)(3,3)(2,4)(1,7)。 ?由于我们的数据经过前期处理之后,63个AC系数产生了很0,为更有效的压缩数据,这里采用一种稍加变化的游程编码。JPEG中这样定义:
?假设RLE编码之后得到了一个(M,N)的数据对,其中M表示两个非零的AC系数之间0的个数,N表示的是下一个非零的AC系数值。
?例如:57,45,0,0,0,0,23,0,-30,-8,0,0,1,000. ?
编
码
之
后
:
(0,57)?;?(0,45)?;?(4,23)?;?(1,-30)?;?(0,-8)?;?(2,1)?;?(0,0)
?同样,如果连0个数超过16个,就要用一个扩展字节(15,0)来表示16个连续的0。
5. Huffman编码
?本文使用JPEG标准DC_Y和AC_Y霍夫曼表。具体步骤参见霍夫曼编解码。
需要说明的是DC系数采用DC_Y表,AC系数采用AC_Y表。 ?1)DC系数编码
?由于DC系数值较大,但相邻两个8*8数据块的DC值差异较小,所以DC系数先做差分,差分值再进行Huffman编码。
?2)AC系数编码
?63个AC系数直接使用AC_Y表进行熵编码。
二、解码
1. 二进制码流解码
?具体步骤参见霍夫曼编解码。 2. 反量化和反ZigZag编码
?根据量化时的计算公式反解,使用的量化表需和量化时使用的一致。 ?反DCT的计算方式需和DCT的计算方式一致。 4. 恢复数据
?1)关键帧:将最后反DCT得到的值加上128,即得到解码出的图像数据值。
func testEncode(in []uint64) { 12, 12, 14, 19, 26, 58, 60, 55,
我们用第一位表示符号(0为非负数,1为负数),剩下的位,非负数保持不变,负数按位求反。比如:
在H.264中,每个4?4块中的每个像素都可用17个最接近先前已编码的像素的不同加权和来进行帧内预测。
f(i, j)经DCT变换之后,F(0,0)是直流系数,其他为交流系数。 ? for (int i = 0; i max_size; i++, offset += 7)
unsigned char* ptr = reinterpret_castunsigned char*(dst); added.It is true \String\after getting rid of these redundant characters.Java Code
?ByteArrayOutputStream baos = new ByteArrayOutputStream(); 0的ZigZag编码还是0,对应的二进制为0000 0001,故对应Varint
编码还是0000 0001,1字节;