📄 mv-search.c
字号:
{
spiral_search_x[k] = i;
spiral_search_y[k] = -l;
spiral_hpel_search_x[k] = i<<1;
spiral_hpel_search_y[k++] = -l<<1;
spiral_search_x[k] = i;
spiral_search_y[k] = l;
spiral_hpel_search_x[k] = i<<1;
spiral_hpel_search_y[k++] = l<<1;
}
for (i=-l; i<=l; i++)
{
spiral_search_x[k] = -l;
spiral_search_y[k] = i;
spiral_hpel_search_x[k] = -l<<1;
spiral_hpel_search_y[k++] = i<<1;
spiral_search_x[k] = l;
spiral_search_y[k] = i;
spiral_hpel_search_x[k] = l<<1;
spiral_hpel_search_y[k++] = i<<1;
}
}
// set global variable prior to ME
start_me_refinement_hp = (input->ChromaMEEnable == 1 || input->MEErrorMetric[F_PEL] != input->MEErrorMetric[H_PEL] ) ? 0 : 1;
start_me_refinement_qp = (input->ChromaMEEnable == 1 || input->MEErrorMetric[H_PEL] != input->MEErrorMetric[Q_PEL] ) ? 0 : 1;
// Setup Distortion Metrics depending on refinement level
for (i=0; i<3; i++)
{
switch(input->MEErrorMetric[i])
{
case ERROR_SAD:
computeUniPred[i] = computeSAD;
computeUniPred[i + 3] = computeSADWP;
computeBiPred1[i] = computeBiPredSAD1;
computeBiPred2[i] = computeBiPredSAD2;
break;
case ERROR_SSE:
computeUniPred[i] = computeSSE;
computeUniPred[i + 3] = computeSSEWP;
computeBiPred1[i] = computeBiPredSSE1;
computeBiPred2[i] = computeBiPredSSE2;
break;
case ERROR_SATD :
default:
computeUniPred[i] = computeSATD;
computeUniPred[i + 3] = computeSATDWP;
computeBiPred1[i] = computeBiPredSATD1;
computeBiPred2[i] = computeBiPredSATD2;
break;
}
}
// Setup buffer access methods
get_line[0] = FastLine4X;
get_line[1] = UMVLine4X;
get_crline[0] = FastLine8X_chroma;
get_crline[1] = UMVLine8X_chroma;
if(input->SearchMode == FAST_FULL_SEARCH)
InitializeFastFullIntegerSearch ();
}
/*!
************************************************************************
* \brief
* Free memory used by motion search
************************************************************************
*/
void
Clear_Motion_Search_Module ()
{
//--- correct array offset ---
mvbits -= max_mvd;
byte_abs -= byte_abs_range/2;
//--- delete arrays ---
free (spiral_search_x);
free (spiral_search_y);
free (spiral_hpel_search_x);
free (spiral_hpel_search_y);
free (mvbits);
free (refbits);
free (byte_abs);
if (motion_cost)
free_mem4Dint (motion_cost, 8, 2);
if(input->SearchMode == FAST_FULL_SEARCH)
ClearFastFullIntegerSearch ();
}
/*!
***********************************************************************
* \brief
* Motion Cost for Bidirectional modes
***********************************************************************
*/
int BPredPartitionCost (Macroblock *currMB,
int blocktype,
int block8x8,
short ref_l0,
short ref_l1,
int lambda_factor,
int list)
{
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}};
int curr_blk[MB_BLOCK_SIZE][MB_BLOCK_SIZE]; // ABT pred.error buffer
int bsx = imin(input->blc_size[blocktype][0], 8);
int bsy = imin(input->blc_size[blocktype][1], 8);
int pic_pix_x, pic_pix_y, block_x, block_y;
int v, h, mcost, i, j, k;
int mvd_bits = 0;
int parttype = (blocktype < 4 ? blocktype : 4);
int step_h0 = (input->part_size[ parttype][0]);
int step_v0 = (input->part_size[ parttype][1]);
int step_h = (input->part_size[blocktype][0]);
int step_v = (input->part_size[blocktype][1]);
int bxx, byy; // indexing curr_blk
int by0_part = by0[parttype][block8x8];
int bx0_part = bx0[parttype][block8x8];
short ******all_mv = list ? img->bipred_mv1 : img->bipred_mv2;
short ****** p_mv = img->pred_mv;
imgpel (*curr_mpr)[16] = img->mpr[0];
for (v = by0_part; v < by0_part + step_v0; v += step_v)
{
for (h = bx0_part; h < bx0_part + step_h0; h += step_h)
{
mvd_bits += mvbits[ all_mv [v][h][LIST_0][ref_l0][blocktype][0] - p_mv[v][h][LIST_0][ref_l0][blocktype][0] ];
mvd_bits += mvbits[ all_mv [v][h][LIST_0][ref_l0][blocktype][1] - p_mv[v][h][LIST_0][ref_l0][blocktype][1] ];
mvd_bits += mvbits[ all_mv [v][h][LIST_1][ref_l1][blocktype][0] - p_mv[v][h][LIST_1][ref_l1][blocktype][0] ];
mvd_bits += mvbits[ all_mv [v][h][LIST_1][ref_l1][blocktype][1] - p_mv[v][h][LIST_1][ref_l1][blocktype][1] ];
}
}
mcost = WEIGHTED_COST (lambda_factor, mvd_bits);
//----- cost of residual signal -----
for (byy=0, v=by0_part; v < by0_part + step_v0; byy += 4, v++)
{
pic_pix_y = img->opix_y + (block_y = (v<<2));
for (bxx=0, h = bx0_part; h < bx0_part + step_h0; bxx += 4, h++)
{
pic_pix_x = img->opix_x + (block_x = (h<<2));
LumaPredictionBi (currMB, block_x, block_y, 4, 4, blocktype, blocktype, ref_l0, ref_l1, list);
for (k = j = 0; j < 4; j++)
{
for (i = 0; i < 4; i++)
diff64[k++] = curr_blk[byy+j][bxx+i] =
pCurImg[pic_pix_y+j][pic_pix_x+i] - curr_mpr[j+block_y][i+block_x];
}
if ((!input->Transform8x8Mode) || (blocktype>4))
{
mcost += distortion4x4 (diff64);
}
}
}
if (input->Transform8x8Mode && (blocktype<=4)) // tchen 4-29-04
{
for (byy=0; byy < input->blc_size[parttype][1]; byy += bsy)
for (bxx=0; bxx < input->blc_size[parttype][0]; bxx += bsx)
{
for (k=0, j = byy; j < byy + 8; j++, k += 8)
memcpy(&diff64[k], &(curr_blk[j][bxx]), 8 * sizeof(int));
mcost += distortion8x8(diff64);
}
}
return mcost;
}
/*!
***********************************************************************
* \brief
* Block motion search
***********************************************************************
*/
int //!< minimum motion cost after search
BlockMotionSearch (Macroblock *currMB, //!< Current Macroblock
short ref, //!< reference idx
int list, //!< reference picture list
int mb_x, //!< x-coordinate inside macroblock
int mb_y, //!< y-coordinate inside macroblock
int blocktype, //!< block type (1-16x16 ... 7-4x4)
int search_range, //!< 1-d search range for integer-position search
int* lambda_factor) //!< lagrangian parameter for determining motion cost
{
// each 48-pel line stores the 16 luma pels (at 0) followed by 8 or 16 crcb[0] (at 16) and crcb[1] (at 32) pels
// depending on the type of chroma subsampling used: YUV 4:4:4, 4:2:2, and 4:2:0
imgpel *orig_pic_tmp = orig_pic;
short mv[2];
int i, j;
int max_value = INT_MAX;
int min_mcost = max_value;
int block_x = (mb_x>>2);
int block_y = (mb_y>>2);
int bsx = input->blc_size[blocktype][0];
int bsy = input->blc_size[blocktype][1];
int pic_pix_x = img->opix_x + mb_x;
int pic_pix_y = img->opix_y + mb_y;
int pic_pix_x_c = pic_pix_x >> (shift_cr_x);
int pic_pix_y_c = pic_pix_y >> (shift_cr_y);
int bsx_c = bsx >> (shift_cr_x);
int bsy_c = bsy >> (shift_cr_y);
short* pred_mv = img->pred_mv[block_y][block_x][list][ref][blocktype];
short****** all_mv = img->all_mv;
int list_offset = ((img->MbaffFrameFlag) && (currMB->mb_field)) ? img->current_mb_nr % 2 ? 4 : 2 : 0;
int *prevSad = (input->SearchMode == EPZS)? EPZSDistortion[list + list_offset][blocktype - 1]: NULL;
#if GET_METIME
static struct TIMEB tstruct1;
static struct TIMEB tstruct2;
time_t me_tmp_time;
ftime( &tstruct1 ); // start time ms
#endif
//==================================
//===== GET ORIGINAL BLOCK =====
//==================================
for (j = pic_pix_y; j < pic_pix_y + bsy; j++)
{
memcpy(orig_pic_tmp,&pCurImg[j][pic_pix_x], bsx *sizeof(imgpel));
orig_pic_tmp += bsx;
}
ChromaMEEnable = input->ChromaMEEnable;
if ( ChromaMEEnable )
{
// copy the original cmp1 and cmp2 data to the orig_pic matrix
for ( i = 0; i<=1; i++)
{
orig_pic_tmp = orig_pic + (256 << i);
for (j = pic_pix_y_c; j < pic_pix_y_c + bsy_c; j++)
{
memcpy(orig_pic_tmp, &(imgUV_org[i][j][pic_pix_x_c]), bsx_c * sizeof(imgpel));
orig_pic_tmp += bsx_c;
}
}
}
if(input->SearchMode == UM_HEX)
{
UMHEX_blocktype = blocktype;
bipred_flag = 0;
}
else if (input->SearchMode == UM_HEX_SIMPLE)
{
smpUMHEX_setup(ref, list, block_y, block_x, blocktype, all_mv );
}
// Set if 8x8 transform will be used if SATD is used
test8x8transform = input->Transform8x8Mode && blocktype <= 4;
//===========================================
//===== GET MOTION VECTOR PREDICTOR =====
//===========================================
if (input->SearchMode == UM_HEX)
UMHEXSetMotionVectorPredictor(currMB, pred_mv, enc_picture->ref_idx[list], enc_picture->mv[list], ref, list, block_x, block_y, bsx, bsy, &search_range);
else
SetMotionVectorPredictor (currMB, pred_mv, enc_picture->ref_idx[list], enc_picture->mv[list], ref, list, block_x, block_y, bsx, bsy);
//==================================
//===== INTEGER-PEL SEARCH =====
//==================================
if (input->SearchMode == UM_HEX)
{
mv[0] = pred_mv[0] / 4;
mv[1] = pred_mv[1] / 4;
if (!input->rdopt)
{
//--- adjust search center so that the (0,0)-vector is inside ---
mv[0] = iClip3(-search_range, search_range, mv[0]);
mv[1] = iClip3(-search_range, search_range, mv[1]);
}
mv[0] = iClip3(-2047 + search_range, 2047 - search_range, mv[0]);
mv[1] = iClip3(LEVELMVLIMIT[img->LevelIndex][0] + search_range, LEVELMVLIMIT[img->LevelIndex][1] - search_range, mv[1]);
min_mcost = UMHEXIntegerPelBlockMotionSearch(orig_pic, ref, list, pic_pix_x, pic_pix_y, blocktype,
pred_mv[0], pred_mv[1], &mv[0], &mv[1], search_range,
min_mcost, lambda_factor[F_PEL]);
}
else if (input->SearchMode == UM_HEX_SIMPLE)
{
mv[0] = pred_mv[0] / 4;
mv[1] = pred_mv[1] / 4;
if (!input->rdopt)
{
//--- adjust search center so that the (0,0)-vector is inside ---
mv[0] = iClip3(-search_range, search_range, mv[0]);
mv[1] = iClip3(-search_range, search_range, mv[1]);
}
mv[0] = iClip3(-2047 + search_range, 2047 - search_range, mv[0]);
mv[1] = iClip3(LEVELMVLIMIT[img->LevelIndex][0] + search_range, LEVELMVLIMIT[img->LevelIndex][1] - search_range, mv[1]);
min_mcost = smpUMHEXIntegerPelBlockMotionSearch (orig_pic, ref, list, pic_pix_x, pic_pix_y, blocktype,
pred_mv[0], pred_mv[1], &mv[0], &mv[1], search_range,
min_mcost, lambda_factor[F_PEL]);
for (i=0; i < (bsx>>2); i++)
{
for (j=0; j < (bsy>>2); j++)
{
if(list == 0)
{
smpUMHEX_l0_cost[blocktype][(img->pix_y>>2)+block_y+j][(img->pix_x>>2)+block_x+i] = min_mcost;
}
else
{
smpUMHEX_l1_cost[blocktype][(img->pix_y>>2)+block_y+j][(img->pix_x>>2)+block_x+i] = min_mcost;
}
}
}
}
//--- perform motion search using EPZS schemes---
else if (input->SearchMode == EPZS)
{
//--- set search center ---
// This has to be modified in the future
if (input->EPZSSubPelGrid)
{
mv[0] = pred_mv[0];
mv[1] = pred_mv[1];
}
else
{
mv[0] = (pred_mv[0] + 2)>> 2;
mv[1] = (pred_mv[1] + 2)>> 2;
}
if (!input->rdopt)
{
//--- adjust search center so that the (0,0)-vector is inside ---
mv[0] = iClip3 (-search_range<<(input->EPZSGrid), search_range<<(input->EPZSGrid), mv[0]);
mv[1] = iClip3 (-search_range<<(input->EPZSGrid), search_range<<(input->EPZSGrid), mv[1]);
}
// valid search range limits could be precomputed once during the initialization process
mv[0] = iClip3((-2047 + search_range)<<(input->EPZSGrid), (2047 - search_range)<<(input->EPZSGrid), mv[0]);
mv[1] = iClip3((LEVELMVLIMIT[img->LevelIndex][0] + search_range)<<(input->EPZSGrid),
(LEVELMVLIMIT[img->LevelIndex][1] - search_range)<<(input->EPZSGrid), mv[1]);
min_mcost = EPZSPelBlockMotionSearch (currMB, orig_pic, ref, list, list_offset,
enc_picture->ref_idx, enc_picture->mv, pic_pix_x, pic_pix_y, blocktype,
pred_mv, mv, search_range<<(input->EPZSGrid), min_mcost, lambda_factor[F_PEL]);
}
else if (input->SearchMode == FAST_FULL_SEARCH)
{
// comments: - orig_pic is not used -> be careful
// - search center is automatically determined
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -