转:JM8.6之erc_api.c文件初探

这个文件里面的函数都相对来说比较简单,主要就是对objectBuffer_tercVariables_t两个结构体一些控制。

 void ercInit(int pic_sizex, int pic_sizey, int flag)

函数被调用时ercInit(img->width, img->height, 1);

flag=1设置是否将解码器的误码掩盖功能开启,通过ercSetErrorConcealment(erc_errorVar, flag);设置。在函数中一开始就是对erc_object_list分配了内存:

erc_object_list = (objectBuffer_t *) calloc((pic_sizex * pic_sizey) >> 6, sizeof(objectBuffer_t));

(pic_sizex * pic_sizey) >> 6为了方便,我们可以写成(pic_sizex/8)*( pic_sizey/8),这样我们就明白了,erc_object_list存储了一帧图像中所有8x8块的该结构体容量。

   

   

ercVariables_t *ercOpen( void )

这个函数相当于C++中私有性质,它只被ercInit()所调用。这个函数主要是对ercVariables_t结构体的一些初始化设置,所以我想大家更关心的是这个结构体中变量所代表的具体含义,我在这边提一下我个人的理解。

/* Error detector & concealment instance data structure */

typedef struct ercVariables_s

{

/* Number of macroblocks (size or size/4 of the arrays) */

int nOfMBs;

/* Number of segments (slices) in frame */

int nOfSegments;

 

/* Array for conditions of Y blocks */

int *yCondition; //++ 8*8Y块的状态

/* Array for conditions of U blocks */

int *uCondition; //++ 8*8U块的状态

/* Array for conditions of V blocks */

int *vCondition; //++ 8*8V块的状态

 

/* Array for Slice level information */

ercSegment_t *segments;

int currSegment;

 

/* Conditions of the MBs of the previous frame */

int *prevFrameYCondition;

 

/* Flag telling if the current segment was found to be corrupted */

int currSegmentCorrupted;

/* Counter for corrupted segments per picture */

int nOfCorruptedSegments;

 

/* State variables for error detector and concealer */

int concealment;

 

} ercVariables_t;

   

nOfMBs表示一帧中宏块的数目

nOfSegments表示一帧中slice的数目

*yCondition

*uCondition 都是指针数组,分别代表了一帧中所有8x8YUV块的状态标志(Status Map)

*vCondition

ercSegment_t *segments; 表示一个Slice的数据结构,等下介绍

currSegment 根据命名规则来看,应该表示当前的Slice序号(不确定,但是根据exit_picture()中传递参数的情况来看猜测应该是正确的)

prevFrameYCondition 也是指针数组,表示前一帧中Y块的状态标志

currSegmentCorrupted 用来判断当前Slice是否被误码

nOfCorruptedSegments 一帧图像中误码Slice的数目

concealment 该帧图像解码后是否需要误码掩盖的设置开关

   

/* segment data structure */

typedef struct ercSegment_s

{

int startMBPos;

int endMBPos;

int fCorrupted;

} ercSegment_t;

   

一个Slice的结构,从变量的命名规则我们已经可以很清楚地很明白各自所代表的含义。

startMBPos Slice的起始宏块位置

endMBPos Slice的结束宏块位置

fCorrupted 状态标志,判断该Slice是否被误码了

   

   

void ercReset( ercVariables_t *errorVar, int nOfMBs, int numOfSegments, int32 picSizeX )

这个函数里面有些重复给变量赋值,我自己还没有搞明白。该函数被image.c里面的init_picture()所调用,在解每一帧之前重置ercVariables_t。顺便提下,dec_picture是通过alloc_storable_picture()分配相应的内存空间的。

这边的代码相对来说还是比较简单,我主要有以下几点的疑问:

1  nOfMBsnumOfSegments为什么传参的时候都用img->PicSizeInMbs

2  for ( i = 0; i < errorVar->nOfSegments; i++ )

for ( j = 0; j < nOfMBs; j++ )

    这两个for循环结合在一起什么意思?

   

我自己的解释(我自己都觉得错)

第一问:ercReset()的作用相当于初始化,所以numOfSegments这边传递可能的最大值,即一个宏块就是一个Slice

第二问:同第一问的解释雷同,且设置一个Slice的最大范围。

    errorVar->segments[i].fCorrupted = 1;

    errorVar->segments[i].startMBPos = 0;

    errorVar->segments[i].endMBPos = nOfMBs - 1;

   

   

void ercClose( ercVariables_t *errorVar )

释放errorVar资源,很简单。

   

   

void ercSetErrorConcealment( ercVariables_t *errorVar, int value )

这个函数就是在ercInit()被调用用来设置一帧图片是否进行误码掩盖的状态标志。

   

   

void ercStartSegment( int currMBNum, int segment, u_int32 bitPos, ercVariables_t *errorVar )

void ercStopSegment( int currMBNum, int segment, u_int32 bitPos, ercVariables_t *errorVar )

两个函数结构相似,可以一起介绍。

注意:bitPos这个参数在函数体内其实并没有用到。

ercStartSegment()

errorVar->currSegmentCorrupted = 0;

errorVar->segments[ segment ].fCorrupted = 0;

errorVar->segments[ segment ].startMBPos = currMBNum;

设定一个Slice的起始宏块位置。

ercStopSegment()

errorVar->segments[ segment ].endMBPos = currMBNum;

errorVar->currSegment++;

设定一个Slice的结束宏块位置,并使当前Slice游标加1

   

   

void ercMarkCurrSegmentLost(int32 picSizeX, ercVariables_t *errorVar )

void ercMarkCurrSegmentOK(int32 picSizeX, ercVariables_t *errorVar )

current_segment = errorVar->currSegment-1;这边之所以要减1,因为在调用这个函数之前,会先调用ercStopSegment(),而正是这个函数会使errorVar->currSegment++,这个currSegment已经指向了后面的Segment。里面的一些都比较好理解。

   

   

void ercMarkCurrMBConcealed( int currMBNum, int comp, int32 picSizeX, ercVariables_t *errorVar )

这是在帧间误码掩盖中被调用的函数,里面的动作都很了解,这边我只对

errorVar->uCondition[currMBNum] = ERC_BLOCK_CONCEALED;

errorVar->vCondition[currMBNum] = ERC_BLOCK_CONCEALED;

因为初看可能会觉得奇怪,因为uConditionvCondition都是存储8x8块的状态标志,但这边却用currMBNum,这是宏块的位置,不是矛盾了吗?但是仔细想一下,亮度中宏块的位置和色度中8x8块的位置不是一样的吗,就是这么简单。 

 

参考:http://blog.csdn.net/zhangji1983/article/details/1504780

posted @ 2012-07-28 20:34  Mr.Rico  阅读(357)  评论(0编辑  收藏  举报