This source file includes following definitions.
- Divide
- rescale
- predict_acdc
- add_acdc
- get_pmv2
#include "global.h"
#include "mbprediction.h"
#if 0
#define Divide(a,b) (((a)>0) ? ((a)+((b)>>1))/(b) : ((a)-((b)>>1))/(b))
#else
#define RET_DIV(a, N) return (a*N+32768) >> 16;
#define RET_SHR(a, N, S) return (a+N) >> S;
static int Divide(int a, int b) {
switch(b) {
case 1:
return a;
case 2:
return a >> 1;
case 4:
RET_SHR(a, 2, 2);
case 8:
RET_SHR(a, 4, 3);
case 16:
RET_SHR(a, 8, 4);
case 32:
RET_SHR(a, 16, 5);
case 3:
RET_DIV(a, 21845);
case 5:
RET_DIV(a, 13107);
case 6:
RET_DIV(a, 10923);
case 7:
RET_DIV(a, 9362);
case 9:
RET_DIV(a, 7282);
case 10:
RET_DIV(a, 6554);
case 11:
RET_DIV(a, 5958);
case 12:
RET_DIV(a, 5461);
case 13:
RET_DIV(a, 5041);
case 14:
RET_DIV(a, 4681);
case 15:
RET_DIV(a, 4369);
case 17:
RET_DIV(a, 3855);
case 18:
RET_DIV(a, 3641);
case 19:
RET_DIV(a, 3449);
case 20:
RET_DIV(a, 3277);
case 21:
RET_DIV(a, 3121);
case 22:
RET_DIV(a, 2979);
case 23:
RET_DIV(a, 2849);
case 24:
RET_DIV(a, 2731);
case 25:
RET_DIV(a, 2621);
case 26:
RET_DIV(a, 2521);
case 27:
RET_DIV(a, 2427);
case 28:
RET_DIV(a, 2341);
case 29:
RET_DIV(a, 2260);
case 30:
RET_DIV(a, 2185);
case 31:
RET_DIV(a, 2114);
}
return ((a>0) ? (a+(b>>1))/b : (a-(b>>1))/b);
}
#endif
inline int rescale(int predict_quant, int current_quant, int coeff) {
if(!coeff)
return 0;
return Divide(coeff * predict_quant, current_quant);
}
static const int default_acdc_values[15] = {
1024,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0
};
void predict_acdc(MACROBLOCK *pMBs, dword x, dword y, dword mb_width, dword block, int qcoeff[64], dword current_quant, int iDcScaler, int predictors[8], int bound) {
const int mbpos = (y * mb_width) + x;
int *left, *top, *diag, *current;
int left_quant = current_quant;
int top_quant = current_quant;
const int *pLeft = default_acdc_values;
const int *pTop = default_acdc_values;
const int *pDiag = default_acdc_values;
dword index = x + y * mb_width;
int *acpred_direction = &pMBs[index].acpred_directions[block];
dword i;
left = top = diag = current = 0;
if (x && mbpos >= bound + 1 &&
(pMBs[index - 1].mode == MODE_INTRA ||
pMBs[index - 1].mode == MODE_INTRA_Q)) {
left = pMBs[index - 1].pred_values[0];
left_quant = pMBs[index - 1].quant;
}
if (mbpos >= bound + (int)mb_width &&
(pMBs[index - mb_width].mode == MODE_INTRA ||
pMBs[index - mb_width].mode == MODE_INTRA_Q)) {
top = pMBs[index - mb_width].pred_values[0];
top_quant = pMBs[index - mb_width].quant;
}
if (x && mbpos >= bound + (int)mb_width + 1 &&
(pMBs[index - 1 - mb_width].mode == MODE_INTRA ||
pMBs[index - 1 - mb_width].mode == MODE_INTRA_Q)) {
diag = pMBs[index - 1 - mb_width].pred_values[0];
}
current = pMBs[index].pred_values[0];
switch(block) {
case 0:
if(left)
pLeft = left + MBPRED_SIZE;
if(top)
pTop = top + (MBPRED_SIZE << 1);
if(diag)
pDiag = diag + 3 * MBPRED_SIZE;
break;
case 1:
pLeft = current;
left_quant = current_quant;
if(top) {
pTop = top + 3 * MBPRED_SIZE;
pDiag = top + (MBPRED_SIZE << 1);
}
break;
case 2:
if(left) {
pLeft = left + 3 * MBPRED_SIZE;
pDiag = left + MBPRED_SIZE;
}
pTop = current;
top_quant = current_quant;
break;
case 3:
pLeft = current + (MBPRED_SIZE << 1);
left_quant = current_quant;
pTop = current + MBPRED_SIZE;
top_quant = current_quant;
pDiag = current;
break;
case 4:
if(left)
pLeft = left + (MBPRED_SIZE << 2);
if(top)
pTop = top + (MBPRED_SIZE << 2);
if(diag)
pDiag = diag + (MBPRED_SIZE << 2);
break;
case 5:
if(left)
pLeft = left + 5 * MBPRED_SIZE;
if(top)
pTop = top + 5 * MBPRED_SIZE;
if(diag)
pDiag = diag + 5 * MBPRED_SIZE;
break;
}
if(ABS(pLeft[0] - pDiag[0]) < ABS(pDiag[0] - pTop[0])) {
*acpred_direction = 1;
predictors[0] = Divide(pTop[0], iDcScaler);
for(i = 1; i < 8; i++)
predictors[i] = rescale(top_quant, current_quant, pTop[i]);
} else {
*acpred_direction = 2;
predictors[0] = Divide(pLeft[0], iDcScaler);
for(i = 1; i < 8; i++)
predictors[i] = rescale(left_quant, current_quant, pLeft[i + 7]);
}
}
void add_acdc(MACROBLOCK *pMB, dword block, int dct_codes[64], dword iDcScaler, int predictors[8]) {
byte acpred_direction = pMB->acpred_directions[block];
int *pCurrent = pMB->pred_values[block];
DPRINTF(XVID_DEBUG_COEFF,"predictor[0] %i\n", predictors[0]);
dct_codes[0] += predictors[0];
pCurrent[0] = dct_codes[0] * iDcScaler;
if(acpred_direction == 1) {
for(int i = 1; i < 8; i++) {
int level = dct_codes[i] + predictors[i];
dct_codes[i] = level;
pCurrent[i] = level;
pCurrent[i + 7] = dct_codes[i * 8];
}
} else if(acpred_direction == 2) {
for(int i = 1; i < 8; i++) {
int level = dct_codes[i * 8] + predictors[i];
dct_codes[i * 8] = level;
pCurrent[i + 7] = level;
pCurrent[i] = dct_codes[i];
}
} else {
for(int i = 1; i < 8; i++) {
pCurrent[i] = dct_codes[i];
pCurrent[i + 7] = dct_codes[i * 8];
}
}
}
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;
int tx, ty, tz;
int rx, ry, rz;
int lpos, tpos, rpos;
int num_cand = 0, last_cand = 1;
VECTOR pmv[4];
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(num_cand > 1) {
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];
}