📄 mbprediction.c
字号:
int Z1, Z2;
/* store current coeffs to pred_values[] for future prediction */
pCurrent[0] = qcoeff[0] * iDcScaler;
pCurrent[0] = CLIP(pCurrent[0], -2048, 2047);
for (i = 1; i < 8; i++) {
pCurrent[i] = qcoeff[i];
pCurrent[i + 7] = qcoeff[i * 8];
}
/* dc prediction */
qcoeff[0] = qcoeff[0] - predictors[0];
/* calc cost before ac prediction */
Z2 = CodeCoeffIntra_CalcBits(qcoeff, scan_tables[0]);
/* apply ac prediction & calc cost*/
if (direction == 1) {
for (i = 1; i < 8; i++) {
tmp[i] = qcoeff[i];
qcoeff[i] -= predictors[i];
predictors[i] = qcoeff[i];
}
}else{ /* acpred_direction == 2 */
for (i = 1; i < 8; i++) {
tmp[i] = qcoeff[i*8];
qcoeff[i*8] -= predictors[i];
predictors[i] = qcoeff[i*8];
}
}
Z1 = CodeCoeffIntra_CalcBits(qcoeff, scan_tables[direction]);
/* undo prediction */
if (direction == 1) {
for (i = 1; i < 8; i++)
qcoeff[i] = tmp[i];
}else{ /* acpred_direction == 2 */
for (i = 1; i < 8; i++)
qcoeff[i*8] = tmp[i];
}
return Z2-Z1;
}
/* apply predictors[] to qcoeff */
static void
apply_acdc(MACROBLOCK * pMB,
uint32_t block,
int16_t qcoeff[64],
int16_t predictors[8])
{
unsigned int i;
if (pMB->acpred_directions[block] == 1) {
for (i = 1; i < 8; i++)
qcoeff[i] = predictors[i];
} else {
for (i = 1; i < 8; i++)
qcoeff[i * 8] = predictors[i];
}
}
void
MBPrediction(FRAMEINFO * frame,
uint32_t x,
uint32_t y,
uint32_t mb_width,
int16_t qcoeff[6 * 64])
{
int32_t j;
int32_t iDcScaler, iQuant;
int S = 0;
int16_t predictors[6][8];
MACROBLOCK *pMB = &frame->mbs[x + y * mb_width];
iQuant = pMB->quant;
if ((pMB->mode == MODE_INTRA) || (pMB->mode == MODE_INTRA_Q)) {
for (j = 0; j < 6; j++) {
iDcScaler = get_dc_scaler(iQuant, j<4);
predict_acdc(frame->mbs, x, y, mb_width, j, &qcoeff[j * 64],
iQuant, iDcScaler, predictors[j], 0);
if ((frame->vop_flags & XVID_VOP_HQACPRED))
S += calc_acdc_bits(pMB, j, &qcoeff[j * 64], iDcScaler, predictors[j]);
else
S += calc_acdc_coeff(pMB, j, &qcoeff[j * 64], iDcScaler, predictors[j]);
}
if (S<=0) { /* dont predict */
for (j = 0; j < 6; j++)
pMB->acpred_directions[j] = 0;
}else{
for (j = 0; j < 6; j++)
apply_acdc(pMB, j, &qcoeff[j * 64], predictors[j]);
}
pMB->cbp = calc_cbp(qcoeff);
}
}
static const VECTOR zeroMV = { 0, 0 };
VECTOR
get_pmv2(const MACROBLOCK * const mbs,
const int mb_width,
const int bound,
const int x,
const int y,
const int block)
{
int lx, ly, lz; /* left */
int tx, ty, tz; /* top */
int rx, ry, rz; /* top-right */
int lpos, tpos, rpos;
int num_cand = 0, last_cand = 1;
VECTOR pmv[4]; /* left neighbour, top neighbour, top-right neighbour */
switch (block) {
case 0:
lx = x - 1; ly = y; lz = 1;
tx = x; ty = y - 1; tz = 2;
rx = x + 1; ry = y - 1; rz = 2;
break;
case 1:
lx = x; ly = y; lz = 0;
tx = x; ty = y - 1; tz = 3;
rx = x + 1; ry = y - 1; rz = 2;
break;
case 2:
lx = x - 1; ly = y; lz = 3;
tx = x; ty = y; tz = 0;
rx = x; ry = y; rz = 1;
break;
default:
lx = x; ly = y; lz = 2;
tx = x; ty = y; tz = 0;
rx = x; ry = y; rz = 1;
}
lpos = lx + ly * mb_width;
rpos = rx + ry * mb_width;
tpos = tx + ty * mb_width;
if (lpos >= bound && lx >= 0) {
num_cand++;
pmv[1] = mbs[lpos].mvs[lz];
} else pmv[1] = zeroMV;
if (tpos >= bound) {
num_cand++;
last_cand = 2;
pmv[2] = mbs[tpos].mvs[tz];
} else pmv[2] = zeroMV;
if (rpos >= bound && rx < mb_width) {
num_cand++;
last_cand = 3;
pmv[3] = mbs[rpos].mvs[rz];
} else pmv[3] = zeroMV;
/* If there're more than one candidate, we return the median vector */
if (num_cand > 1) {
/* set median */
pmv[0].x =
MIN(MAX(pmv[1].x, pmv[2].x),
MIN(MAX(pmv[2].x, pmv[3].x), MAX(pmv[1].x, pmv[3].x)));
pmv[0].y =
MIN(MAX(pmv[1].y, pmv[2].y),
MIN(MAX(pmv[2].y, pmv[3].y), MAX(pmv[1].y, pmv[3].y)));
return pmv[0];
}
return pmv[last_cand]; /* no point calculating median mv */
}
VECTOR get_pmv2_interlaced(const MACROBLOCK * const mbs,
const int mb_width,
const int bound,
const int x,
const int y,
const int block)
{
int lx, ly, lz; /* left */
int tx, ty, tz; /* top */
int rx, ry, rz; /* top-right */
int lpos, tpos, rpos;
int num_cand = 0, last_cand = 1;
VECTOR pmv[4]; /* left neighbour, top neighbour, top-right neighbour */
lx=x-1; ly=y; lz=1;
tx=x; ty=y-1; tz=2;
rx=x+1; ry=y-1; rz=2;
lpos=lx+ly*mb_width;
rpos=rx+ry*mb_width;
tpos=tx+ty*mb_width;
if(lx>=0 && lpos>=bound)
{
num_cand++;
if(mbs[lpos].field_pred)
pmv[1] = mbs[lpos].mvs_avg;
else
pmv[1] = mbs[lpos].mvs[lz];
}
else
{
pmv[1] = zeroMV;
}
if(tpos>=bound)
{
num_cand++;
last_cand=2;
if(mbs[tpos].field_pred)
pmv[2] = mbs[tpos].mvs_avg;
else
pmv[2] = mbs[tpos].mvs[tz];
}
else
{
pmv[2] = zeroMV;
}
if(rx<mb_width && rpos>=bound)
{
num_cand++;
last_cand = 3;
if(mbs[rpos].field_pred)
pmv[3] = mbs[rpos].mvs_avg;
else
pmv[3] = mbs[rpos].mvs[rz];
}
else
{
pmv[3] = zeroMV;
}
/* If there're more than one candidate, we return the median vector */
if(num_cand>1)
{
/* set median */
pmv[0].x = MIN(MAX(pmv[1].x, pmv[2].x),
MIN(MAX(pmv[2].x, pmv[3].x), MAX(pmv[1].x, pmv[3].x)));
pmv[0].y = MIN(MAX(pmv[1].y, pmv[2].y),
MIN(MAX(pmv[2].y, pmv[3].y), MAX(pmv[1].y, pmv[3].y)));
return pmv[0];
}
return pmv[last_cand]; /* no point calculating median mv */
}
VECTOR
get_qpmv2(const MACROBLOCK * const mbs,
const int mb_width,
const int bound,
const int x,
const int y,
const int block)
{
int lx, ly, lz; /* left */
int tx, ty, tz; /* top */
int rx, ry, rz; /* top-right */
int lpos, tpos, rpos;
int num_cand = 0, last_cand = 1;
VECTOR pmv[4]; /* left neighbour, top neighbour, top-right neighbour */
switch (block) {
case 0:
lx = x - 1; ly = y; lz = 1;
tx = x; ty = y - 1; tz = 2;
rx = x + 1; ry = y - 1; rz = 2;
break;
case 1:
lx = x; ly = y; lz = 0;
tx = x; ty = y - 1; tz = 3;
rx = x + 1; ry = y - 1; rz = 2;
break;
case 2:
lx = x - 1; ly = y; lz = 3;
tx = x; ty = y; tz = 0;
rx = x; ry = y; rz = 1;
break;
default:
lx = x; ly = y; lz = 2;
tx = x; ty = y; tz = 0;
rx = x; ry = y; rz = 1;
}
lpos = lx + ly * mb_width;
rpos = rx + ry * mb_width;
tpos = tx + ty * mb_width;
if (lpos >= bound && lx >= 0) {
num_cand++;
pmv[1] = mbs[lpos].qmvs[lz];
} else pmv[1] = zeroMV;
if (tpos >= bound) {
num_cand++;
last_cand = 2;
pmv[2] = mbs[tpos].qmvs[tz];
} else pmv[2] = zeroMV;
if (rpos >= bound && rx < mb_width) {
num_cand++;
last_cand = 3;
pmv[3] = mbs[rpos].qmvs[rz];
} else pmv[3] = zeroMV;
/* If there're more than one candidate, we return the median vector */
if (num_cand > 1) {
/* set median */
pmv[0].x =
MIN(MAX(pmv[1].x, pmv[2].x),
MIN(MAX(pmv[2].x, pmv[3].x), MAX(pmv[1].x, pmv[3].x)));
pmv[0].y =
MIN(MAX(pmv[1].y, pmv[2].y),
MIN(MAX(pmv[2].y, pmv[3].y), MAX(pmv[1].y, pmv[3].y)));
return pmv[0];
}
return pmv[last_cand]; /* no point calculating median mv */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -