📄 umc_h264_me.cpp
字号:
}
if (mvy + padded_y + MBYoffset + sbheight >= height)
{
return PREDICTION_FROM_BOTTOM;
}
return ALLOK;
}
template <class PixType, class CoeffsType>
void H264CoreEncoder<PixType,CoeffsType>::Interpolate(const Ipp32s mb_decoding_flag,
const PixType* src,
Ipp32s src_pitch,
PixType* dst,
Ipp32s dst_pitch,
Ipp32s xh,
Ipp32s yh,
IppiSize sz,
Ipp32s mvy,
Ipp32s mb_y_pos,
Ipp32s sb_y_pos)
{
Ipp32s mbYOffset = (mb_y_pos >> mb_decoding_flag) + sb_y_pos; //m_CurMB_Y * 16 + sb_pos;
Ipp32s yint = mvy >> 2;
Ipp32s height = (m_HeightInMBs << 4) >> mb_decoding_flag;
Ipp8u pred_method = SelectPredictionMethod(
mbYOffset,
mvy,
sz.height,
height);
switch(pred_method)
{
case ALLOK:
ippiInterpolateLuma_H264(src, src_pitch*sizeof(PixType),
dst, dst_pitch*sizeof(PixType),
xh, yh, sz, m_PicParamSet.bit_depth_luma);
break;
case PREDICTION_FROM_TOP:
ippiInterpolateLumaTop_H264(src, src_pitch*sizeof(PixType),
dst, dst_pitch*sizeof(PixType),
xh, yh, - ((Ipp32s)mbYOffset + yint), sz, m_PicParamSet.bit_depth_luma);
break;
case PREDICTION_FROM_BOTTOM:
ippiInterpolateLumaBottom_H264(src, src_pitch*sizeof(PixType),
dst, dst_pitch*sizeof(PixType),
xh, yh, ((Ipp32s)mbYOffset + yint + sz.height) - (height), sz, m_PicParamSet.bit_depth_luma);
break;
default:
VM_ASSERT(false);
break;
}
}
template <class PixType, class CoeffsType>
void H264CoreEncoder<PixType,CoeffsType>::Interpolate_Cr(const Ipp32s mb_decoding_flag,
const PixType* src,
Ipp32s src_pitch,
PixType* dst,
Ipp32s dst_pitch,
Ipp32s xh,
Ipp32s yh,
IppiSize sz,
Ipp32s mvy,
Ipp32s mb_y_pos,
Ipp32s sb_y_pos)
{
Ipp32s mbYOffset = (mb_y_pos >> mb_decoding_flag) + sb_y_pos; //m_CurMB_Y * 16 + sb_pos;
Ipp32s yint = mvy >> 3;
Ipp32s height = (m_HeightInMBs << 4) >> mb_decoding_flag;
Ipp8u pred_method = SelectPredictionMethod(
mbYOffset,
mvy,
sz.height*2,
height);
switch(pred_method)
{
case ALLOK:
ippiInterpolateChroma_H264(src, src_pitch*sizeof(PixType),
dst, dst_pitch*sizeof(PixType),
xh, yh, sz, m_SeqParamSet.bit_depth_chroma);
break;
case PREDICTION_FROM_TOP:
ippiInterpolateChromaTop_H264(src, src_pitch*sizeof(PixType),
dst, dst_pitch*sizeof(PixType),
xh, yh, - ((Ipp32s)mbYOffset/2 + yint), sz, m_SeqParamSet.bit_depth_chroma);
break;
case PREDICTION_FROM_BOTTOM:
ippiInterpolateChromaBottom_H264(src, src_pitch*sizeof(PixType),
dst, dst_pitch*sizeof(PixType),
xh, yh, ((Ipp32s)mbYOffset/2 + yint + sz.height) - (height)/2, sz, m_SeqParamSet.bit_depth_chroma);
break;
default:
VM_ASSERT(false);
break;
}
}
////////////////////////////////////////////////////////////////////////////////
// FindBestInitialMV
// Return the best Initial 16x16 MV from the possible candidates:
////////////////////////////////////////////////////////////////////////////////
template <class PixType, class CoeffsType>
bool H264CoreEncoder<PixType,CoeffsType>::FindBestInitialMV(
H264EncoderThreadPrivateSlice<PixType, CoeffsType> *curr_slice,
const PixType* pCurrent,
const PixType* pPrev,
const Ipp32u uMB, // MB number
bool bBSlice,
H264MotionVector& BestMV16x16, // resulting Best MV
Ipp32s& uBestSAD16x16e, // resulting Best RD-Opt Distortion
Ipp32s& uBestSAD16x16NoRD, // resulting Distortion
H264MotionVector& PredictedMV, // return the 16x16 predicted vector
const Ipp32s xMin,
const Ipp32s xMax,
const Ipp32s yMin,
const Ipp32s yMax)
{
Ipp32s sad_16x16_full, sad_16x16;
bool is_done = true;
H264MotionVector mvs_pred[16];
H264MotionVector mv_delta;
H264EncoderFrame<PixType> *pPrevFrm = GetRefPicList(curr_slice, LIST_0,curr_slice->m_is_cur_mb_field,uMB&1)->m_RefPicList[0];
bool is_bwd_pred = (curr_slice->m_cur_mb.GlobalMacroblockInfo->mbtype == MBTYPE_BACKWARD);
Ipp32s list_num = is_bwd_pred ? LIST_1 : LIST_0;
Ipp32s iQP = getLumaQP51(curr_slice->m_cur_mb.LocalMacroblockInfo->QP, m_PicParamSet.bit_depth_luma);
Ipp16s* pRDQM = glob_RDQM[iQP];
Ipp32s mv_num = 1;
// TODO !!! Will improve Best of 5 for sliced images, by allowing Top/Left MVs to contend across slice boundaries, which is OK, since there is no
// dependency implied here. Particularly important since the Predictor will not be as good in these cases.
// zero vector
mvs_pred[0] = null_mv;
// predicted
//f Estimate_One_MV_Predictor(curr_slice, uMB, 0, is_bwd_pred, NULL, 4, 4, &PredictedMV, &mv_delta);
Calc_One_MV_Predictor(curr_slice, uMB, 0, is_bwd_pred, 4, 4, &PredictedMV, &mv_delta);
mvs_pred[1].mvx = (Ipp16s) (PredictedMV.mvx >> SUB_PEL_SHIFT);
mvs_pred[1].mvy = (Ipp16s) (PredictedMV.mvy >> SUB_PEL_SHIFT);
if (mvs_pred[1].mvx >= xMin && mvs_pred[1].mvx <= xMax && mvs_pred[1].mvy >= yMin && mvs_pred[1].mvy <= yMax) {
if (mvs_pred[1] != mvs_pred[0])
mv_num = 2;
}
// above MV
Ipp32s above_addr = curr_slice->m_cur_mb.CurrentMacroblockNeighbours.mb_B;
if (above_addr >= 0) {
const H264MotionVector &above = m_pCurrentFrame->m_mbinfo.MV[list_num][above_addr].MotionVectors[12];
mvs_pred[mv_num].mvx = above.mvx >> SUB_PEL_SHIFT;
mvs_pred[mv_num].mvy = above.mvy >> SUB_PEL_SHIFT;
if (mvs_pred[mv_num].mvx >= xMin && mvs_pred[mv_num].mvx <= xMax && mvs_pred[mv_num].mvy >= yMin && mvs_pred[mv_num].mvy <= yMax) {
for (Ipp32s i = 0; i < mv_num; i++) {
if (mvs_pred[mv_num] == mvs_pred[i]) {
mv_num --;
break;
}
}
mv_num++;
}
}
// left MV
Ipp32s left_addr = curr_slice->m_cur_mb.CurrentMacroblockNeighbours.mb_A;
if (left_addr >= 0) {
const H264MotionVector &left = m_pCurrentFrame->m_mbinfo.MV[list_num][left_addr].MotionVectors[3];
mvs_pred[mv_num].mvx = left.mvx >> SUB_PEL_SHIFT;
mvs_pred[mv_num].mvy = left.mvy >> SUB_PEL_SHIFT;
if (mvs_pred[mv_num].mvx >= xMin && mvs_pred[mv_num].mvx <= xMax && mvs_pred[mv_num].mvy >= yMin && mvs_pred[mv_num].mvy <= yMax) {
for (Ipp32s i = 0; i < mv_num; i++) {
if (mvs_pred[mv_num] == mvs_pred[i]) {
mv_num --;
break;
}
}
mv_num++;
}
}
// topleft MV
Ipp32s topleft_addr = curr_slice->m_cur_mb.CurrentMacroblockNeighbours.mb_D;
if (topleft_addr >= 0) {
const H264MotionVector &topleft = m_pCurrentFrame->m_mbinfo.MV[list_num][topleft_addr].MotionVectors[15];
mvs_pred[mv_num].mvx = topleft.mvx >> SUB_PEL_SHIFT;
mvs_pred[mv_num].mvy = topleft.mvy >> SUB_PEL_SHIFT;
if (mvs_pred[mv_num].mvx >= xMin && mvs_pred[mv_num].mvx <= xMax && mvs_pred[mv_num].mvy >= yMin && mvs_pred[mv_num].mvy <= yMax) {
for (Ipp32s i = 0; i < mv_num; i++) {
if (mvs_pred[mv_num] == mvs_pred[i]) {
mv_num --;
break;
}
}
mv_num++;
}
}
//f
// topright MV
if (curr_slice->m_CurMB_Y > 0 && curr_slice->m_CurMB_X < m_WidthInMBs - 1) {
Ipp32s topright_addr = uMB - m_WidthInMBs + 1;
const H264MotionVector &topright = m_pCurrentFrame->m_mbinfo.MV[list_num][topright_addr].MotionVectors[12];
mvs_pred[mv_num].mvx = topright.mvx >> SUB_PEL_SHIFT;
mvs_pred[mv_num].mvy = topright.mvy >> SUB_PEL_SHIFT;
if (mvs_pred[mv_num].mvx >= xMin && mvs_pred[mv_num].mvx <= xMax && mvs_pred[mv_num].mvy >= yMin && mvs_pred[mv_num].mvy <= yMax) {
for (Ipp32s i = 0; i < mv_num; i++) {
if (mvs_pred[mv_num] == mvs_pred[i]) {
mv_num --;
break;
}
}
mv_num++;
}
}
// ref bottom
if (curr_slice->m_CurMB_Y < m_HeightInMBs - 1) {
Ipp32s bottom_addr = uMB + m_WidthInMBs;
const H264MotionVector &bottom = pPrevFrm->m_mbinfo.MV[LIST_0][bottom_addr].MotionVectors[0];
if (!bBSlice) {
mvs_pred[mv_num] = bottom;
} else {
// Forward vector, needs to be scaled, but direction is correct
const Ipp32s uFwdRatio = curr_slice->DistScaleFactorMV[0];
const Ipp32s TR_RND = (1 << (TR_SHIFT - 1));
mvs_pred[mv_num].mvx = (Ipp16s) ((uFwdRatio * bottom.mvx + TR_RND) >> TR_SHIFT);
mvs_pred[mv_num].mvy = (Ipp16s) ((uFwdRatio * bottom.mvy + TR_RND) >> TR_SHIFT);
if (is_bwd_pred) {
// Backward vector, needs both scaling and direction changed derived the backward MV from the reference MV: MVb = MVf-MV = -(1-r1)*MV
mvs_pred[mv_num].mvx = (Ipp16s)(mvs_pred[mv_num].mvx - bottom.mvx);
mvs_pred[mv_num].mvy = (Ipp16s)(mvs_pred[mv_num].mvy - bottom.mvy);
}
}
mvs_pred[mv_num].mvx = bottom.mvx >> SUB_PEL_SHIFT;
mvs_pred[mv_num].mvy = bottom.mvy >> SUB_PEL_SHIFT;
if (mvs_pred[mv_num].mvx >= xMin && mvs_pred[mv_num].mvx <= xMax && mvs_pred[mv_num].mvy >= yMin && mvs_pred[mv_num].mvy <= yMax) {
for (Ipp32s i = 0; i < mv_num; i++) {
if (mvs_pred[mv_num] == mvs_pred[i]) {
mv_num --;
break;
}
}
mv_num++;
}
}
// This code properly selects and scales a MV from the reference frame(s)
H264MotionVector fwd_mv = pPrevFrm->m_mbinfo.MV[LIST_0][uMB].MotionVectors[0];
if (!bBSlice) {
mvs_pred[mv_num] = fwd_mv;
} else {
// Forward vector, needs to be scaled, but direction is correct
const Ipp32s uFwdRatio = curr_slice->DistScaleFactorMV[0];
const Ipp32s TR_RND = (1 << (TR_SHIFT - 1));
mvs_pred[mv_num].mvx = (Ipp16s) ((uFwdRatio * fwd_mv.mvx + TR_RND) >> TR_SHIFT);
mvs_pred[mv_num].mvy = (Ipp16s) ((uFwdRatio * fwd_mv.mvy + TR_RND) >> TR_SHIFT);
if (is_bwd_pred) {
// Backward vector, needs both scaling and direction changed derived the backward MV from the reference MV: MVb = MVf-MV = -(1-r1)*MV
mvs_pred[mv_num].mvx = (Ipp16s)(mvs_pred[mv_num].mvx - fwd_mv.mvx);
mvs_pred[mv_num].mvy = (Ipp16s)(mvs_pred[mv_num].mvy - fwd_mv.mvy);
}
}
// truncate motion vector
Ipp32s frm_width = m_WidthInMBs << 4;
Ipp32s frm_height = m_HeightInMBs << 4;
Ipp32s posx = curr_slice->m_CurMB_X*16;
Ipp32s posy = curr_slice->m_CurMB_Y*16;
TRUNCATE_LO(mvs_pred[mv_num].mvx, (frm_width - posx + 1) << SUB_PEL_SHIFT);
TRUNCATE_HI(mvs_pred[mv_num].mvx, (-16 - posx - 1) << SUB_PEL_SHIFT);
TRUNCATE_LO(mvs_pred[mv_num].mvy, (frm_height - posy + 1) << SUB_PEL_SHIFT);
TRUNCATE_HI(mvs_pred[mv_num].mvy, (-16 - posy - 1) << SUB_PEL_SHIFT);
// Scale to Integer Pel
mvs_pred[mv_num].mvx >>= SUB_PEL_SHIFT;
mvs_pred[mv_num].mvy >>= SUB_PEL_SHIFT;
if (mvs_pred[mv_num].mvx >= xMin && mvs_pred[mv_num].mvx <= xMax && mvs_pred[mv_num].mvy >= yMin && mvs_pred[mv_num].mvy <= yMax) {
for (Ipp32s i = 0; i < mv_num; i++) {
if (mvs_pred[mv_num] == mvs_pred[i]) {
mv_num --;
break;
}
}
mv_num++;
}
do {
// Begin tests to determine which of the 5 MVs is the best starting point...
Ipp32s pitchPixels = m_pCurrentFrame->pitchPixels()<<curr_slice->m_is_cur_mb_field;
// start with zero vector
BestMV16x16 = null_mv;
// do not need expand interpolation
uBestSAD16x16NoRD = SAD16x16(pCurrent, pitchPixels*sizeof(PixType), pPrev, pitchPixels*sizeof(PixType));
uBestSAD16x16e = uBestSAD16x16NoRD + MVConstraint(0 - PredictedMV.mvx, 0 - PredictedMV.mvy, pRDQM);
// If the zero vector is the predicted vector, then give it preference to encourage skip blocks in P slices.
//f if (PredictedMV.is_zero() && !bBSlice)
//f uBestSAD16x16e -= BITS_COST(6, glob_RDQM[iQP]);
#if defined BESTOF5_EARLY_EXIT
// Consider the best of five mv is good enough if the effective SAD is less than the given threshold.
if (uBestSAD16x16e <= m_BestOf5EarlyExitThres[iQP]) {
if (uBestSAD16x16e < 0)
uBestSAD16x16e = 0;
break;
}
#else
// Skip if sad < 0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -