您的位置:首页 > 其它

JM8.6 的核心编码函数研究

2014-08-20 11:26 267 查看
原地址:http://www.cnblogs.com/xkfz007/articles/2612755.html

摘 要: H.264 编解码软件JM 通常被作为算法研究或者实际应用的平台。理解JM 的程序结构是在其基础上进行进一步研究工作的前提。JM 中的编码函数encode_one_macroblock在程序实现编码算法的过程中起到核心的作用。这篇文章通过对程序中开销计算,关键全局变量及编码一个宏块的算法的分析,查明了JM 核心编码函数encode_one_macroblock()的结构,给出了该函数的流程。

关键词:高级视频编码;运动估计;率失真优化;宏块;模式选择

1. 引言

H.264 视频编解码标准是由 ITU-T 的VCEG(视频编码专家组)和ISO/IEC 的MPEG(活动图像编码专家组)的联合视频组JVT 开发的[1]。和以前的视频编码标准相比,H.264 获得了更加出色的编码性能,但需要更加复杂的运算。JM模型是JVT 发布的源代码公开的H.264编解码软件,用C 语言编写而成。JM8.6 是JM 的一个版本,尽管JM8.6(下文简称JM)没有引进最新的一些运动搜索以及快速模式选择算法,但研究它的工作方式和程序结构对H.264算法研究和在JM 基础上的代码剪裁仍然很有意义。为了简明起见,本文只考虑H.264 基本档次的特性。

2. 编码一个宏块(Macroblock)在整个H.264 编码系统中的位置以及负责完成的工作



如图1 所示,如果待编码的宏块属于P slice(如果待编码的宏块属于I
slice,那么其编码过程包含在下述过程中),需要在帧内和帧间的几种编码模式中进行模式选择[2]。如果选择的是帧内模式,则预测值由当前帧已经编码重建的宏块(没有经过去块效应滤波器)给出,最佳的模式值经过熵编码输出到编码流。如果选择的是帧间模式,则预测值由以前编码帧的重建图像给出,选择的参考帧和运动向量等信息经过熵编码输出到码流。原始图像的值和帧内或者帧间预测得到的预测值相减得到残差数据,这些残差数据经过变换,量化后得到的残差系数也经过熵编码输出到码流。另外,参加熵编码的残差系数经过反量化和反变换,和预测值相加,得到重建宏块,存储在当前帧的重建图像中。当前帧的重建图像全部完成以后,经过去块效应滤波器的滤波,将作为参考帧存储起来成为以后编码图像的帧间运动估计的参考。图1中虚线包括起来的部分是JM 的核心编码函数encode_one_macroblock()所完成的工作,包括:运动搜索,参考帧选择,帧间模式选择,帧内模式选择,帧内帧间判定,残差数据的计算,变换和量化,反变换和反量化,重建图像的计算。

3. 开销(cost)的计算

开销是运动搜索,最佳参考帧选择,模式选择的依据。在JM 中,开销的计算有几种不同的方法[3]。

3.1 运动搜索

cost_motion=SA(T)D+lambda_motion*Rate_motion (1)

式中SA(T)D 根据配置文件(本文采用JM 中的配置文件encoder_baselien.cfg, 以下均相同)中的UseHadamard 取值来进行选择。如果不使用Hadamard 变换,SA(T)D 表示原始图像块和预测图像块之间的绝对差值和。如果使用Hadamard 变换,SA(T)D 表示对原始图像和预测图像之间的差值矩阵进行4x4 的Hadamard 变换,然后对变换后的矩阵求绝对值和并除以2。Rate 表示为了编码相应的运动向量所花费的比特数,这个比特数在 JM 中用查表的方式获得:编码的比特数事先经过计算存储在一维数组mvbits[]中,使用的时候,分别用mv 的横纵两个分量的值(都是1/4 像素精度)作为索引去查找mvbits[]。lambda_motion 和下文要提到的lambda_mode 称为乘法因子。在JM 中,它们由如下的公式计算获得

lambda_mode=0.85 *2^(qp/3.00) (2)

lambda_motion=lambda_mode^0.5
(3)


式中,qp 表示量化参数。

3.2 最佳参考帧的选择

cost_ref=cost_motion+lambda_motion*Rate_ref (4)

式中,cost_motion 表示该在该参考帧中用式(1)计算的运动估计的开销,Rate_ref 表示为了编码该参考帧的信息所需要的比特数。这个数值在JM 中用查表的方式获得:编码的比特数事先经过计算存储在一维数组refbits[]中。使用的时候,用参考帧的编号作为索引去查找refbits[]。

3.3 模式的选择

模式选择开销的计算,根据配置文件中RDOptimization 的取值的不同,有两种方式,如果没有使用率失真优化:

cost_mode=cost_ref+lambda_motion*Rate_mode (5)

式中,cost_ref 表示由式4 计算的,在该模式下,选择的最佳参考帧以及相应的运动估计的总开销。Rate_mode 表示为了编码该参考帧的信息所需要的比特数。这个数值在JM 中用查表的方式获得。值得注意的是,在JM 中,查找将仍然使用refbits[]。原因是,模式信息和参考帧信息都是一个无符号整数信息。如果使用了率失真优化,则

cost_mode=SSD+lambda_mode*Rate (6)

式中,SSD 表示原始图像块和重建图像块之间的差值和。在JM 使用式6 对开销进行计算时,SSD 和Rate 有多种含义。对于计算SSD 来说,有时程序只考虑了亮度分量,例如RDCost_for_8x8blocks()函数,有时候,程序同时考虑了亮度分量和两个色度分量,例如RDCost_for_macroblock()函数。Rate 表示编码所需要的比特数。程序将调用熵编码函数进行熵编码操作以确定Rate 值。在不同情况下,Rate 有不同的含义。在Rdcost_for_8x8blocks()函数中,为了进行帧间的模式选择,Rate 的计算过程将编码下列的信息:模式,运动矢量和亮度残差数据。在RDCost_for_4x4IntraBlocks()函数中,为了进行亮度帧内预测模式的选择,Rate 只包括模式和亮度残差系数的编码比特数。而在RDCost_for_macroblock()函数中,由于同时进行了帧内,帧间,亮度和色度的模式选择,Rate 将同时包含以下部分:宏块头数据,模式,运动向量,亮度残差数据以及色度残差数据。

4. 编码一个宏块的步骤

编码模式在以下的7 种帧间,17 种帧内模式中间选择。7 种帧间模式包括:16x16
16x8 8x16 8x8 8x4 4x8 4x4, 分别对应模式编号1~7。17 种帧内模式包括:以4x4 块为单位进行亮

度分量预测的9 种模式(统称为I4MB),以宏块为单位进行亮度分量预测的4 种模式(统称为I16MB)和以宏块为单位进行色度分量预测的4 种模式。值得注意的是,在进行帧间预测

的时候,只有在选择了把一个宏块划分成4 个8x8 的块之后,才能进一步选择8x4,4x8 和4x4的分块[4],因此,在JM 模型中,把4~7 的四种帧间模式统称为P8x8。根据配置文件中的

RDOptimization 的取值,JM 采用两套不同的编码步骤。为了简明起见,本文只讨论RDOptimization=1(使用率失真)的情况,并且假定待编码的宏块属于P
slice。编码过程大体可

以分为以下三个阶段

阶段1:对于帧间模式mode=1,2,3,分别按照式1 和式4 的开销计算标准进行运动搜索和参考帧的选择。

阶段2:对于当前宏块的4个8x8 块,首先按照式1 和式4 的开销计算标准进行运动搜索和参考帧的选择。然后按照式6 的标准进行mode=4,5,6,7 的模式选择。

