三坐标测量仪使用:PartitionMotionSearch()函数流程-H264读书笔记-搜狐空间
来源:百度文库 编辑:偶看新闻 时间:2024/04/28 16:45:17
PartitionMotionSearch()函数流程
标签: 搜索 矢量 预测 编码 运动 分类: PartitionMotionSearch()函数流程 2007-01-08 16:20
PartitionMotionSearch (int blocktype, int block8x8, double lambda)
{
//各种宏块模式下的子块的起始偏移量,相对4*4块来讲,这有利于运动矢量的存放
//[5]表示宏块的类型,[4]表示各种类型下的子块序号,最多子块情况为P8X8模式下有4个
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}};
…………
if (img->mb_data[img->current_mb_nr].mb_field)
{
…………//设置list_offset,对于场编码的宏块的情况
}
else
{
……//设置list_offset,对于非自适应帧/场编码的宏块的情况或者宏块帧编码情况
}
numlists=bslice?2:1;/*bslice对应img->type,如果img->type==B_SLICE,那么参考序列就要参考listX[0],listX[1],这时
numlists就应该等于2,by the way,JM86采用的遍历的方法在参考列表中搜索。*/
for (list=0; list
for (ref=0; ref < listXsize[list+list_offset]; ref++)//list_offset和场模式有关,对于
{
…………
for (v=by0[parttype][block8x8]; v
……
for (h=bx0[parttype][block8x8]; h
…………
//--- motion search for block ---//
mcost = BlockMotionSearch(ref, list, h<<2, v<<2, blocktype, search_range, lambda)
{
/*
BlockMotionSearch(),该函数的具体流程如下:
a、 获取当前块的数据
b、 运动矢量预测
c、 整象素点搜索
d、 亚象素点搜索
e、 保存MV并返回SAD值
*/
static pel_t orig_val [256];//16*16宏块的象素个数就是16*16=256个
static pel_t *orig_pic [16] =
{orig_val, orig_val+ 16, orig_val+ 32, orig_val+ 48,
orig_val+ 64, orig_val+ 80, orig_val+ 96, orig_val+112,
orig_val+128, orig_val+144, orig_val+160, orig_val+176,
orig_val+192, orig_val+208, orig_val+224, orig_val+240};
……………………………………………………………………
int bsx = input->blc_size[blocktype][0];//mode1就是等于16,mode2时等于16,mode3时等于8
int bsy = input->blc_size[blocktype][1];//mode1就是等于16,mode2时等于8 ,mode3时等于16
int pic_pix_x = img->opix_x + mb_x;//!< current original picture pixel horizontal
int pic_pix_y = img->opix_y + mb_y;//!< current original picture pixel vertical
int****** all_mv = img->all_mv;
/*六重指针all_mv的含义:
对应的是一个六维数组如下:
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×16,16×8。。。4×4
Direction表示水平或垂直方向,其值分别是0和1
*/
if(input->FMEnable) // FastME enable,可通过配置文件中的参数UseFME 将其关掉# Use fast motion estimation
(0=disable, 1=enable)
{
…………
}
//==================================
//===== GET ORIGINAL BLOCK =====
//==================================
for (j = 0; j < bsy; j++)//获得宏块YUV数据
{
for (i = 0; i < bsx; i++)
{
}
}
//===========================================
//===== GET MOTION VECTOR PREDICTOR =====
//===========================================
SetMotionVectorPredictor (pred_mv, enc_picture->ref_idx, enc_picture->mv, ref, list, block_x, block_y, bsx, bsy);
void SetMotionVectorPredictor (int pmv[2],
int ***refPic,
int ****tmp_mv,
int ref_frame,
int list,
int block_x,
int block_y,
int blockshape_x,
int blockshape_y)
{
/*block_x:X方向的坐标
block_y:Y方向的坐标
blockshape_x:该子块X方向的尺寸,MbPartWidth,
blockshape_y:该子块Y方向的尺寸 MbPartHeight
*/
/*
pmv:将要获得的预测向量.
ref_frame:当前参考帧序号,refIdxLX
rFrameL:相邻块A的参考帧序号,即标准中的refIdxLXA
rFrameU:refIdxLXB
rFrameUR:refIdxLXC
refPic:当前编码帧每个4X4子块的参考帧索引.
tmp_mv:当前编码帧每个4X4子块的运动MV包括X,Y两个方向.
(已经运动估计过的的子块,当前编码块相邻的A,B,C,D子块都是已经运动估计了,所以refPic,tmp_mv可以用来参考)
ref_frame:参考帧索引号,不是frame_num,也不是POC号,是位于list中的序号.
block_x:X方向的坐标
block_y:Y方向的坐标
blockshape_x:该子块X方向的尺寸,MbPartWidth,
blockshape_y:该子块Y方向的尺寸 MbPartHeight
*/
getLuma4x4Neighbour(mb_nr, block_x, block_y, -1, 0, &block_a);
getLuma4x4Neighbour(mb_nr, block_x, block_y, 0, -1, &block_b);
getLuma4x4Neighbour(mb_nr, block_x, block_y, blockshape_x, -1, &block_c);
getLuma4x4Neighbour(mb_nr, block_x, block_y, -1, -1, &block_d);
/////////////////////block_c和block_d是什么关系//////////////////////
if (!block_c.available)
{
block_c=block_d;//当C块不存在时就参考D块,C块时再当前块的右上角,D块是在当前块的左上角
}
if (!img->MbaffFrameFlag)//>MbaffFrameFlag表明编码器是否支持自适应帧/场编码,这个选项可通过配置文件的参数
PicInterlace设置
{/*
rFrameL是相邻块A的参考帧序号,即标准中的refIdxLXA
rFrameU:refIdxLXB
rFrameUR:refIdxLXC*/
rFrameL = block_a.available ? refPic[list][block_a.pos_x][block_a.pos_y] : -1;//
rFrameU = block_b.available ? refPic[list][block_b.pos_x][block_b.pos_y] : -1;
rFrameUR = block_c.available ? refPic[list][block_c.pos_x][block_c.pos_y] : -1;
}
else/////////////////////////////////////我不支持自适应帧场编码模式,所以这段程序无效
{
}
//中间这些语句是在确定预测方向,即确定rFrameL,rFrameU,rFrameUR等的值
for (hv=0; hv < 2; hv++)
{
if (!img->MbaffFrameFlag || hv==0)//获得候选预测块的矢量,也就是取得abc三块的矢量
{
mv_a = block_a.available ? tmp_mv[list][block_a.pos_x][block_a.pos_y][hv] : 0;
mv_b = block_b.available ? tmp_mv[list][block_b.pos_x][block_b.pos_y][hv] : 0;
mv_c = block_c.available ? tmp_mv[list][block_c.pos_x][block_c.pos_y][hv] : 0;
}
switch (mvPredType)//根据预测方向,确定最后的预测矢量
{
case MVPRED_MEDIAN:
case MVPRED_L:
case MVPRED_UR:
default:
break;
}
pmv[hv] = pred_vec;
}
//*********************以上是SetMotionVectorPredictor 的流程
//==================================
//===== INTEGER-PEL SEARCH =====
//==================================
if(input->FMEnable)
{
else
{
//--- perform motion search ---
min_mcost = FullPelBlockMotionSearch (orig_pic, ref, list, pic_pix_x, pic_pix_y, blocktype,
pred_mv_x, pred_mv_y, &mv_x, &mv_y, search_range,
min_mcost, lambda);
}
}
…………
//==============================
//===== SUB-PEL SEARCH =====
//==============================
if (input->hadamard)
{
}
if(input->FMEnable)
{
}
else
{
min_mcost = SubPelBlockMotionSearch (orig_pic, ref, list, pic_pix_x, pic_pix_y, blocktype,
pred_mv_x, pred_mv_y, &mv_x, &mv_y, 9, 9,
min_mcost, lambda);
}
//===============================================
//===== SET MV'S AND RETURN MOTION COST =====
//===============================================
if(input->FMEnable)
{
}
else
{
for (i=0; i < (bsx>>2); i++)
{
for (j=0; j < (bsy>>2); j++)
{
all_mv[block_x+i][block_y+j][list][ref][blocktype][0] = mv_x;
all_mv[block_x+i][block_y+j][list][ref][blocktype][1] = mv_y;
}
}
}
return min_mcost;
}