PartitionMotionSearch()



Outline:

1、 CFG文件中有关多参考帧的相关选项

2、 多参考帧涉及到的数据结构和全局变量

3、 保存重建图像为参考帧

4、 编码一帧前,设置参考帧列表

5、 多参考帧的使用(即参考帧的选择策略问题

6、 遗留问题

1、CFG文件中有关多参考帧的相关选项

############################################################################### #Encoder Control

###############################################################################

NumberReferenceFrames = 10 # Number of previous frames used for inter motion search (1-16)

解释:

a、 首先通过Configure()转换成input->num_reference_frames

b、 input->num_reference_frames再通过parset.c文件中的IdentifyNumRefFrames()返回给同一文件的FillParameterSetStructures()中的sps->num_ref_frames。

c、 FillParameterSetStructures()其实被parset.c文件中的GenerateParameterSets()函数调用,所以sps又被赋给了active_sps,active_sps是全局变量。

d、 active_sps->num_ref_frames又会在lencod.c中的init_img()函数中被赋给img->num_reference_frames。

PList0References      = 0 # P slice List 0 reference override (0 disable, N <= NumberReferenceFrames)

解释:

用于限制LIST0中参考帧的数目


###############################################################################

# B Frames

###############################################################################

BList0References      = 0 # B slice List 0 reference override (0 disable, N <= NumberReferenceFrames)

BList1References      = 0 # B slice List 1 reference override (0 disable, N <= NumberReferenceFrames)

2、 多参考帧涉及到的数据结构和全局变量

a、 概要

多参考帧相关的重要的数据结构都在mbuffer.h文件中。

其中重要的数据结构有:StorblePicture, FrameStore, DecodedPictureBuffer

重要的全局变量有:

extern DecodedPictureBuffer dpb;

extern StorablePicture **listX[6];

extern int listXsize[6];

b、 各数据结构的作用和相互之间的关系

StorblePicture存放的是一帧帧方式或场方式的重建图像

FrameStore嵌套了StorblePicture,同时增加了一些标志信息,如是否已输出到文件等,所以它可以用于通用的表示一帧的数据结构(不分场或帧)

DecodedPictureBuffer又嵌套了FrameStore,它用于保存所有的重建图像(应该保存的),其中设置很多辅助的参数,如used_size用来表示已经保存的重建图像数。

c、 各全局变量的作用

dpb的作用从上面对DecodedPictureBuffer的解释中,已经可以看出是用来存储所有的重建图像。值的提醒的是它可能保存了非参考帧重建图像。

listX[6]:该变量的作用是用来在每次编码一帧图像时,将所要用到的参考帧保存在其中。但真正所要用到的参考帧图像数据是指向到dpb对应的结构元素中。

对于P帧,只要用到listX[0]。

对于B帧,要用到listX[0],listX[1]

对于Mbaff的编码方式,可能还会用到listX[2-5]。

3、   保存重建图像为参考帧

所用到的函数是:void store_picture_in_dpb(StorablePicture* p),mbuffer.c

该函数在image.c的encode_one_frame()的后段被调要到。

其中重要的程序段如下:

// first try to remove unused frames 当缓冲已满时

if (dpb.used_size==dpb.size)

{

    remove_unused_frame_from_dpb();//只删除一帧。这种策略是否有效呢?怀疑???

}

// then output frames until one can be removed

while (dpb.used_size==dpb.size)
{
    // non-reference frames may be output directly

    if (!p->used_for_reference) //如果当前帧不作为参卡帧,可以直接输出到重建序列文件
    {
        get_smallest_poc(&poc, &pos);

        if ((-1==pos) || (p->poc < poc))

        {

            direct_output(p, p_dec);

            return
        }
    }
    // flush a frame
    output_one_frame_from_dpb();//输出一帧到文件

}

insert_picture_in_dpb(dpb.fs[dpb.used_size],p); //将当前解码帧插入到dpb尾部

4、 编码一帧前,设置参考帧列表

所用到的函数是:init_lists(), mbuffer.c

该函数在image.c中的code_a_picture()的开始部分被调用到。

其中重要的程序段如下:(只举例分析帧模式的情况)

//将dpb中参考帧写入ListX中去


if ((currSliceType == I_SLICE)||(currSliceType == SI_SLICE))
{
    listXsize[0] = 0;
    listXsize[1] = 0;
    return;
}
if ((currSliceType == P_SLICE)||(currSliceType == SP_SLICE))
{
    // Calculate FrameNumWrap and PicNum
    if (currPicStructure == FRAME)
    {
        for (i=0; i<dpb.ref_frames_in_buffer; i++)
        {
            if (dpb.fs_ref[i]->is_used==3)
            {
                if ((dpb.fs_ref[i]->frame->used_for_reference)&&(!dpb.fs_ref[i]->frame->is_long_term))
                {
                    listX[0][list0idx++] = dpb.fs_ref[i]->frame;
                }
            }
        }
        // order list 0 by PicNum
        qsort((void *)listX[0], list0idx, sizeof(StorablePicture*), compare_pic_by_pic_num_desc);
        listXsize[0] = list0idx;

}
else//B_SLICE
{
    …
}
5、 多参考帧的使用(即参考帧的选择策略问题)

所用到的函数是:PartitionMotionSearch(), mv_search.c 该函数的作用是对各种尺寸的宏块或亚宏块寻找匹配块。

其中涉及到多参考帧的程序段如下:

//===== LOOP OVER REFERENCE FRAMES =====
for (list=0; list<numlists;list++)
{
    for (ref=0; ref < listXsize[list+list_offset]; ref++)//list_offset和场模式有关

    {

NOTE:从上面的程序可以看出,JM8.5对多参考帧的选择,是采用的是一种完全遍历的方式,所以其计算复杂度会很高。

6、 遗留问题

a、 在init_lists()对于ListX[0]和ListX[1]中参考帧数相同时,会采用一种交换机制,不知其目的如何?

b、 dpb的参考帧有short_term或long_term这样的属性,这属性会影响多参考帧机制的整个过程,但不知其具体作用和原理?


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zhoujunming/archive/2008/07/31/2747316.aspx

 

PartitionMotionSearch()函数&&宏块分割

encode_one_macroblock()函数中的运动估计分为两大块,对于宏块级的三种模式,分块后直接对patition依次调用PartitionMotionSearch()函数;而对于亚宏块级的(含8x8, 8x4,4x8,4x4)模式,首先将宏块拆分为4个8×8子宏块,针对每个8×8子宏块调用PartitionMotionSearch()函数。

void
PartitionMotionSearch (int    blocktype, //块模式
                   int    block8x8, //当前partition在宏块的序号
                   double lambda)   // λ
{
static int bx0[5][4] = {{0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,2,0,0}, {0,2,0,2}};
static int by0[5][4] = {{0,0,0,0}, {0,0,0,0}, {0,2,0,0}, {0,0,0,0}, {0,0,2,2}}; //参见注释[1]
int   **ref_array, ***mv_array; //参考帧列表和运动向量列表
int   parttype = (blocktype<4?blocktype:4);
int   step_h0   = (input->blc_size[ parttype][0]>>2);
int   step_v0   = (input->blc_size[ parttype][1]>>2);
//partition的尺寸,用于决定block的边界,对非P8×8模式无意义。
int   step_h    = (input->blc_size[blocktype][0]>>2); //子块的尺寸
int   step_v    = (input->blc_size[blocktype][1]>>2);
int   v, h; // BlockMotionSearch()函数要处理的子块在当前宏块中的相对块坐标
//以上尺寸全部以4×4block为单位

numlists=bslice?2:1;
for (list=0; list
{
for (ref=0; ref < listXsize[list+list_offset]; ref++)
{
ref_array = enc_picture->ref_idx[list];
    mv_array = enc_picture->mv[list];
//遍历partition中的每一个
for (v=by0[parttype][block8x8]; v        {
          pic_block_y = img->block_y + v;// 当前子块在图像中的块坐标=当前宏块的块坐标+当前子块在宏块中的相对块坐标
          for (h=bx0[parttype][block8x8]; h          {
            pic_block_x = img->block_x + h; // 当前子块在图像中的块坐标=当前宏块的块坐标+当前子块在宏块中的相对块坐标
            mcost = BlockMotionSearch (ref, list, h<<2, v<<2, blocktype, search_range, lambda); //对当前子块作运动向量搜索
            motion_cost[blocktype][list][ref][block8x8] += mcost; //保存代价值
           
          for (j=0; j
             for (i=0; i
             {
         mv_array [pic_block_x+i][pic_block_y+j][0] = img->all_mv[h][v][list][ref][blocktype][0];
         mv_array [pic_block_x+i][pic_block_y+j][1] = img->all_mv[h][v][list][ref][blocktype][1];
//以4×4block为单位保存运动向量
         ref_array [pic_block_x+i][pic_block_y+j]    = ref;
//保存参考帧序号
             }
          }
       }
    }
}
}
[1] static int bx0[5][4] = {{0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,2,0,0}, {0,2,0,2}};
    static int by0[5][4] = {{0,0,0,0}, {0,0,0,0}, {0,2,0,0}, {0,0,0,0}, {0,0,2,2}};
这里的bx0, by0两个数组分别对应了SKIP模式,16×16,16×8,8×16,P8×8这四种模式的横坐标和纵坐标。举两个例子
如图所示的16×16宏块,首先划分为4个8×8子块(因为PartitionMotionSearch()函数处理的最小块的尺寸为8×8),以4×4block为单位设定坐标,图上已标出4个8×8子块左上角的块坐标。SKIP模式实际上并不牵涉到这个函数,因此坐标全部置零;16×16模式只有第一个坐标起作用,后三个置零;16×8只有前两个有意义,标出两个partition的左上角坐标,如图标出了(0,0),(0,2),对照bx0, by0可以看到相应坐标值;最多子块情况为4个8×8,即最后一组坐标。

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zhoujunming/archive/2008/09/11/2915084.aspx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值