Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2225668
  • 博文数量: 668
  • 博客积分: 10016
  • 博客等级: 上将
  • 技术积分: 8588
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-29 19:22
文章分类

全部博文(668)

文章存档

2011年(1)

2010年(2)

2009年(273)

2008年(392)

分类:

2009-08-14 10:52:34

③ 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语言编程、核心模块用汇编优化。

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主频等性能的提升,软压缩得到了极大的发展,对硬件视频压缩有一定的影响。

阅读(718) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~