📄 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) *********************************************************************** */voidSetupFastFullIntegerSearch (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) *********************************************************************** */intFastFullIntegerSearch (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 + -