|
14.2.1 MPEG-4编/解码设计与剖析(5)
③ Intra宏块变换、量化/反量化、反变换
图像Intra块的变换与量化一般是放置在一起的。变换采用离散余弦变换(DCT),量化采用H.263的均匀量化。并且量化采取的是查表、移位的方式,从而避免了除法。实现该功能的函数是MBTransQuantIntra(),其代码如下。
void MBTransQuantIntra(const MBParam * const pParam, const FRAMEINFO * const frame, MACROBLOCK * const pMB, const uint32_t x_pos, const uint32_t y_pos, int16_t data[6 * 64], int16_t qcoeff[6 * 64]) { /* 从图像空间读取宏块数据,并做16位扩展 */ MBTrans8to16(pParam, frame, pMB, x_pos, y_pos, data); /* 宏块做DCT变换 */ MBfDCT(pParam, frame, pMB, x_pos, y_pos, data); /* 宏块DCT系数做量化 */ MBQuantIntra(pParam, frame, pMB, data, qcoeff); /* 宏块DCT系数做反量化 */ MBDeQuantIntra(pParam, pMB->quant, data, qcoeff); /* 宏块做IDCT变换 */ MBiDCT(data, 0x3F); /* 把重建的宏块更新到当前编码帧,直接复制*/ MBTrans16to8(pParam, frame, pMB, x_pos, y_pos, data, 0, 0x3F); }
|
上述程序实现宏块(包括一个16 16的亮度块,两个8 8的色度块)的变换与量化处理。首先扩展图像为16位,为DCT做数据源,接着做变换和量化。最后为保证与解码图像一致,做反DCT和反量化,将这些重建值更新到编码图像。
④ Inter宏块变换、量化/反量化、反变换
Inter块的处理与Intra块基本相同,只是根据CBP编码模式决定哪些块的重建值更新编码图像。实现函数为MBTransQuantInter(),其代码实现如下。
uint8_t MBTransQuantInter(const MBParam * const pParam, const FRAMEINFO * const frame, MACROBLOCK * const pMB, const uint32_t x_pos,const uint32_t y_pos, int16_t data[6 * 64], int16_t qcoeff[6 * 64]) { uint8_t cbp; /* MC中已经做了减法,得到了图像差值 */ /* 宏块DCT */ MBfDCT(pParam, frame, pMB, x_pos, y_pos, data); /* Set the limit threshold */ /* 宏块DCT系数量化 */ cbp = MBQuantInter(pParam, frame, pMB, data, qcoeff, 0, 1); /* 宏块DCT系数反量化 */ MBDeQuantInter(pParam, pMB->quant, data, qcoeff, cbp); /* 宏块反DCT变换 */ MBiDCT(data, cbp); /* 重建的宏块数据更新到当前编码帧,做加操作,与MC相反 */ MBTrans16to8(pParam, frame, pMB, x_pos, y_pos, data, 1, cbp); return(cbp); /* 返回块编码模式CBP(Coded Block Pattern)*/ }
|
上述代码实现Inter宏块的变换与量化处理,需特别注意CBP的获取与应用。
⑤ 变换、量化后的系数做VLC熵编码
void MBCoding(const FRAMEINFO * const frame, MACROBLOCK * pMB, int16_t qcoeff[6 * 64], Bitstream * bs, Statistics * pStat) { if (frame->coding_type != I_VOP) BitstreamPutBit(bs, 0); /* 编码模式:not_coded */ if (pMB->mode == MODE_INTRA) CodeBlockIntra(frame, pMB, qcoeff, bs, pStat); /* Inter宏块编码,MV、系数VLC*/ else CodeBlockInter(frame, pMB, qcoeff, bs, pStat); /* Intra宏块系数VLC*/ } |
对于Inter宏块编码,首先写mcbpc、cbpy、MV,最后写宏块系数。对于Intra宏块编码,首先写mcbpc、AC预测方向、cbpy,最后写宏块系数。对于图像或图像差值做变换、量化/反量化、反变换、编码等底层核心模块,为了提高效率,一般要汇编优化、改写。在后面的两节中,分别介绍采用MMX/SSE 2和DM642两个平台优化核心模块。这也符合视频编码算法开发应用的思路:框架用C语言编程(www.cppentry.com)、核心模块用汇编优化。
3)XviD 销毁编码器
销毁编码器实例对应于创建编码器实例的工作,即把所有申请的内存释放。
int enc_destroy(Encoder * pEnc) { /*释放图像序列空间*/ image_destroy(&pEnc->queue[0].image, pEnc->mbParam. edged_width,pEnc->mbParam. edged_height); xvid_free(pEnc->queue); /*释放当前编码帧的图像空间*/ image_destroy(&pEnc->current->image, pEnc->mbParam. edged_width,pEnc->mbParam. edged_height); /*释放参考帧的图像空间*/ image_destroy(&pEnc->reference->image, pEnc->mbParam. edged_width,pEnc->mbParam. edged_height); /*释放参考帧的水平插值帧的图像空间*/ image_destroy(&pEnc->vInterH, pEnc->mbParam. edged_width,pEnc->mbParam.edged_ height); /*释放参考帧的垂直插值帧的图像空间*/ image_destroy(&pEnc->vInterV, pEnc->mbParam. edged_width,pEnc->mbParam.edged_ height); /*释放参考帧的水平、垂直(即斜角方向)插值帧的图像空间*/ image_destroy (&pEnc->vInterHV, pEnc->mbParam. edged_width,pEnc->mbParam.edged_height); /*释放宏块编码空间*/ xvid_free(pEnc->current->mbs); xvid_free(pEnc->current); /*释放空间*/ /*释放宏块编码空间*/ xvid_free(pEnc->reference->mbs); xvid_free(pEnc->reference); /*释放空间*/ xvid_free(pEnc); /*释放编码器的空间*/ return 0; } | XviD CODEC的MPEG-4视频编码有多种参数可供选择。开发者可以根据自己的指标要求和不同的实现平台,组合编码参数或删减无用的代码以提高编码器的效率。一个典型的嵌入式MPEG-4视频编码算法一般不支持B帧编码、1/4像素精度或MPEG量化模式,但是可采用浮点的码流控制机制以适应网络传输。对于通用CPU如Intel系列CPU,在实现视频编码以验证算法的效率时,可以选择较多的功能,但是实时性可能不高。不过,随着CPU主频等性能的提升,软压缩得到了极大的发展,对硬件视频压缩有一定的影响。
【责任编辑: 云霞 TEL:(010)68476606】
|