阶段3:按照式6 的标准,进行以4x4block 为单位的9 种亮度预测模式的模式选择,以最佳模式作为模式I4MB 的值。然后以SA(T)D 值作为开销值,进行以macroblock 为单位的4 种亮度预测模式的模式选择,以最佳模式作为模式I16MB 的值。最后,在帧间模式1,2,3,P8x8等四种模式,帧内亮度分量预测的I4MB,I16MB 两种模式,以及色度预测的4 种模式之间,按照式6 的标准进行模式选择。

最后,程序将以上编码所得到的参数存储起来,这些参数随后将进行熵编码以生成视频输出码流。

5. 重要全局变量说明

JM 模型使用了大量的全局变量,作为参数传递的媒介。理解这些全局变量的意义是理解程序工作方式的关键。下面对encode_one_macroblock()中的关键全局变量作一下说明。

img->all_mv[block_x][block_y][list][ref][mode][direction]:

该变量是一个6维数组,存储了一个宏块的16 个4x4 块在全部参考帧,全部帧间预测模式下的运动向量。direction=0 表示运动向量的x 分量,direction=1 表示y 分量。函数BlockMotionSearch()的主要任务就是进行运动搜索,并更新该数组的值。

best8x8fwref[mode][block8x8]:

该2 维数组存储了一个宏块的4 个8x8block 在各个帧间预测模式下的最佳前向参考帧。在第3 节描述的编码过程的第一阶段和第二阶段中,进行完最佳参考帧的选择后,会将最佳参考帧的信息存储在这个数组中。编码过程的第三阶段,计算预测值时,程序会引用该数组作为参考。

best8x8mode[block8x8]:

该维数组存储了一个宏块的4 个8x8block 的最佳帧间预测模式。它的作用和意义和best8x8fwref 类似。

enc_picture->imgY[pix_y][pix_x],enc_picture->imgUV[uv]
[pix_y][pix_x]:

这两个数组存储了当前编码帧的重建图像的亮度分量和色度分量。其中,pix_y,pix_x 表示像素点在整个图像中的纵横坐标。uv 则指示了U 或V 分量。这两个数组在计算SSD 值时被引用。

motion_cost[mode][list][ref][block]:

该数组存储了一个宏块的分块在不同帧间模式和参考帧下的运动估计的开销值。函数PartitionMotionSearch()的主要任务就是更新该数组。同时,该数组也在决定最佳参考帧时被引用。

img->mpr,img->mprr,img->mprr_2 和img->mprr_c:

这四个数组分别存储了一个宏块在如下四种预测模式下的预测值:亮度分量的帧间预测,亮度分量的4x4 的帧内预测,亮度分量的16x16 的帧内预测,色度分量的8x8 预测。

6. 代码简明分析

下面按照第4 节描述的编码步骤对encode_one_macroblock()函数进行简要的分析。

对帧间模式1,2,3 进行运动搜索和参考帧的选择。

首先, 程序调用PatitionMotionSearch() 函数分别对每个分块进行运动搜索。PartiotionMotionSearch()主要进行了三项工作:第一,选择一个参考帧和分块(如果选择了P8x8 模式,则每个8x8block 还要进行继续的划分),调用BlockMotionSearch()进行每个分块的运动搜索。其中,BlockMotionSearch()函数找到运动向量并更新img->all_mv 的值,并将对应的运动开销作为函数返回值;第二,用BlockMotionSearch()的返回值更新motion_cost,作为接下来进行参考帧选择的依据;第三,更新enc-picture->ref_idx,enc_picture->mv 两个全局变量,这两个变量将作为BlockMotionSearch()中运动搜索时运动向量预测的依据。程序从PartitionMotionSearch()返回之后,继续进行最佳参考帧的选择,选择依据为式4。最后,程序将最佳参考帧的信息存储在数组best8x8fwref 中。

对当前编码宏块的四个block8x8 分别进行运动搜索,参考帧的选择和模式的选择。运动搜索和参考帧选择的过程与第一阶段基本相同。而模式的选择将按照式6 的标准进行。程序将调用RDCost_for_8x8blocks()来进行模式开销的计算,该函数主要进行了以下几项工作。第一,调用LumaResidualCoding8x8()对该8x8 块进行亮度值的预测,残差数据的变换量化以及反变换反量化,以及重建图像的计算。第二,调用熵编码函数对待编码信息进行熵编码,得到rate 值。第三,计算SSD 值并使用式6 计算开销,将其作为函数的返回值。RDCost_for_8x8block()的调用关系如下图所示。



