📄 estimation_rd_based_bvop.c
字号:
ReferenceB = GetReferenceB(xb, yb, 1, data);
current = data->currentMV + Direction - 1;
xcf = xf; ycf = yf;
xcb = xb; ycb = yb;
} else {
ReferenceF = xvid_me_interpolate16x16qpel(xf, yf, 0, data);
current = data->currentQMV + Direction - 1;
ReferenceB = xvid_me_interpolate16x16qpel(xb, yb, 1, data);
xcf = xf/2; ycf = yf/2;
xcb = xb/2; ycb = yb/2;
}
rd += BITS_MULT * (d_mv_bits(xf, yf, data->predMV, data->iFcode, data->qpel^data->qpel_precision)
+ d_mv_bits(xb, yb, data->bpredMV, data->iFcode, data->qpel^data->qpel_precision));
for(i = 0; i < 4; i++) {
int s = 8*((i&1) + (i>>1)*data->iEdgedWidth);
if (rd >= *data->iMinSAD) return;
transfer_8to16sub2ro(in, data->Cur + s, ReferenceF + s, ReferenceB + s, data->iEdgedWidth);
rd += Block_CalcBits_BVOP(coeff, in, data->dctSpace + 128, data->iQuant, data->quant_type, &cbp,
i, data->scan_table, data->lambda[i], data->mpeg_quant_matrices,
data->quant_sq, &cbpcost);
}
/* chroma */
xcf = (xcf >> 1) + roundtab_79[xcf & 0x3];
ycf = (ycf >> 1) + roundtab_79[ycf & 0x3];
xcb = (xcb >> 1) + roundtab_79[xcb & 0x3];
ycb = (ycb >> 1) + roundtab_79[ycb & 0x3];
/* chroma U */
ReferenceF = interpolate8x8_switch2(data->RefQ, data->RefP[4], 0, 0, xcf, ycf, data->iEdgedWidth/2, data->rounding);
ReferenceB = interpolate8x8_switch2(data->RefQ + 16, data->b_RefP[4], 0, 0, xcb, ycb, data->iEdgedWidth/2, data->rounding);
transfer_8to16sub2ro(in, data->CurU, ReferenceF, ReferenceB, data->iEdgedWidth/2);
rd += Block_CalcBits_BVOP(coeff, in, data->dctSpace + 128, data->iQuant, data->quant_type, &cbp,
4, data->scan_table, data->lambda[4], data->mpeg_quant_matrices,
data->quant_sq, &cbpcost);
if (rd >= data->iMinSAD[0]) return;
/* chroma V */
ReferenceF = interpolate8x8_switch2(data->RefQ, data->RefP[5], 0, 0, xcf, ycf, data->iEdgedWidth/2, data->rounding);
ReferenceB = interpolate8x8_switch2(data->RefQ + 16, data->b_RefP[5], 0, 0, xcb, ycb, data->iEdgedWidth/2, data->rounding);
transfer_8to16sub2ro(in, data->CurV, ReferenceF, ReferenceB, data->iEdgedWidth/2);
rd += Block_CalcBits_BVOP(coeff, in, data->dctSpace + 128, data->iQuant, data->quant_type, &cbp,
5, data->scan_table, data->lambda[5], data->mpeg_quant_matrices,
data->quant_sq, &cbpcost);
if (rd < *(data->iMinSAD)) {
*data->iMinSAD = rd;
current->x = x; current->y = y;
data->dir = Direction;
*data->cbp = cbp;
}
}
static int
SearchInterpolate_RD(const int x, const int y,
const uint32_t MotionFlags,
const MBParam * const pParam,
int32_t * const best_sad,
SearchData * const Data)
{
int i, j;
Data->iMinSAD[0] = *best_sad;
get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy,
x, y, 4, pParam->width, pParam->height, Data->iFcode, 1 + Data->qpel);
Data->qpel_precision = Data->qpel;
if (Data->qpel) {
i = Data->currentQMV[0].x; j = Data->currentQMV[0].y;
} else {
i = Data->currentMV[0].x; j = Data->currentMV[0].y;
}
CheckCandidateRDInt(i, j, Data, 1);
return Data->iMinSAD[0];
}
static int
SearchDirect_RD(const int x, const int y,
const uint32_t MotionFlags,
const MBParam * const pParam,
int32_t * const best_sad,
SearchData * const Data)
{
Data->iMinSAD[0] = *best_sad;
Data->qpel_precision = Data->qpel;
CheckCandidateRDDirect(Data->currentMV->x, Data->currentMV->y, Data, 255);
return Data->iMinSAD[0];
}
static int
SearchBF_RD(const int x, const int y,
const uint32_t MotionFlags,
const MBParam * const pParam,
int32_t * const best_sad,
SearchData * const Data)
{
int i, j;
Data->iMinSAD[0] = *best_sad;
get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy,
x, y, 4, pParam->width, pParam->height, Data->iFcode, 1 + Data->qpel);
Data->qpel_precision = Data->qpel;
if (Data->qpel) {
i = Data->currentQMV[0].x; j = Data->currentQMV[0].y;
} else {
i = Data->currentMV[0].x; j = Data->currentMV[0].y;
}
CheckCandidateRDBF(i, j, Data, 1);
return Data->iMinSAD[0];
}
static int
get_sad_for_mode(int mode,
SearchData * const Data_d,
SearchData * const Data_b,
SearchData * const Data_f,
SearchData * const Data_i)
{
switch(mode) {
case MODE_DIRECT: return Data_d->iMinSAD[0];
case MODE_FORWARD: return Data_f->iMinSAD[0];
case MODE_BACKWARD: return Data_b->iMinSAD[0];
default:
case MODE_INTERPOLATE: return Data_i->iMinSAD[0];
}
}
void
ModeDecision_BVOP_RD(SearchData * const Data_d,
SearchData * const Data_b,
SearchData * const Data_f,
SearchData * const Data_i,
MACROBLOCK * const pMB,
const MACROBLOCK * const b_mb,
VECTOR * f_predMV,
VECTOR * b_predMV,
const uint32_t MotionFlags,
const MBParam * const pParam,
int x, int y,
int best_sad)
{
int mode = MODE_DIRECT, k;
int f_rd, b_rd, i_rd, d_rd, best_rd;
const int qpel = Data_d->qpel;
const uint32_t iQuant = Data_d->iQuant;
int i;
int ref_quant = b_mb->quant;
int no_of_checks = 0;
int order[4] = {MODE_DIRECT, MODE_FORWARD, MODE_BACKWARD, MODE_INTERPOLATE};
Data_d->scan_table = Data_b->scan_table = Data_f->scan_table = Data_i->scan_table
= /*VopFlags & XVID_VOP_ALTERNATESCAN ? scan_tables[2] : */scan_tables[0];
*Data_f->cbp = *Data_b->cbp = *Data_i->cbp = *Data_d->cbp = 63;
f_rd = b_rd = i_rd = d_rd = best_rd = 256*4096;
for (i = 0; i < 6; i++) {
/* re-calculate as if it was p-frame's quant +.5 */
int lam = (pMB->lambda[i]*LAMBDA*iQuant*iQuant)/(ref_quant*(ref_quant+1));
lam >>= LAMBDA_EXP;
Data_d->lambda[i] = lam;
Data_b->lambda[i] = lam;
Data_f->lambda[i] = lam;
Data_i->lambda[i] = lam;
}
/* find the best order of evaluation - smallest SAD comes first, because *if* it means smaller RD,
early-stops will activate sooner */
for (i = 3; i >= 0; i--) {
int j;
for (j = 0; j < i; j++) {
int sad1 = get_sad_for_mode(order[j], Data_d, Data_b, Data_f, Data_i);
int sad2 = get_sad_for_mode(order[j+1], Data_d, Data_b, Data_f, Data_i);
if (sad1 > sad2) {
int t = order[j];
order[j] = order[j+1];
order[j+1] = t;
}
}
}
for(i = 0; i < 4; i++)
if (get_sad_for_mode(order[i], Data_d, Data_b, Data_f, Data_i) < 2*best_sad)
no_of_checks++;
if (no_of_checks > 1) {
/* evaluate cost of all modes */
for (i = 0; i < no_of_checks; i++) {
int rd;
if (2*best_sad < get_sad_for_mode(order[i], Data_d, Data_b, Data_f, Data_i))
break; /* further SADs are too big */
switch (order[i]) {
case MODE_DIRECT:
rd = d_rd = SearchDirect_RD(x, y, MotionFlags, pParam, &best_rd, Data_d);
break;
case MODE_FORWARD:
rd = f_rd = SearchBF_RD(x, y, MotionFlags, pParam, &best_rd, Data_f) + 1*BITS_MULT; /* extra one bit for FORWARD vs BACKWARD */
break;
case MODE_BACKWARD:
rd = b_rd = SearchBF_RD(x, y, MotionFlags, pParam, &best_rd, Data_b);
break;
default:
case MODE_INTERPOLATE:
rd = i_rd = SearchInterpolate_RD(x, y, MotionFlags, pParam, &best_rd, Data_i);
break;
}
if (rd < best_rd) {
mode = order[i];
best_rd = rd;
}
}
} else {
/* only 1 mode is below the threshold */
mode = order[0];
best_rd = 0;
}
pMB->sad16 = best_rd;
pMB->mode = mode;
switch (mode) {
case MODE_DIRECT:
if (!qpel && b_mb->mode != MODE_INTER4V) pMB->mode = MODE_DIRECT_NO4V; /* for faster compensation */
pMB->pmvs[3] = Data_d->currentMV[0];
pMB->cbp = *Data_d->cbp;
for (k = 0; k < 4; k++) {
pMB->mvs[k].x = Data_d->directmvF[k].x + Data_d->currentMV->x;
pMB->b_mvs[k].x = ( (Data_d->currentMV->x == 0)
? Data_d->directmvB[k].x
:pMB->mvs[k].x - Data_d->referencemv[k].x);
pMB->mvs[k].y = (Data_d->directmvF[k].y + Data_d->currentMV->y);
pMB->b_mvs[k].y = ((Data_d->currentMV->y == 0)
? Data_d->directmvB[k].y
: pMB->mvs[k].y - Data_d->referencemv[k].y);
if (qpel) {
pMB->qmvs[k].x = pMB->mvs[k].x; pMB->mvs[k].x /= 2;
pMB->b_qmvs[k].x = pMB->b_mvs[k].x; pMB->b_mvs[k].x /= 2;
pMB->qmvs[k].y = pMB->mvs[k].y; pMB->mvs[k].y /= 2;
pMB->b_qmvs[k].y = pMB->b_mvs[k].y; pMB->b_mvs[k].y /= 2;
}
if (b_mb->mode != MODE_INTER4V) {
pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0];
pMB->b_mvs[3] = pMB->b_mvs[2] = pMB->b_mvs[1] = pMB->b_mvs[0];
pMB->qmvs[3] = pMB->qmvs[2] = pMB->qmvs[1] = pMB->qmvs[0];
pMB->b_qmvs[3] = pMB->b_qmvs[2] = pMB->b_qmvs[1] = pMB->b_qmvs[0];
break;
}
}
break;
case MODE_FORWARD:
if (qpel) {
pMB->pmvs[0].x = Data_f->currentQMV->x - f_predMV->x;
pMB->pmvs[0].y = Data_f->currentQMV->y - f_predMV->y;
pMB->qmvs[0] = *Data_f->currentQMV;
*f_predMV = Data_f->currentQMV[0];
} else {
pMB->pmvs[0].x = Data_f->currentMV->x - f_predMV->x;
pMB->pmvs[0].y = Data_f->currentMV->y - f_predMV->y;
*f_predMV = Data_f->currentMV[0];
}
pMB->mvs[0] = *Data_f->currentMV;
pMB->cbp = *Data_f->cbp;
pMB->b_mvs[0] = *Data_b->currentMV; /* hint for future searches */
break;
case MODE_BACKWARD:
if (qpel) {
pMB->pmvs[0].x = Data_b->currentQMV->x - b_predMV->x;
pMB->pmvs[0].y = Data_b->currentQMV->y - b_predMV->y;
pMB->b_qmvs[0] = *Data_b->currentQMV;
*b_predMV = Data_b->currentQMV[0];
} else {
pMB->pmvs[0].x = Data_b->currentMV->x - b_predMV->x;
pMB->pmvs[0].y = Data_b->currentMV->y - b_predMV->y;
*b_predMV = Data_b->currentMV[0];
}
pMB->b_mvs[0] = *Data_b->currentMV;
pMB->cbp = *Data_b->cbp;
pMB->mvs[0] = *Data_f->currentMV; /* hint for future searches */
break;
case MODE_INTERPOLATE:
pMB->mvs[0] = Data_i->currentMV[0];
pMB->b_mvs[0] = Data_i->currentMV[1];
if (qpel) {
pMB->qmvs[0] = Data_i->currentQMV[0];
pMB->b_qmvs[0] = Data_i->currentQMV[1];
pMB->pmvs[1].x = pMB->qmvs[0].x - f_predMV->x;
pMB->pmvs[1].y = pMB->qmvs[0].y - f_predMV->y;
pMB->pmvs[0].x = pMB->b_qmvs[0].x - b_predMV->x;
pMB->pmvs[0].y = pMB->b_qmvs[0].y - b_predMV->y;
*f_predMV = Data_i->currentQMV[0];
*b_predMV = Data_i->currentQMV[1];
} else {
pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x;
pMB->pmvs[1].y = pMB->mvs[0].y - f_predMV->y;
pMB->pmvs[0].x = pMB->b_mvs[0].x - b_predMV->x;
pMB->pmvs[0].y = pMB->b_mvs[0].y - b_predMV->y;
*f_predMV = Data_i->currentMV[0];
*b_predMV = Data_i->currentMV[1];
}
pMB->cbp = *Data_i->cbp;
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -