JM8.6中重要结构体说明

2011年4月24日9:30:25

JM8.6中重要结构体说明

 

[global.h文件]

  1. 下面是一些枚举类型的定义

数据分区方式:PAR_DP_TYPE[PAR_DP_1(不使用数据分区), PAR_DP_3(使用ABC3数据分区)]

输出文件的类型:PAR_OF_TYPE[PAR_OF_ANNEXB, PAR_OF_RTP]

编码的方式: CodingType [FRAME_CODING, FIELD_CODING, ADAPTIVE_CODING]

句法元素的类型: SE_type[SE_HEADER, SE_PTYPE, SE_MBTYPE, SE_REFFRAME, SE_INTRAPREDMODE, SE_MVD ….]

比特位类型: BitCountType[BITS_HEADER,

BITS_TOTAL_MB,

BITS_MB_MODE,        //++ 宏块类型、宏块模式编码比特数(writeMBHeader函数)

BITS_INTER_MB,    //++ 帧间宏块的参考帧、运动向量编码比特数(writeMotionInfo2NAL函数)

BITS_CBP_MB,        //++ 宏块 CBP编码比特数(writeCBPandLumaCoeff函数)

BITS_COEFF_Y_MB,    //++ 宏块亮度残差编码比特数(writeCBPandLumaCoeff函数)

BITS_COEFF_UV_MB,    //++ 宏块色度残差编码比特数(writeChromaCoeff函数)

BITS_DELTA_QUANT_MB,    //++ 宏块量化参数增量编码比特数(writeCBPandLumaCoeff函数)

MAX_BITCOUNTER_MB

];

图像结构类型: PictureStructure[FRAME, TOP_FIELD, BOTTOM_FIELD]

片结构类型: SliceType[ P_SLICE = 0, B_SLICE, I_SLICE, SP_SLICE, SI_SLICE];

 

定义这些枚举类型, 主要是为了使代码更加清晰易读, 便于识别一些变量的含义

  1. 一些重要的结构体的定义

CABAC所要使用的结构体: EncodingEnvironmentBiContextType[state,MPS,count]

MotionInfoContextsTextureInfoContexts

PixelPos在代码中使用的很多, 主要是保存像素相关的一些信息,

句法元素: SyntaxElement, 包含一些基本的类型和两个函数指针(*mapping)(*writing)

宏块结构体:Macroblock, 一些和宏块相关的信息, 宏块指针struct macroblock *mb_available_up*mb_available_left

int mvd[2][BLOCK_MULTIPLE][BLOCK_MULTIPLE][2]; //!< indices correspond to [forw,backw][block_y][block_x][x,y]

Bitstream结构体:保存了一些与正在写的比特流相关的信息

[int byte_pos; //!< current position in bitstream;

int bits_to_go; //!< current bitcounter]

数据分区结构体: DataPartition, 其中包括Bitstream *bitstream;

片结构体:Slice,其中包括了DataPartition *partArr;

图像结构体:Picture,其中包括了slice数组Slice *slices[MAXSLICEPERPICTURE];

同时定义了三个Picture指针

对这三个指针变量, 我们可以追踪一下他们的使用情况:

其实, 我们可以发现, frame_pictop_pic(bottom_pic)出现的位置很相似, 一个是针对帧图像,另外两个是针对场图像的, 所以我们可也只对frame_pic进行追踪即可.

frame_pic出现的过程如下:

首先在global.h文件中定义了指针变量frame_pic, 然后再lencode.c函数中对frame_pic进行了内存分配, frame_pic=malloc_picture(),但是我们可以看看函数malloc_picutre(),发现在这个函数中只是分配了sizeof(Picture)大小的内存, 并不含有任何数据信息.

接下来在函数encode_one_frame()函数中调用了函数frame_picture(frame_pic),此时的frame_pic是空的, 所以猜想在函数frame_picture中会对frame_pic进行填充.

在函数frame_pictureframe_pic变为frame, 所以对frame追踪:

可以发现,未对frame做任何变化就将其传入了函数code_a_picture,接着进入该函数:

在函数code_a_pictureframe变为pic, 接下来,pic赋给了img->currentPicture,这样这两个指针指向了同一个内存区域,可以同时对内存区域进行修改了.

pic的几个成员进行了初始化之后就将pic传入了函数encode_one_slice (SliceGroup, pic);

由于pic中此时不含有输入序列的信息, 所以可以猜想在img变量中应该包含了输入文件的信息

我们进入encode_one_slice函数:可以发现该函数中没有对pic的修改, 所以pic根本没有必要作为一个参数传进来.

但是,通过对img->currentPicture进行追踪可以发现,在函数encode_one_slice中调用了一个函数init_slice, 而在这个函数中有,然后对currPic中的slice数组进行了分配空间, 其实看init_slice之后可以发现这儿确实是对currentPicture所指向的slice数组进行了初始化.[需要追踪一下img变量的变化情况]

通过这个追踪过程, 我们可以发现img的成员变量currentPicture其实是用来指向当前正在活动的图像(frame_pic, top_picbottom_pic)

 

结构体sourceframe:主要用来保存从.yuv文件中读取出来的原始的yuv三个分量数据,分别保存在(char *yf, *uf, *vf; )帧和场的情况不一样

Sourceframe定义了一个指针,利用函数AllocSourceframesrcframe分配了内存空间, 利用函数ReadoneFrameyuv文件中的数据读入到srcframe中去,然后利用srcframe中的数据保存到了二维数组byte**imgY_org_frm, imgUV_org_frm, imgUV_org_frm

对几个比较相似的byte**多维数组进行分析

下面是几个看起来比较类似的数组, 现在我们要搞清它们之间的联系与区别.

观察来看, 其实主要分为三类:

第一类:

这些数组中是对应的存储的原始图像的亮度,色度, 数组所存储的数据是从srcframe变量传递过来的.这些数组区别在于帧还是场.

第二类:

由于色度与亮度是类似的,我们只分析亮度.img_orgimgY_org_frm是类似的, 也是存储的原始图像的亮度.通过查找img_org所在的位置, 我们可以从下面的截图可以发现,

在函数中有imgY_org=imgy_org_frmimgY_org=imgy_org_topimgY_org=imgy_org_bot的语句.

这相当于将imgY_org指针指向了imgy_org_frmimgY_org_top.

这样我们就可以理解了,其实imgY_org是一个用来指示当前正在处理的图像的原始亮度值,根据帧编码还是场编码的不同,可以指向imgy_org_frm()imgY_org_top().

看代码到现在,其实总结起来可以发现有很多这样的情况:相当于有三个比较类似的量,两个分别指向帧和场,而还有一个变量作为比较灵活的中间量,根据当前的选择,指向另外两个中的一个.从这儿开始总结一下这样的三元量(暂时这样称呼它们吧).

第三类:

这两个和上面的区别比较大,这些是重建后的亮度和色度值,

在结构体enc_top_picture(StorablePicture)byte ** imgY;byte *** imgUV;存储的是重建后的亮度和色度值,在函数combine_field中将imgYimgUV中的值分别复制到了imgY_comimgUV_com

 

结构体Decoders, 对应的全局变量指针decs

结构体SNRParameters, 对应的全局变量指针snr

结构体InputParameters,对应全局变量指针input, 个人觉得这个不是很重要,因为它主要获得配置文件中的一些参数设置

结构体ImageParameters,这是一个很重要的结构体, 它的全局变量指针img,这个非常重要,要好好分析一下:

先看看这个结构体中比较重要的成员变量吧:
(
1) int m7[16][16];这个变量的命名很有意思,我觉得,因为它是m1,m2m3,m4,而是m7,为什么是m7??

我们先看看这些m数组都在哪儿出现过吧?!

这些数组都与DCT变换有关

M1[16][16]一个宏块(16x16)的残差值

M0[4][4][4][4]也是一个宏块(16x16)的残差值,相比M1只是分成了164x4小块

在函数dct_luma_16x16中有:

在函数find_sad_16x16中有

在函数dct_luma中有:

在函数dct_chroma中有:

可以发现,在函数中出现了M1,M0,M3,M4,M5,M6, 所以为了程序的可读性比较强出现了m7,并且我们可以看到有很多

地方是m7m5m6之间的计算.

其实m5m6应该是进行DCT变换时的中间变量,m7应该与M1类似,是存储的是宏块残差值

(2) int ****cofAC; //!< AC coefficients [8x8block][4x4block][level/run][scan_pos]

int ***cofDC; //!< DC coefficients [yuv][level/run][scan_pos]

这两个数组的含义很明显, 就是用来存储AC系数和DC系数,

但是还是有些东西值得我们去查找探寻的:

首先在rdopt.c文件中有两个全局变量:

这个可以与[H.264知识点释疑]中对cofAC等变量的分析结合起来看

其实这也牵扯到了函数store_macroblock_parameters和函数set_stored_macroblock_parameters的作用了,这个在之后再讨论

(3)介绍一下下面的几个指针变量:

Picture *currentPicture; //指向当前处理的图像的指针

Slice *currentSlice; //指向当前的slice

Macroblock *mb_data; //指向当前的宏块

SyntaxElement MB_SyntaxElements[MAX_SYMBOLS_PER_MB];

(4) 结构体RD_DATA:这个结构体中的很多成员变量与ImageParameters中的相似,可以考虑研究一下:

   

posted @ 2012-07-27 16:33  Mr.Rico  阅读(...)  评论(...编辑  收藏