其中,LumaPrediction4x4()首先调用OneComponentLumaPrediction4x4()函数,按照给定的预测模式,参考帧以及运动向量,得到一个(或者两个,对于 B
slice 的双向预测而言)

4x4block 的亮度矩阵。然后对该亮度矩阵进行加权处理,将预测值存储在img->mpr 中。随后,程序调用dct_luma()对残差数据进行变换量化以及反量化反变换,并进行重建块的计算,将重建块矩阵存储在enc_picture->imgY 中,并将经过重排序和游程编码的系数存储在img->cofAC 中。程序从LumaResidualCoding8x8()函数返回以后,将紧接着调用熵编码函数计算Rate 值,在计算了SSD 之后,程序按照式6 得到编码开销作为函数的返回值。最终编码模式的确定。该部分的程序的流程图如下:



完成以上模式选择的操作后, 程序调用store_macroblock_parameters() 函数和set_stored_macroblock_parameters() 函数存储相关的编码信息。
程序从encode_one_macroblock()函数返回以后,会紧接调用write_one_macroblock()进行熵编码和码流生成工作。

7. 结论

JM 作为JVT 官方推出的H.264 软件编解码模型,主要为测试的目的而开发,它实现了H.264 全部特性,通常做为算法研究的平台。本文通过对JM 编码部分的核心函数encode_one_macroblock()的分析,查明了JM 对一个宏块进行编码的程序结构,有利于算法研究工作的展开。例如,新的运动搜索算法可按照BlockMotionSearch()函数定义的接口,在该函数中实现,而不用改动程序的其他部分。另外,由于JM 关心的是引进新的编码算法和特性来尽量提高编码性能,没有考虑算法复杂度的问题,造成了其源代码冗长,结构复杂。通过对其结构的分析,我们可以有目的裁减代码,去除不需要的特性,作为在目标处理器上(例如,DSP 处理器)实现算法的软件参考[5]。

参考文献

[1] Thomas Wiegand,Gary Sullivan.Overview of the H.264/AVC Video Coding Standard[C].IEEE transactions on circuits and systems for video technology,2003-07 ,Vol.13,No.7:560-575

[2] Iain Richardson.H.264 And MPEG-4 video compression[M]. England: John Wiley & Sons Ltd, 2004

[3] Keng-Pang Lim ,Gary Sullivan and Thomas Wiegand. Text Description of Joint Model Reference Encoding Methods and Decoding Concealment Methods[R].Busan,Korea: Joint Video Team (JVT) of ISO/IEC MPEG
and ITU-T VCEG,, 2005-11-09

[4] ITU-T Recommendation H.264,Advanced video coding for generic audiovisual services [S]

[5] 王仁龙. 基于VxWorks和DM642视频采集压缩系统的技术研究[J].计算机工程与应用,2007,43(11):216-218

[6] Yu-Wen Huang,Bing-Yu Hsieh,Tung-Chien Chen,and Liang-Gee Chen.Analysis,Fast Algorithm,and VLSI Architecture Design for H.264/AVC Intra Frame Coder[J].IEEE transactions on circuits and systems for
video technology,Vol.15,No.3,March 2005:378-401

[7] 陈春雁. H.264中基于多分辨率高效帧间预测算法[J].计算机工程与应用,2007,43(01):83-85

[8] 周韬.H.264中基于全零块的编码模式快速选择[J].计算机工程与设计,2007/07,第28卷,第14期:3404-3406

[9] 李军.适用于H.264的直接二维离散余弦变换[J].计算机工程与设计,2007/07,第28卷,第14期:3401-3403

这儿是pdf版下载:http://download.csdn.net/detail/xkfz008/4459813
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: