📄 estimation_bvop.c
字号:
int32_t * const best_sad,
const int32_t mode_current,
SearchData * const Data,
VECTOR hint)
{
int i;
VECTOR pmv[7];
*Data->iMinSAD = MV_MAX_ERROR;
Data->qpel_precision = 0;
Data->predMV = *predMV;
get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 4,
pParam->width, pParam->height, iFcode - Data->qpel, 1);
pmv[0] = Data->predMV;
if (Data->qpel) {
pmv[0].x /= 2; pmv[0].y /= 2;
hint.x /= 2; hint.y /= 2;
}
PreparePredictionsBF(pmv, x, y, pParam->mb_width, pMB, mode_current, hint);
Data->currentMV->x = Data->currentMV->y = 0;
/* main loop. checking all predictions */
for (i = 0; i < 7; i++)
if (!vector_repeats(pmv, i) )
CheckCandidate16no4v(pmv[i].x, pmv[i].y, Data, i);
if (*Data->iMinSAD > 512) {
unsigned int mask = make_mask(pmv, 7, Data->dir);
MainSearchFunc *MainSearchPtr;
if (MotionFlags & XVID_ME_USESQUARES16) MainSearchPtr = xvid_me_SquareSearch;
else if (MotionFlags & XVID_ME_ADVANCEDDIAMOND16) MainSearchPtr = xvid_me_AdvDiamondSearch;
else MainSearchPtr = xvid_me_DiamondSearch;
MainSearchPtr(Data->currentMV->x, Data->currentMV->y, Data, mask, CheckCandidate16no4v);
}
if (Data->iMinSAD[0] < *best_sad) *best_sad = Data->iMinSAD[0];
}
static void
SearchBF_final(const int x, const int y,
const uint32_t MotionFlags,
const MBParam * const pParam,
int32_t * const best_sad,
SearchData * const Data)
{
if(!Data->qpel) {
/* halfpel mode */
if (MotionFlags & XVID_ME_HALFPELREFINE16)
xvid_me_SubpelRefine(Data->currentMV[0], Data, CheckCandidate16no4v, 0);
} else {
/* qpel mode */
if(MotionFlags & XVID_ME_FASTREFINE16) {
/* fast */
get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 4,
pParam->width, pParam->height, Data->iFcode, 2);
FullRefine_Fast(Data, CheckCandidate16no4v, 0);
} else {
Data->currentQMV->x = 2*Data->currentMV->x;
Data->currentQMV->y = 2*Data->currentMV->y;
if(MotionFlags & XVID_ME_QUARTERPELREFINE16) {
/* full */
if (MotionFlags & XVID_ME_HALFPELREFINE16) {
xvid_me_SubpelRefine(Data->currentMV[0], Data, CheckCandidate16no4v, 0); /* hpel part */
Data->currentQMV->x = 2*Data->currentMV->x;
Data->currentQMV->y = 2*Data->currentMV->y;
}
get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 4,
pParam->width, pParam->height, Data->iFcode, 2);
Data->qpel_precision = 1;
xvid_me_SubpelRefine(Data->currentQMV[0], Data, CheckCandidate16no4v, 0); /* qpel part */
}
}
}
if (Data->iMinSAD[0] < *best_sad) *best_sad = Data->iMinSAD[0];
}
static void
SkipDecisionB(MACROBLOCK * const pMB, const SearchData * const Data)
{
int k;
if (!Data->chroma) {
int dx = 0, dy = 0, b_dx = 0, b_dy = 0;
int32_t sum;
const uint32_t stride = Data->iEdgedWidth/2;
/* this is not full chroma compensation, only it's fullpel approximation. should work though */
for (k = 0; k < 4; k++) {
dy += Data->directmvF[k].y >> Data->qpel;
dx += Data->directmvF[k].x >> Data->qpel;
b_dy += Data->directmvB[k].y >> Data->qpel;
b_dx += Data->directmvB[k].x >> Data->qpel;
}
dy = (dy >> 3) + roundtab_76[dy & 0xf];
dx = (dx >> 3) + roundtab_76[dx & 0xf];
b_dy = (b_dy >> 3) + roundtab_76[b_dy & 0xf];
b_dx = (b_dx >> 3) + roundtab_76[b_dx & 0xf];
sum = sad8bi(Data->CurU,
Data->RefP[4] + (dy/2) * (int)stride + dx/2,
Data->b_RefP[4] + (b_dy/2) * (int)stride + b_dx/2,
stride);
if (sum >= MAX_CHROMA_SAD_FOR_SKIP * (int)Data->iQuant) return; /* no skip */
sum += sad8bi(Data->CurV,
Data->RefP[5] + (dy/2) * (int)stride + dx/2,
Data->b_RefP[5] + (b_dy/2) * (int)stride + b_dx/2,
stride);
if (sum >= MAX_CHROMA_SAD_FOR_SKIP * (int)Data->iQuant) return; /* no skip */
} else {
int sum = Data->chromaSAD; /* chroma-sad SAD caching keeps it there */
if (sum >= MAX_CHROMA_SAD_FOR_SKIP * (int)Data->iQuant) return; /* no skip */
}
/* skip */
pMB->mode = MODE_DIRECT_NONE_MV; /* skipped */
for (k = 0; k < 4; k++) {
pMB->qmvs[k] = pMB->mvs[k] = Data->directmvF[k];
pMB->b_qmvs[k] = pMB->b_mvs[k] = Data->directmvB[k];
if (Data->qpel) {
pMB->mvs[k].x /= 2; pMB->mvs[k].y /= 2; /* it's a hint for future searches */
pMB->b_mvs[k].x /= 2; pMB->b_mvs[k].y /= 2;
}
}
}
static uint32_t
SearchDirect_initial(const int x, const int y,
const uint32_t MotionFlags,
const int32_t TRB, const int32_t TRD,
const MBParam * const pParam,
MACROBLOCK * const pMB,
const MACROBLOCK * const b_mb,
int32_t * const best_sad,
SearchData * const Data)
{
int32_t skip_sad;
int k = (x + Data->iEdgedWidth*y) * 16;
k = Data->qpel ? 4 : 2;
Data->max_dx = k * (pParam->width - x * 16);
Data->max_dy = k * (pParam->height - y * 16);
Data->min_dx = -k * (16 + x * 16);
Data->min_dy = -k * (16 + y * 16);
Data->referencemv = Data->qpel ? b_mb->qmvs : b_mb->mvs;
for (k = 0; k < 4; k++) {
Data->directmvF[k].x = ((TRB * Data->referencemv[k].x) / TRD);
Data->directmvB[k].x = ((TRB - TRD) * Data->referencemv[k].x) / TRD;
Data->directmvF[k].y = ((TRB * Data->referencemv[k].y) / TRD);
Data->directmvB[k].y = ((TRB - TRD) * Data->referencemv[k].y) / TRD;
if ( (Data->directmvB[k].x > Data->max_dx) | (Data->directmvB[k].x < Data->min_dx)
| (Data->directmvB[k].y > Data->max_dy) | (Data->directmvB[k].y < Data->min_dy) ) {
Data->iMinSAD[0] = *best_sad = 256*4096; /* in that case, we won't use direct mode */
return 256*4096;
}
if (b_mb->mode != MODE_INTER4V) {
Data->directmvF[1] = Data->directmvF[2] = Data->directmvF[3] = Data->directmvF[0];
Data->directmvB[1] = Data->directmvB[2] = Data->directmvB[3] = Data->directmvB[0];
break;
}
}
Data->qpel_precision = Data->qpel; /* this initial check is done with full precision, to find real
SKIP sad */
CheckCandidateDirect(0, 0, Data, 255); /* will also fill iMinSAD[1..4] with 8x8 SADs */
/* initial (fast) skip decision */
if (Data->iMinSAD[1] < (int)Data->iQuant * INITIAL_SKIP_THRESH
&& Data->iMinSAD[2] < (int)Data->iQuant * INITIAL_SKIP_THRESH
&& Data->iMinSAD[3] < (int)Data->iQuant * INITIAL_SKIP_THRESH
&& Data->iMinSAD[4] < (int)Data->iQuant * INITIAL_SKIP_THRESH) {
/* possible skip */
SkipDecisionB(pMB, Data);
if (pMB->mode == MODE_DIRECT_NONE_MV)
return *Data->iMinSAD; /* skipped */
}
if (Data->chroma && Data->chromaSAD >= MAX_CHROMA_SAD_FOR_SKIP * (int)Data->iQuant) /* chroma doesn't allow skip */
skip_sad = 256*4096;
else
skip_sad = 4*MAX(MAX(Data->iMinSAD[1],Data->iMinSAD[2]), MAX(Data->iMinSAD[3],Data->iMinSAD[4]));
Data->currentMV[1].x = Data->directmvF[0].x + Data->currentMV->x; /* hints for forward and backward searches */
Data->currentMV[1].y = Data->directmvF[0].y + Data->currentMV->y;
Data->currentMV[2].x = ((Data->currentMV->x == 0) ?
Data->directmvB[0].x
: Data->currentMV[1].x - Data->referencemv[0].x);
Data->currentMV[2].y = ((Data->currentMV->y == 0) ?
Data->directmvB[0].y
: Data->currentMV[1].y - Data->referencemv[0].y);
*best_sad = Data->iMinSAD[0];
return skip_sad;
}
static void
SearchDirect_final( const uint32_t MotionFlags,
const MACROBLOCK * const b_mb,
int32_t * const best_sad,
SearchData * const Data)
{
CheckFunc * CheckCandidate = b_mb->mode == MODE_INTER4V ?
CheckCandidateDirect : CheckCandidateDirectno4v;
MainSearchFunc *MainSearchPtr;
if (MotionFlags & XVID_ME_USESQUARES16) MainSearchPtr = xvid_me_SquareSearch;
else if (MotionFlags & XVID_ME_ADVANCEDDIAMOND16) MainSearchPtr = xvid_me_AdvDiamondSearch;
else MainSearchPtr = xvid_me_DiamondSearch;
Data->qpel_precision = 0;
MainSearchPtr(0, 0, Data, 255, CheckCandidate);
Data->qpel_precision = Data->qpel;
if(Data->qpel) {
*Data->iMinSAD = 256*4096; /* this old SAD was not real, it was in hpel precision */
CheckCandidate(Data->currentMV->x, Data->currentMV->y, Data, 255);
}
xvid_me_SubpelRefine(Data->currentMV[0], Data, CheckCandidate, 0);
if (Data->iMinSAD[0] < *best_sad) {
*best_sad = Data->iMinSAD[0];
}
}
static __inline void
set_range(int * range, SearchData * Data)
{
Data->min_dx = range[0];
Data->max_dx = range[1];
Data->min_dy = range[2];
Data->max_dy = range[3];
}
static void
SearchInterpolate_initial(
const int x, const int y,
const uint32_t MotionFlags,
const MBParam * const pParam,
const VECTOR * const f_predMV,
const VECTOR * const b_predMV,
int32_t * const best_sad,
SearchData * const Data,
const VECTOR startF,
const VECTOR startB)
{
int b_range[4], f_range[4];
Data->qpel_precision = 0;
Data->predMV = *f_predMV;
Data->bpredMV = *b_predMV;
Data->currentMV[0] = startF;
Data->currentMV[1] = startB;
get_range(f_range, f_range+1, f_range+2, f_range+3, x, y, 4, pParam->width, pParam->height, Data->iFcode - Data->qpel, 1);
get_range(b_range, b_range+1, b_range+2, b_range+3, x, y, 4, pParam->width, pParam->height, Data->bFcode - Data->qpel, 1);
if (Data->currentMV[0].x > f_range[1]) Data->currentMV[0].x = f_range[1];
if (Data->currentMV[0].x < f_range[0]) Data->currentMV[0].x = f_range[0];
if (Data->currentMV[0].y > f_range[3]) Data->currentMV[0].y = f_range[3];
if (Data->currentMV[0].y < f_range[2]) Data->currentMV[0].y = f_range[2];
if (Data->currentMV[1].x > b_range[1]) Data->currentMV[1].x = b_range[1];
if (Data->currentMV[1].x < b_range[0]) Data->currentMV[1].x = b_range[0];
if (Data->currentMV[1].y > b_range[3]) Data->currentMV[1].y = b_range[3];
if (Data->currentMV[1].y < b_range[2]) Data->currentMV[1].y = b_range[2];
set_range(f_range, Data);
CheckCandidateInt(Data->currentMV[0].x, Data->currentMV[0].y, Data, 1);
if (Data->iMinSAD[0] < *best_sad) *best_sad = Data->iMinSAD[0];
}
static void
SearchInterpolate_final(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;
int b_range[4], f_range[4];
get_range(f_range, f_range+1, f_range+2, f_range+3, x, y, 4, pParam->width, pParam->height, Data->iFcode - Data->qpel, 1);
get_range(b_range, b_range+1, b_range+2, b_range+3, x, y, 4, pParam->width, pParam->height, Data->bFcode - Data->qpel, 1);
/* diamond */
do {
Data->dir = 0;
/* forward MV moves */
i = Data->currentMV[0].x; j = Data->currentMV[0].y;
CheckCandidateInt(i + 1, j, Data, 1);
CheckCandidateInt(i, j + 1, Data, 1);
CheckCandidateInt(i - 1, j, Data, 1);
CheckCandidateInt(i, j - 1, Data, 1);
/* backward MV moves */
set_range(b_range, Data);
i = Data->currentMV[1].x; j = Data->currentMV[1].y;
CheckCandidateInt(i + 1, j, Data, 2);
CheckCandidateInt(i, j + 1, Data, 2);
CheckCandidateInt(i - 1, j, Data, 2);
CheckCandidateInt(i, j - 1, Data, 2);
set_range(f_range, Data);
} while (Data->dir != 0);
/* qpel refinement */
if (Data->qpel) {
Data->qpel_precision = 1;
get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy,
x, y, 4, pParam->width, pParam->height, Data->iFcode, 2);
Data->currentQMV[0].x = 2 * Data->currentMV[0].x;
Data->currentQMV[0].y = 2 * Data->currentMV[0].y;
Data->currentQMV[1].x = 2 * Data->currentMV[1].x;
Data->currentQMV[1].y = 2 * Data->currentMV[1].y;
if (MotionFlags & XVID_ME_QUARTERPELREFINE16) {
xvid_me_SubpelRefine(Data->currentQMV[0], Data, CheckCandidateInt, 1);
get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy,
x, y, 4, pParam->width, pParam->height, Data->bFcode, 2);
xvid_me_SubpelRefine(Data->currentQMV[1], Data, CheckCandidateInt, 2);
}
}
if (Data->iMinSAD[0] < *best_sad) *best_sad = Data->iMinSAD[0];
}
static void
ModeDecision_BVOP_SAD(const SearchData * const Data_d,
const SearchData * const Data_b,
const SearchData * const Data_f,
const SearchData * const Data_i,
MACROBLOCK * const pMB,
const MACROBLOCK * const b_mb,
VECTOR * f_predMV,
VECTOR * b_predMV)
{
int mode = MODE_DIRECT, k;
int best_sad, f_sad, b_sad, i_sad;
const int qpel = Data_d->qpel;
/* evaluate cost of all modes - quite simple in SAD */
best_sad = Data_d->iMinSAD[0] + 1*Data_d->lambda16;
b_sad = Data_b->iMinSAD[0] + 3*Data_d->lambda16;
f_sad = Data_f->iMinSAD[0] + 4*Data_d->lambda16;
i_sad = Data_i->iMinSAD[0] + 2*Data_d->lambda16;
if (b_sad < best_sad) {
mode = MODE_BACKWARD;
best_sad = b_sad;
}
if (f_sad < best_sad) {
mode = MODE_FORWARD;
best_sad = f_sad;
}
if (i_sad < best_sad) {
mode = MODE_INTERPOLATE;
best_sad = i_sad;
}
pMB->sad16 = best_sad;
pMB->mode = mode;
pMB->cbp = 63;
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];
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -