现在的位置: 首页 > 综合 > 正文

JM8.5中的高精度象素运动估计

2012年07月14日 ⁄ 综合 ⁄ 共 3339字 ⁄ 字号 评论关闭

JM8.5中的高精度象素运动估计

Outline:

1、  运动估计相关的数据结构和变量

2、  相关重要变量的初始化

3、  运动估计函数(BlockMotionSearch())的流程

4、  运动矢量预测

5、  整象素点运动估计

6、  亚象素点运动估计(即高精度象素点运动估计)

7、  亚象素点的插值预测

8、  遗留问题

 

 

1、运动估计相关的数据结构和变量

a、六重指针all_mv的解释

1)声明的样式如下:

int****** all_mv

2)出现之处:

全局变量img的结构元素all_mv和pred_mv(其数据结构在global.h中定义)

mv_search.cBlockMotiongSearch()函数对一块进行运动估计的函数后面会重点讲述中声明的局部变量int****** all_mv;

3)六重指针的含义:

对应的是一个六维数组如下:

all_mv[block_x][block_y][list][ref][blocktype][direction]

其中block_x, block_y分别表示4*4块在整个宏块16*16内的水平和垂直位置,同时也说明所保存的运动矢量都是以4*4为单位的,假如有一个8*4的块,其运动矢量会保存成相同的两份。

List表示的是哪个参考帧列表

Ref表示的是参考帧序号

Blocktype表示的是宏块的类型,有16×1616×8。。。4×4

Direction表示水平或垂直方向,其值分别是01

 

2、相关重要变量的初始化

aimg->all_mv的初始化

其初始化的整个过程如下:

首先,在lencod.cmain()函数调用了init_img()(在同一文件中)函数

然后init_img()又调用了get_mem_mv(img->all_mv)(在同一文件中)all_mv进行初始化。Pred_mv的初始化同上。下面重点分析一下get_mem_mv()函数

int get_mem_mv (int******* mv)

{

  int i, j, k, l, m;

 

  //4*4块的序号,水平方向:block_x。因为采用的宏块或亚宏块的尺寸不超过16×16,所以最大值为4

  if ((*mv = (int******)calloc(4,sizeof(int*****))) == NULL)

    no_mem_exit ("get_mem_mv: mv");

  for (i=0; i<4; i++)

  {

    if (((*mv)[i] = (int*****)calloc(4,sizeof(int****))) == NULL)//block_y

      no_mem_exit ("get_mem_mv: mv");

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

    {

      if (((*mv)[i][j] = (int****)calloc(2,sizeof(int***))) == NULL)//list。6?

        no_mem_exit ("get_mem_mv: mv");

      for (k=0; k<2; k++)

      {

        if (((*mv)[i][j][k] = (int***)calloc(img->max_num_references,sizeof(int**))) == NULL)//ref

          no_mem_exit ("get_mem_mv: mv");

        for (l=0; l<img->max_num_references; l++)

        {

          if (((*mv)[i][j][k][l] = (int**)calloc(9,sizeof(int*))) == NULL)//blocktype:16*16,16*8...

            no_mem_exit ("get_mem_mv: mv");

          for (m=0; m<9; m++)

            if (((*mv)[i][j][k][l][m] = (int*)calloc(2,sizeof(int))) == NULL)//x or y direction:0 or 1

              no_mem_exit ("get_mem_mv: mv");

        }

      }

    }

  }

  return 4*4*img->max_num_references*9*2*sizeof(int);

}

 

 

3  运动估计函数(BlockMotionSearch())的流程

对一个块(各种尺寸)进行运动估计的最核心的函数就是mv_search.c中的BlockMotionSearch(),该函数的具体流程如下:

a、  获取当前块的数据

b、  运动矢量预测

c、  整象素点搜索

d、  亚象素点搜索

e、  保存MV并返回SAD

下面对b,c,d三块内容进行重点分析

 

4运动矢量预测

相关的函数是:SetMotionVectorPredictor(),mv_search.c

a、相应宏定义的解释:

#define MVPRED_MEDIAN   0   //中值预测方式

#define MVPRED_L        1   //取左相邻块的运动矢量

#define MVPRED_U        2   //取上相邻块的运动矢量

#define MVPRED_UR       3   //取右上相邻块的运动矢量

b、该函数的具体流程

1)先检查各相邻块是否有效

2)结合参考帧序号等情况来确定预测方式mvPredType

3)根据mvPredType采取不同的预测方式

c、重要的程序段

。。。

  //判断相邻4*4块的有效性

getLuma4x4Neighbour(mb_nr, block_x, block_y,           -1,  0, &block_a);//left

getLuma4x4Neighbour(mb_nr, block_x, block_y,            0, -1, &block_b);//up

getLuma4x4Neighbour(mb_nr, block_x, block_y, blockshape_x, -1, &block_c);//right-up

getLuma4x4Neighbour(mb_nr, block_x, block_y,           -1, -1, &block_d);//left-up

。。。

/* Prediction if only one of the neighbors uses the reference frame

* we are checking

*///只有一个相邻块的参考帧序号和当前参卡帧序号相同的情况下,采用的预测方式相对较简单

if(rFrameL == ref_frame && rFrameU != ref_frame && rFrameUR != ref_frame)       mvPredType = MVPRED_L;

else if(rFrameL != ref_frame && rFrameU == ref_frame && rFrameUR != ref_frame)  mvPredType = MVPRED_U;

else if(rFrameL != ref_frame && rFrameU != ref_frame && rFrameUR == ref_frame)  mvPredType = MVPRED_UR;

。。。

//根据mvPredType采取不同的预测方式

switch (mvPredType)

{

case MVPRED_MEDIAN:

    。。。

    {

//取中值

    pred_vec = mv_a+mv_b+mv_c-min(mv_a,min(mv_b,mv_c))-max(mv_a,max(mv_b,mv_c));

    }

    break;

case MVPRED_L:

    pred_vec = mv_a;

    if(input->FMEnable) temp_pred_SAD[hv] = SAD_a;

    break;

case MVPRED_U:

    pred_vec = mv_b;

    if(input->FMEnable) temp_pred_SAD[hv] = SAD_b;

    break;

case MVPRED_UR:

    pred_vec = mv_c;

抱歉!评论已关闭.