mv-search.c
来自「the newest JM software by h.264 JVT offi」· C语言 代码 · 共 1,857 行 · 第 1/5 页
C
1,857 行
{
mcost += distortion4x4 (diff64);
}
}
}
if (params->Transform8x8Mode && (blocktype<=4)) // tchen 4-29-04
{
for (byy=0; byy < params->blc_size[parttype][1]; byy += bsy)
for (bxx=0; bxx < params->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
static PixelPos block_a, block_b, block_c, block_d; // neighbor blocks
imgpel *orig_pic_tmp = orig_pic;
int apply_bi_weights = params->UseWeightedReferenceME && ((img->type == B_SLICE) && active_pps->weighted_bipred_idc != 0);
int apply_weights = params->UseWeightedReferenceME &&
((active_pps->weighted_pred_flag && (img->type == P_SLICE || img->type == SP_SLICE)) || apply_bi_weights);
short pred_mv[2];
MotionVector mv, pred;
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 = params->blc_size[blocktype][0];
int bsy = params->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*** all_mv = &img->all_mv[list][ref][blocktype][block_y];
PicMotionParams *motion = &enc_picture->motion;
int *prevSad = (params->SearchMode == EPZS)? EPZSDistortion[list + currMB->list_offset][blocktype - 1]: NULL;
get_neighbors(currMB, &block_a, &block_b, &block_c, &block_d, mb_x, mb_y, bsx);
PrepareMEParams(apply_weights, params->ChromaMEEnable, list + currMB->list_offset, ref);
//==================================
//===== 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 = params->ChromaMEEnable;
if ( ChromaMEEnable )
{
// copy the original cmp1 and cmp2 data to the orig_pic matrix
for ( i = 1; i<=2; i++)
{
orig_pic_tmp = orig_pic + (256 << (i - 1));
for (j = pic_pix_y_c; j < pic_pix_y_c + bsy_c; j++)
{
memcpy(orig_pic_tmp, &(pImgOrg[i][j][pic_pix_x_c]), bsx_c * sizeof(imgpel));
orig_pic_tmp += bsx_c;
}
}
}
if (params->SearchMode == UM_HEX)
{
UMHEX_blocktype = blocktype;
bipred_flag = 0;
}
else if (params->SearchMode == UM_HEX_SIMPLE)
{
smpUMHEX_setup(ref, list, block_y, block_x, blocktype, img->all_mv );
}
//===========================================
//===== GET MOTION VECTOR PREDICTOR =====
//===========================================
if (params->SearchMode == UM_HEX)
UMHEXSetMotionVectorPredictor(currMB, pred_mv, motion->ref_idx[list], motion->mv[list], ref, list, mb_x, mb_y, bsx, bsy, &search_range);
else
GetMotionVectorPredictor (currMB, &block_a, &block_b, &block_c, pred_mv, motion->ref_idx[list], motion->mv[list], ref, mb_x, mb_y, bsx, bsy);
pred.mv_x = pred_mv[0];
pred.mv_y = pred_mv[1];
//==================================
//===== INTEGER-PEL SEARCH =====
//==================================
if (params->EPZSSubPelGrid)
{
mv = pred;
}
else
{
mv.mv_x = (pred.mv_x + 2)>> 2;
mv.mv_y = (pred.mv_y + 2)>> 2;
}
if (!params->rdopt)
{
//--- adjust search center so that the (0,0)-vector is inside ---
mv.mv_x = iClip3 (-search_range<<(params->EPZSGrid), search_range<<(params->EPZSGrid), mv.mv_x);
mv.mv_y = iClip3 (-search_range<<(params->EPZSGrid), search_range<<(params->EPZSGrid), mv.mv_y);
}
// valid search range limits could be precomputed once during the initialization process
clip_mv_range(img, search_range, &mv, params->EPZSGrid);
//--- perform motion search ---
min_mcost = IntPelME (currMB, orig_pic, ref, list,
motion->ref_idx, motion->mv, pic_pix_x, pic_pix_y, blocktype,
&pred, &mv, search_range<<(params->EPZSGrid), min_mcost, lambda_factor[F_PEL], apply_weights);
//===== convert search center to quarter-pel units =====
if (params->EPZSSubPelGrid == 0 || params->SearchMode != EPZS)
{
mv.mv_x <<= 2;
mv.mv_y <<= 2;
}
//==============================
//===== SUB-PEL SEARCH =====
//==============================
ChromaMEEnable = (params->ChromaMEEnable == ME_YUV_FP_SP ) ? 1 : 0; // set it externally
if (!params->DisableSubpelME)
{
if (params->SearchMode != EPZS || (ref == 0 || img->structure != FRAME || (ref > 0 && min_mcost < 3.5 * prevSad[pic_pix_x >> 2])))
{
if ( !start_me_refinement_hp )
{
min_mcost = max_value;
}
min_mcost = SubPelME (orig_pic, ref, list, currMB->list_offset, pic_pix_x, pic_pix_y, blocktype,
&pred, &mv, 9, 9, min_mcost, lambda_factor, apply_weights);
}
}
// clip mvs after me is performed (is not exactly the best)
// better solution is to modify search window appropriately
clip_mv_range(img, 0, &mv, Q_PEL);
if (!params->rdopt)
{
// Get the skip mode cost
if (blocktype == 1 && (img->type == P_SLICE||img->type == SP_SLICE))
{
int cost;
FindSkipModeMotionVector (currMB);
cost = GetSkipCostMB (currMB);
cost -= ((lambda_factor[Q_PEL] + 4096) >> 13);
if (cost < min_mcost)
{
min_mcost = cost;
mv.mv_x = img->all_mv [0][0][0][0][0][0];
mv.mv_y = img->all_mv [0][0][0][0][0][1];
}
}
}
//===============================================
//===== SET MV'S AND RETURN MOTION COST =====
//===============================================
// Set first line
for (i=block_x; i < block_x + (bsx>>2); i++)
{
all_mv[0][i][0] = mv.mv_x;
all_mv[0][i][1] = mv.mv_y;
}
// set all other lines
for (j=1; j < (bsy>>2); j++)
{
memcpy(all_mv[j][block_x], all_mv[0][block_x], (bsx>>2) * 2 * sizeof(short));
}
// Bipred ME consideration: returns minimum bipred cost
if (img->type == B_SLICE && is_bipred_enabled(blocktype) && (ref == 0))
{
BiPredBlockMotionSearch(currMB, &mv, &pred, ref, list, mb_x, mb_y, blocktype, search_range, apply_bi_weights, lambda_factor);
}
return min_mcost;
}
/*!
***********************************************************************
* \brief
* Bi-predictive motion search
***********************************************************************
*/
int BiPredBlockMotionSearch(Macroblock *currMB, //!< Current Macroblock
MotionVector *mv, //!< current list motion vector
MotionVector *pred_mv, //!< current list motion vector predictor
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 apply_bi_weights, //!< apply bipred weights
int* lambda_factor) //!< lagrangian parameter for determining motion cost
{
int iteration_no, i, j;
short bipred_type = list ? 0 : 1;
short****** bipred_mv = img->bipred_mv[bipred_type];
int min_mcostbi = INT_MAX;
MotionVector bimv, tempmv;
MotionVector pred_mv1, pred_mv2, pred_bi;
MotionVector bi_mv1, bi_mv2;
short iterlist=list;
short pred_mv_bi[2];
int block_x = (mb_x>>2);
int block_y = (mb_y>>2);
int bsx = params->blc_size[blocktype][0];
int bsy = params->blc_size[blocktype][1];
int pic_pix_x = img->opix_x + mb_x;
int pic_pix_y = img->opix_y + mb_y;
static PixelPos block_a, block_b, block_c, block_d; // neighbor blocks
PicMotionParams *motion = &enc_picture->motion;
get_neighbors(currMB, &block_a, &block_b, &block_c, &block_d, mb_x, mb_y, bsx);
if (params->SearchMode == UM_HEX)
{
bipred_flag = 1;
UMHEXSetMotionVectorPredictor(currMB, pred_mv_bi, motion->ref_idx[list ^ 1], motion->mv[list ^ 1], 0, list ^ 1, mb_x, mb_y, bsx, bsy, &search_range);
}
else
GetMotionVectorPredictor (currMB, &block_a, &block_b, &block_c, pred_mv_bi, motion->ref_idx[list ^ 1], motion->mv[list ^ 1], 0, mb_x, mb_y, bsx, bsy);
pred_bi.mv_x = pred_mv_bi[0];
pred_bi.mv_y = pred_mv_bi[1];
if ((params->SearchMode != EPZS) || (params->EPZSSubPelGrid == 0))
{
mv->mv_x = (mv->mv_x + 2) >> 2;
mv->mv_y = (mv->mv_y + 2) >> 2;
bimv.mv_x = (pred_bi.mv_x + 2)>>2;
bimv.mv_y = (pred_bi.mv_y + 2)>>2;
}
else
{
bimv = pred_bi;
}
//Bi-predictive motion Refinements
for (iteration_no = 0; iteration_no <= params->BiPredMERefinements; iteration_no++)
{
if (iteration_no & 0x01)
{
pred_mv1 = *pred_mv;
pred_mv2 = pred_bi;
bi_mv1 = *mv;
bi_mv2 = bimv;
iterlist = list;
}
else
{
pred_mv1 = pred_bi;
pred_mv2 = *pred_mv;
bi_mv1 = bimv;
bi_mv2 = *mv;
iterlist = list ^ 1;
}
tempmv = bi_mv1;
PrepareBiPredMEParams(apply_bi_weights, ChromaMEEnable, iterlist, currMB->list_offset, ref);
// Get bipred mvs for list iterlist given previously computed mvs from other list
min_mcostbi = BiPredME (currMB, orig_pic, ref, iterlist, motion->ref_idx, motion->mv,
pic_pix_x, pic_pix_y, blocktype, &pred_mv1, &pred_mv2, &bi_mv1, &bi_mv2,
(params->BiPredMESearchRange <<(params->EPZSGrid))>>iteration_no, min_mcostbi, iteration_no, lambda_factor[F_PEL], apply_bi_weights);
if (iteration_no > 0 && (tempmv.mv_x == bi_mv1.mv_x) && (tempmv.mv_y == bi_mv1.mv_y))
{
break;
}
}
if ((params->SearchMode != EPZS) || (params->EPZSSubPelGrid == 0))
{
bi_mv2.mv_x = (bi_mv2.mv_x << 2);
bi_mv2.mv_y = (bi_mv2.mv_y << 2);
bi_mv1.mv_x = (bi_mv1.mv_x << 2);
bi_mv1.mv_y = (bi_mv1.mv_y << 2);
}
if (!params->DisableSubpelME)
{
if (params->BiPredMESubPel)
{
min_mcostbi = INT_MAX;
PrepareBiPredMEParams(apply_bi_weights, ChromaMEEnable, iterlist, currMB->list_offset, ref);
min_mcostbi = SubPelBiPredME (orig_pic, ref, iterlist, pic_pix_x, pic_pix_y, blocktype,
&pred_mv1, &pred_mv2, &bi_mv1, &bi_mv2, 9, 9, min_mcostbi, lambda_factor, apply_bi_weights);
}
if (params->BiPredMESubPel==2)
{
min_mcostbi = INT_MAX;
PrepareBiPredMEParams(apply_bi_weights, ChromaMEEnable, iterlist ^ 1, currMB->list_offset, ref);
min_mcostbi = SubPelBiPredME (orig_pic, ref, iterlist ^ 1, pic_pix_x, pic_pix_y, blocktype,
&pred_mv2, &pred_mv1, &bi_mv2, &bi_mv1, 9, 9, min_mcostbi, lambda_factor, apply_bi_weights);
}
}
clip_mv_range(img, 0, &bi_mv1, Q_PEL);
clip_mv_range(img, 0, &bi_mv2, Q_PEL);
for (j=block_y; j < block_y + (bsy>>2); j++)
{
for (i=block_x ; i < block_x + (bsx>>2); i++)
{
bipred_mv[iterlist ][ref][blocktype][j][i][0] = bi_mv1.mv_x;
bipred_mv[iterlist ][ref][blocktype][j][i][1] = bi_mv1.mv_y;
bipred_mv[iterlist ^ 1][ref][blocktype][j][i][0] = bi_mv2.mv_x;
bipred_mv[iterlist ^ 1][ref][blocktype][j][i][1] = bi_mv2.mv_y;
}
}
return min_mcostbi;
}
/*!
***********************************************************************
* \brief
* Motion Cost for Bidirectional modes
***********************************************************************
*/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?