📄 mv-search.c
字号:
_bo = BlockSAD[refindex][3];
_bi = BlockSAD[refindex][4];
_bj = _bi + 8;
ADD_UP_BLOCKS(); INCREMENT(2);
ADD_UP_BLOCKS();
//--- blocktype 2 ---
_bo = BlockSAD[refindex][2];
_bi = BlockSAD[refindex][4];
_bj = _bi + 2;
ADD_UP_BLOCKS(); INCREMENT(8);
ADD_UP_BLOCKS();
//--- blocktype 1 ---
_bo = BlockSAD[refindex][1];
_bi = BlockSAD[refindex][3];
_bj = _bi + 2;
ADD_UP_BLOCKS();
}
/*!
***********************************************************************
* \brief
* calculation of all SAD's (for all motion vectors and 4x4 blocks)
***********************************************************************
*/
void
SetupFastFullIntegerSearch (int refframe,
int **refFrArr,
int ***tmp_mv,
int *****img_mv,
pel_t *CurrRefPic,
int search_range,
int backward,
int rdopt)
// Note: All Vectors in this function are full pel only.
{
int x, y, pos, blky, bindex;
int Absolute_X, Absolute_Y;
int LineSadBlk0, LineSadBlk1, LineSadBlk2, LineSadBlk3;
int range_partly_outside, offset_x, offset_y, ref_x, ref_y;
int refindex = backward ? img->buf_cycle : refframe;
int max_width = img->width - 17;
int max_height = img->height - 17;
int max_pos = (2*search_range+1) * (2*search_range+1);
int mv_mul = input->mv_res ? 2 : 1;
int **block_sad = BlockSAD[refindex][7];
pel_t orig_blocks [256];
register pel_t *orgptr = orig_blocks;
register pel_t *refptr;
//===== get search center: predictor of 16x16 block =====
SetMotionVectorPredictor (img_mv[0][0][refframe][1], refFrArr, tmp_mv,
refframe, 0, 0, 16, 16);
search_center_x[refindex] = img_mv[0][0][refframe][1][0] / (mv_mul*4);
search_center_y[refindex] = img_mv[0][0][refframe][1][1] / (mv_mul*4);
if (!rdopt)
{
// correct center so that (0,0) vector is inside
search_center_x[refindex] = max(-search_range, min(search_range, search_center_x[refindex]));
search_center_y[refindex] = max(-search_range, min(search_range, search_center_y[refindex]));
}
search_center_x[refindex] += img->pix_x;
search_center_y[refindex] += img->pix_y;
offset_x = search_center_x[refindex];
offset_y = search_center_y[refindex];
//===== copy original block for fast access =====
for (y = img->pix_y; y < img->pix_y+16; y++)
for (x = img->pix_x; x < img->pix_x+16; x++)
*orgptr++ = imgY_org [y][x];
//===== check if whole search range is inside image =====
if (offset_x >= search_range &&
offset_y >= search_range &&
offset_x <= max_width - 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 (!rdopt)
{
ref_x = img->pix_x - offset_x;
ref_y = img->pix_y - offset_y;
for (pos = 0; pos < max_pos; pos++)
if (ref_x == SpiralX[pos] &&
ref_y == SpiralY[pos])
{
pos_00[refindex] = pos;
break;
}
}
//===== loop over search range (spiral search): get blockwise SAD =====
for (pos = 0; pos < max_pos; pos++)
{
Absolute_Y = offset_y + SpiralY[pos];
Absolute_X = offset_x + SpiralX[pos];
if (range_partly_outside)
{
if (Absolute_Y >= 0 && Absolute_Y <= max_height &&
Absolute_X >= 0 && Absolute_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 (CurrRefPic, Absolute_Y++, Absolute_X);
LineSadBlk0 += ByteAbs(*refptr++ - *orgptr++);
LineSadBlk0 += ByteAbs(*refptr++ - *orgptr++);
LineSadBlk0 += ByteAbs(*refptr++ - *orgptr++);
LineSadBlk0 += ByteAbs(*refptr++ - *orgptr++);
LineSadBlk1 += ByteAbs(*refptr++ - *orgptr++);
LineSadBlk1 += ByteAbs(*refptr++ - *orgptr++);
LineSadBlk1 += ByteAbs(*refptr++ - *orgptr++);
LineSadBlk1 += ByteAbs(*refptr++ - *orgptr++);
LineSadBlk2 += ByteAbs(*refptr++ - *orgptr++);
LineSadBlk2 += ByteAbs(*refptr++ - *orgptr++);
LineSadBlk2 += ByteAbs(*refptr++ - *orgptr++);
LineSadBlk2 += ByteAbs(*refptr++ - *orgptr++);
LineSadBlk3 += ByteAbs(*refptr++ - *orgptr++);
LineSadBlk3 += ByteAbs(*refptr++ - *orgptr++);
LineSadBlk3 += ByteAbs(*refptr++ - *orgptr++);
LineSadBlk3 += ByteAbs(*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 (refindex, max_pos);
//===== set flag marking that search setup have been done =====
search_setup_done[refindex] = 1;
}
/*!
***********************************************************************
* \brief
* fast full integer search (SetupFastFullIntegerSearch have to be called before)
***********************************************************************
*/
int
FastFullIntegerSearch (int mv_mul,
int predicted_x,
int predicted_y,
int search_range,
int refindex,
int blocktype,
int mb_x,
int mb_y,
int *center_h2,
int *center_v2,
int pic_pix_x,
int pic_pix_y,
double lambda)
{
// Note: All Vectors in this function are full pel only.
int Candidate_X, Candidate_Y, current_inter_sad;
int mvres = mv_mul==1 ? 4 : 8;
int mvres_l = mv_mul==1 ? 2 : 3;
int Offset_X = search_center_x[refindex] - img->pix_x;
int Offset_Y = search_center_y[refindex] - img->pix_y;
int best_inter_sad = MAX_VALUE;
int bindex = mb_y + (mb_x >> 2);
register int pos;
register int max_pos = (2*search_range+1)*(2*search_range+1);
register int *block_sad = BlockSAD[refindex][blocktype][bindex];
//===== cost for (0,0)-vector: it is done before, because MVCost can be negative =====
if (!lambda)
{
*center_h2 = 0;
*center_v2 = 0;
best_inter_sad = block_sad[pos_00[refindex]] + MVCost(1, mvres, blocktype, img->qp, predicted_x, predicted_y, 0, 0);
}
//===== loop over search range (spiral search) =====
if (lambda)
{
for (pos = 0; pos < max_pos; pos++, block_sad++)
if (*block_sad < best_inter_sad)
{
Candidate_X = Offset_X + SpiralX[pos];
Candidate_Y = Offset_Y + SpiralY[pos];
current_inter_sad = *block_sad;
current_inter_sad += MVCostLambda (mvres_l, lambda, predicted_x, predicted_y, Candidate_X, Candidate_Y);
if (current_inter_sad < best_inter_sad)
{
*center_h2 = Candidate_X;
*center_v2 = Candidate_Y;
best_inter_sad = current_inter_sad;
}
}
}
else
{
for (pos = 0; pos < max_pos; pos++, block_sad++)
if (*block_sad < best_inter_sad)
{
Candidate_X = Offset_X + SpiralX[pos];
Candidate_Y = Offset_Y + SpiralY[pos];
current_inter_sad = *block_sad;
current_inter_sad += MVCost (1, mvres, blocktype, img->qp, predicted_x, predicted_y, Candidate_X, Candidate_Y);
if (current_inter_sad < best_inter_sad)
{
*center_h2 = Candidate_X;
*center_v2 = Candidate_Y;
best_inter_sad = current_inter_sad;
}
}
}
return best_inter_sad;
}
#endif // _FAST_FULL_ME_
/*!
***********************************************************************
* \brief
* Integer Spiral Search
* \par Output:
* best_inter_sad
* \par Output (through Parameter pointers):
* center_h2, center_v2 (if better MV was found)
***********************************************************************
*/
int IntegerSpiralSearch ( int mv_mul, int center_x, int center_y,
int predicted_x, int predicted_y,
int blockshape_x, int blockshape_y,
int curr_search_range, int blocktype,
pel_t mo[16][16], pel_t *FullPelCurrRefPic,
int *center_h2, int *center_v2,
int pic_pix_x, int pic_pix_y,
double lambda)
{
// Note: All Vectors in this function are full pel only.
int numc, lv;
int best_inter_sad = MAX_VALUE;
int abort_search;
int current_inter_sad;
int Candidate_X, Candidate_Y, Absolute_X, Absolute_Y;
int i, x, y;
int Difference;
pel_t SingleDimensionMo[16*16];
pel_t *check;
numc=(curr_search_range*2+1)*(curr_search_range*2+1);
// Setup a fast access field for the original
for (y=0, i=0; y<blockshape_y; y++)
for (x=0; x<blockshape_x; x++)
SingleDimensionMo[i++] = mo[y][x];
for (lv=0; lv < numc; lv++)
{
Candidate_X = center_x + SpiralX[lv];
Candidate_Y = center_y + SpiralY[lv];
Absolute_X = pic_pix_x + Candidate_X;
Absolute_Y = pic_pix_y + Candidate_Y;
if (lambda)
current_inter_sad = MVCostLambda (mv_mul==1?2:3, lambda, predicted_x, predicted_y, Candidate_X, Candidate_Y);
else
current_inter_sad = MVCost (1, (mv_mul==1)?4:8, blocktype, img->qp, predicted_x, predicted_y, Candidate_X,Candidate_Y);
abort_search=FALSE;
for (y=0, i=0; y < blockshape_y && !abort_search; y++)
{
check = PelYline_11 (FullPelCurrRefPic, Absolute_Y+y, Absolute_X); // get pointer to line
for (x=0; x < blockshape_x ;x++)
{
Difference = SingleDimensionMo[i++]- *check++;
current_inter_sad += ByteAbs (Difference);
}
if (current_inter_sad >= best_inter_sad)
{
abort_search=TRUE;
}
}
if(!abort_search)
{
*center_h2=Candidate_X;
*center_v2=Candidate_Y;
best_inter_sad=current_inter_sad;
}
}
return best_inter_sad;
}
/*!
***********************************************************************
* \brief
* Half Pel Search
***********************************************************************
*/
int HalfPelSearch(int pic4_pix_x, int pic4_pix_y, int mv_mul, int blockshape_x, int blockshape_y,
int *s_pos_x1, int *s_pos_y1, int *s_pos_x2, int *s_pos_y2, int center_h2, int center_v2,
int predicted_x, int predicted_y, int blocktype, pel_t mo[16][16], pel_t **CurrRefPic, int ***tmp_mv,
int *****all_mv, int block_x, int block_y, int ref_frame, int pic_block_x, int pic_block_y,
double lambda)
{
int best_inter_sad=MAX_VALUE;
int current_inter_sad;
int lv, iy0, jy0, vec1_x, vec1_y, vec2_x, vec2_y, i, i22, j;
int s_pos_x, s_pos_y;
int m7[16][16];
for (lv=0; lv < 9; lv++)
{
s_pos_x=center_h2+SpiralX[lv]*2;
s_pos_y=center_v2+SpiralY[lv]*2;
iy0=pic4_pix_x+s_pos_x;
jy0=pic4_pix_y+s_pos_y;
if (lambda)
current_inter_sad = MVCostLambda (mv_mul==1?0:1, lambda,
predicted_x, predicted_y, s_pos_x, s_pos_y);
else
current_inter_sad = MVCost (4, (mv_mul==1)?4:8, blocktype, img->qp, predicted_x, predicted_y, s_pos_x, s_pos_y);
for (vec1_x=0; vec1_x < blockshape_x; vec1_x += 4)
{
for (vec1_y=0; vec1_y < blockshape_y; vec1_y += 4)
{
for (i=0; i < BLOCK_SIZE; i++)
{
vec2_x=i+vec1_x;
i22=iy0+vec2_x*4;
for (j=0; j < BLOCK_SIZE; j++)
{
vec2_y=j+vec1_y;
m7[i][j]=mo[vec2_y][vec2_x]-PelY_14 (CurrRefPic, jy0+vec2_y*4, i22);
}
}
current_inter_sad += find_sad(input->hadamard, m7);
}
}
if (current_inter_sad < best_inter_sad)
{
*s_pos_x1=s_pos_x;
*s_pos_y1=s_pos_y;
*s_pos_x2=s_pos_x;
*s_pos_y2=s_pos_y;
for (i=0; i < blockshape_x/BLOCK_SIZE; i++)
{
for (j=0; j < blockshape_y/BLOCK_SIZE; j++)
{
all_mv[block_x+i][block_y+j][ref_frame][blocktype][0]=mv_mul**s_pos_x1;
all_mv[block_x+i][block_y+j][ref_frame][blocktype][1]=mv_mul**s_pos_y1;
tmp_mv[0][pic_block_y+j][pic_block_x+i+BLOCK_SIZE]=mv_mul**s_pos_x1;
tmp_mv[1][pic_block_y+j][pic_block_x+i+BLOCK_SIZE]=mv_mul**s_pos_y1;
}
}
best_inter_sad=current_inter_sad;
}
}
return best_inter_sad;
}
/*!
***********************************************************************
* \brief
* Quarter Pel Search
***********************************************************************
*/
int QuarterPelSearch(int pic4_pix_x, int pic4_pix_y, int mv_mul, int blockshape_x, int blockshape_y,
int *s_pos_x1, int *s_pos_y1, int *s_pos_x2, int *s_pos_y2, int center_h2, int center_v2,
int predicted_x, int predicted_y, int blocktype, pel_t mo[16][16], pel_t **CurrRefPic, int ***tmp_mv,
int *****all_mv, int block_x, int block_y, int ref_frame,
int pic_block_x, int pic_block_y, int best_inter_sad,
double lambda
)
{
int current_inter_sad;
int lv, s_pos_x, s_pos_y, iy0, jy0, vec1_x, vec1_y, vec2_x, vec2_y, i, i22, j;
int m7[16][16];
for (lv=1; lv < 9; lv++)
{
s_pos_x=*s_pos_x2+SpiralX[lv];
s_pos_y=*s_pos_y2+SpiralY[lv];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -