📄 mv-search.c
字号:
search_center_y[list][ref] += img->opix_y;
offset_x = search_center_x[list][ref];
offset_y = search_center_y[list][ref];
//===== copy original block for fast access =====
for (y = img->opix_y; y < img->opix_y+16; y++)
for (x = img->opix_x; x < img->opix_x+16; x++)
*orgptr++ = imgY_org [y][x];
//===== check if whole search range is inside image =====
if (offset_x >= search_range && offset_x <= max_width - search_range &&
offset_y >= search_range && offset_y <= max_height - search_range )
{
range_partly_outside = 0; PelYline_11 = FastLine16Y_11;
}
else
{
range_partly_outside = 1;
}
//===== determine position of (0,0)-vector =====
if (!input->rdopt)
{
ref_x = img->opix_x - offset_x;
ref_y = img->opix_y - offset_y;
for (pos = 0; pos < max_pos; pos++)
{
if (ref_x == spiral_search_x[pos] &&
ref_y == spiral_search_y[pos])
{
pos_00[list][ref] = pos;
break;
}
}
}
//===== loop over search range (spiral search): get blockwise SAD =====
for (pos = 0; pos < max_pos; pos++)
{
abs_y = offset_y + spiral_search_y[pos];
abs_x = offset_x + spiral_search_x[pos];
if (range_partly_outside)
{
if (abs_y >= 0 && abs_y <= max_height &&
abs_x >= 0 && abs_x <= max_width )
{
PelYline_11 = FastLine16Y_11;
}
else
{
PelYline_11 = UMVLine16Y_11;
}
}
orgptr = orig_blocks;
bindex = 0;
for (blky = 0; blky < 4; blky++)
{
LineSadBlk0 = LineSadBlk1 = LineSadBlk2 = LineSadBlk3 = 0;
for (y = 0; y < 4; y++)
{
refptr = PelYline_11 (ref_pic, abs_y++, abs_x, img_height, img_width);
LineSadBlk0 += byte_abs [*refptr++ - *orgptr++];
LineSadBlk0 += byte_abs [*refptr++ - *orgptr++];
LineSadBlk0 += byte_abs [*refptr++ - *orgptr++];
LineSadBlk0 += byte_abs [*refptr++ - *orgptr++];
LineSadBlk1 += byte_abs [*refptr++ - *orgptr++];
LineSadBlk1 += byte_abs [*refptr++ - *orgptr++];
LineSadBlk1 += byte_abs [*refptr++ - *orgptr++];
LineSadBlk1 += byte_abs [*refptr++ - *orgptr++];
LineSadBlk2 += byte_abs [*refptr++ - *orgptr++];
LineSadBlk2 += byte_abs [*refptr++ - *orgptr++];
LineSadBlk2 += byte_abs [*refptr++ - *orgptr++];
LineSadBlk2 += byte_abs [*refptr++ - *orgptr++];
LineSadBlk3 += byte_abs [*refptr++ - *orgptr++];
LineSadBlk3 += byte_abs [*refptr++ - *orgptr++];
LineSadBlk3 += byte_abs [*refptr++ - *orgptr++];
LineSadBlk3 += byte_abs [*refptr++ - *orgptr++];
}
block_sad[bindex++][pos] = LineSadBlk0;
block_sad[bindex++][pos] = LineSadBlk1;
block_sad[bindex++][pos] = LineSadBlk2;
block_sad[bindex++][pos] = LineSadBlk3;
}
}
//===== combine SAD's for larger block types =====
SetupLargerBlocks (list, ref, max_pos);
//===== set flag marking that search setup have been done =====
search_setup_done[list][ref] = 1;
}
#endif // _FAST_FULL_ME_
/*!
************************************************************************
* \brief
* Set motion vector predictor
************************************************************************
*/
void SetMotionVectorPredictor (short pmv[2],
char **refPic,
short ***tmp_mv,
short ref_frame,
int list,
int block_x,
int block_y,
int blockshape_x,
int blockshape_y)
{
int mb_x = 4*block_x;
int mb_y = 4*block_y;
int mb_nr = img->current_mb_nr;
int mv_a, mv_b, mv_c, pred_vec=0;
int mvPredType, rFrameL, rFrameU, rFrameUR;
int hv;
PixelPos block_a, block_b, block_c, block_d;
// added for bipred mode
int *** fastme_l0_cost_flag = (input->FMEnable == 1) ? (bipred_flag ? fastme_l0_cost_bipred:fastme_l0_cost) : NULL;
int *** fastme_l1_cost_flag = (input->FMEnable == 1) ? (bipred_flag ? fastme_l1_cost_bipred:fastme_l1_cost) : NULL;
//Dynamic Search Range
int dsr_temp_search_range[2];
int dsr_mv_avail, dsr_mv_max, dsr_mv_sum, dsr_small_search_range;
// neighborhood SAD init
if(input->FMEnable == 1)
{
SAD_a=0;
SAD_b=0;
SAD_c=0;
SAD_d=0;
}
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);
if (mb_y > 0)
{
if (mb_x < 8) // first column of 8x8 blocks
{
if (mb_y==8)
{
if (blockshape_x == 16) block_c.available = 0;
}
else
{
if (mb_x+blockshape_x == 8) block_c.available = 0;
}
}
else
{
if (mb_x+blockshape_x == 16) block_c.available = 0;
}
}
if (!block_c.available)
{
block_c=block_d;
}
mvPredType = MVPRED_MEDIAN;
if (!img->MbaffFrameFlag)
{
rFrameL = block_a.available ? refPic[block_a.pos_y][block_a.pos_x] : -1;
rFrameU = block_b.available ? refPic[block_b.pos_y][block_b.pos_x] : -1;
rFrameUR = block_c.available ? refPic[block_c.pos_y][block_c.pos_x] : -1;
}
else
{
if (img->mb_data[img->current_mb_nr].mb_field)
{
rFrameL = block_a.available ?
img->mb_data[block_a.mb_addr].mb_field ?
refPic[block_a.pos_y][block_a.pos_x]:
refPic[block_a.pos_y][block_a.pos_x] * 2:
-1;
rFrameU = block_b.available ?
img->mb_data[block_b.mb_addr].mb_field ?
refPic[block_b.pos_y][block_b.pos_x]:
refPic[block_b.pos_y][block_b.pos_x] * 2:
-1;
rFrameUR = block_c.available ?
img->mb_data[block_c.mb_addr].mb_field ?
refPic[block_c.pos_y][block_c.pos_x]:
refPic[block_c.pos_y][block_c.pos_x] * 2:
-1;
}
else
{
rFrameL = block_a.available ?
img->mb_data[block_a.mb_addr].mb_field ?
refPic[block_a.pos_y][block_a.pos_x] >>1:
refPic[block_a.pos_y][block_a.pos_x] :
-1;
rFrameU = block_b.available ?
img->mb_data[block_b.mb_addr].mb_field ?
refPic[block_b.pos_y][block_b.pos_x] >>1:
refPic[block_b.pos_y][block_b.pos_x] :
-1;
rFrameUR = block_c.available ?
img->mb_data[block_c.mb_addr].mb_field ?
refPic[block_c.pos_y][block_c.pos_x] >>1:
refPic[block_c.pos_y][block_c.pos_x] :
-1;
}
}
/* 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;
// Directional predictions
if(blockshape_x == 8 && blockshape_y == 16)
{
if(mb_x == 0)
{
if(rFrameL == ref_frame)
mvPredType = MVPRED_L;
}
else
{
if( rFrameUR == ref_frame)
mvPredType = MVPRED_UR;
}
}
else if(blockshape_x == 16 && blockshape_y == 8)
{
if(mb_y == 0)
{
if(rFrameU == ref_frame)
mvPredType = MVPRED_U;
}
else
{
if(rFrameL == ref_frame)
mvPredType = MVPRED_L;
}
}
// neighborhood SAD prediction
if(input->FMEnable == 1 &&(input->DynamicSearchRange == 1 || input->BiPredMotionEstimation == 1))
{
SAD_a = block_a.available ? ((list==1) ? (fastme_l1_cost_flag[FME_blocktype][block_a.pos_y][block_a.pos_x]) : (fastme_l0_cost_flag[FME_blocktype][block_a.pos_y][block_a.pos_x])) : 0;
SAD_b = block_b.available ? ((list==1) ? (fastme_l1_cost_flag[FME_blocktype][block_b.pos_y][block_b.pos_x]) : (fastme_l0_cost_flag[FME_blocktype][block_b.pos_y][block_b.pos_x])) : 0;
SAD_d = block_d.available ? ((list==1) ? (fastme_l1_cost_flag[FME_blocktype][block_d.pos_y][block_d.pos_x]) : (fastme_l0_cost_flag[FME_blocktype][block_d.pos_y][block_d.pos_x])) : 0;
SAD_c = block_c.available ? ((list==1) ? (fastme_l1_cost_flag[FME_blocktype][block_c.pos_y][block_c.pos_x]) : (fastme_l0_cost_flag[FME_blocktype][block_c.pos_y][block_c.pos_x])) : SAD_d;
}
for (hv=0; hv < 2; hv++)
{
if (!img->MbaffFrameFlag || hv==0)
{
mv_a = block_a.available ? tmp_mv[block_a.pos_y][block_a.pos_x][hv] : 0;
mv_b = block_b.available ? tmp_mv[block_b.pos_y][block_b.pos_x][hv] : 0;
mv_c = block_c.available ? tmp_mv[block_c.pos_y][block_c.pos_x][hv] : 0;
}
else
{
if (img->mb_data[img->current_mb_nr].mb_field)
{
mv_a = block_a.available ? img->mb_data[block_a.mb_addr].mb_field
? tmp_mv[block_a.pos_y][block_a.pos_x][hv]
: tmp_mv[block_a.pos_y][block_a.pos_x][hv] / 2
: 0;
mv_b = block_b.available ? img->mb_data[block_b.mb_addr].mb_field
? tmp_mv[block_b.pos_y][block_b.pos_x][hv]
: tmp_mv[block_b.pos_y][block_b.pos_x][hv] / 2
: 0;
mv_c = block_c.available ? img->mb_data[block_c.mb_addr].mb_field
? tmp_mv[block_c.pos_y][block_c.pos_x][hv]
: tmp_mv[block_c.pos_y][block_c.pos_x][hv] / 2
: 0;
}
else
{
mv_a = block_a.available ? img->mb_data[block_a.mb_addr].mb_field
? tmp_mv[block_a.pos_y][block_a.pos_x][hv] * 2
: tmp_mv[block_a.pos_y][block_a.pos_x][hv]
: 0;
mv_b = block_b.available ? img->mb_data[block_b.mb_addr].mb_field
? tmp_mv[block_b.pos_y][block_b.pos_x][hv] * 2
: tmp_mv[block_b.pos_y][block_b.pos_x][hv]
: 0;
mv_c = block_c.available ? img->mb_data[block_c.mb_addr].mb_field
? tmp_mv[block_c.pos_y][block_c.pos_x][hv] * 2
: tmp_mv[block_c.pos_y][block_c.pos_x][hv]
: 0;
}
}
switch (mvPredType)
{
case MVPRED_MEDIAN:
if(!(block_b.available || block_c.available))
{
pred_vec = mv_a;
}
else
{
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;
break;
case MVPRED_U:
pred_vec = mv_b;
break;
case MVPRED_UR:
pred_vec = mv_c;
break;
default:
break;
}
pmv[hv] = pred_vec;
//Dynamic Search Range
if (input->FMEnable == 1 && input->DynamicSearchRange)
{
dsr_mv_avail=block_a.available+block_b.available+block_c.available;
if(dsr_mv_avail < 2)
{
dsr_temp_search_range[hv] = input->search_range;
}
else
{
dsr_mv_max = max(abs(mv_a),max(abs(mv_b),abs(mv_c)));
dsr_mv_sum = (abs(mv_a)+abs(mv_b)+abs(mv_c));
if(dsr_mv_sum == 0) dsr_small_search_range = (input->search_range + 4) >> 3;
else if(dsr_mv_sum > 3 ) dsr_small_search_range = (input->search_range + 2) >>2;
else dsr_small_search_range = (3*input->search_range + 8) >> 4;
dsr_temp_search_range[hv]=min(input->search_range,max(dsr_small_search_range,dsr_mv_max<<1));
if(max(SAD_a,max(SAD_b,SAD_c)) > Threshold_DSR_MB[FME_blocktype])
dsr_temp_search_range[hv] = input->search_range;
}
}
}
//Dynamic Search Range
if (input->FMEnable == 1 && input->DynamicSearchRange)
dsr_new_search_range = max(dsr_temp_search_range[0],dsr_temp_search_range[1]);
}
/*!
************************************************************************
* \brief
* Initialize the motion search
************************************************************************
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -