--- mbprediction.c 2002/06/30 10:46:29 1.6 +++ mbprediction.c 2003/02/22 08:49:45 1.13.2.1 @@ -50,14 +50,13 @@ * * ******************************************************************************/ +#include "../global.h" #include "../encoder.h" #include "mbprediction.h" #include "../utils/mbfunctions.h" #include "../bitstream/cbp.h" - - -#define ABS(X) (((X)>0)?(X):-(X)) -#define DIV_DIV(A,B) ( (A) > 0 ? ((A)+((B)>>1))/(B) : ((A)-((B)>>1))/(B) ) +#include "../bitstream/mbcoding.h" +#include "../bitstream/zigzag.h" static int __inline @@ -284,16 +283,14 @@ /* encoder: subtract predictors from qcoeff[] and calculate S1/S2 -todo: perform [-127,127] clamping after prediction -clamping must adjust the coeffs, so dequant is done correctly - -S1/S2 are used to determine if its worth predicting for AC +returns sum of coeefficients *saved* if prediction is enabled + S1 = sum of all (qcoeff - prediction) S2 = sum of all qcoeff */ -uint32_t -calc_acdc(MACROBLOCK * pMB, +int +calc_acdc_coeff(MACROBLOCK * pMB, uint32_t block, int16_t qcoeff[64], uint32_t iDcScaler, @@ -301,7 +298,7 @@ { int16_t *pCurrent = pMB->pred_values[block]; uint32_t i; - uint32_t S1 = 0, S2 = 0; + int S1 = 0, S2 = 0; /* store current coeffs to pred_values[] for future prediction */ @@ -345,6 +342,73 @@ } + +/* returns the bits *saved* if prediction is enabled */ + +int +calc_acdc_bits(MACROBLOCK * pMB, + uint32_t block, + int16_t qcoeff[64], + uint32_t iDcScaler, + int16_t predictors[8]) +{ + const int direction = pMB->acpred_directions[block]; + int16_t *pCurrent = pMB->pred_values[block]; + int16_t tmp[8]; + unsigned int i; + int Z1, Z2; + + /* store current coeffs to pred_values[] for future prediction */ + pCurrent[0] = qcoeff[0] * iDcScaler; + 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 */ +#ifdef BIGLUT + Z2 = CodeCoeff_CalcBits(qcoeff, intra_table, scan_tables[0], 1); +#else + Z2 = CodeCoeffIntra_CalcBits(qcoeff, scan_tables[0]); +#endif + + /* 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]; + } + } + +#ifdef BIGLUT + Z1 = CodeCoeff_CalcBits(qcoeff, intra_table, scan_tables[direction], 1); +#else + Z1 = CodeCoeffIntra_CalcBits(qcoeff, scan_tables[direction]); +#endif + + /* 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 */ void @@ -353,16 +417,14 @@ int16_t qcoeff[64], int16_t predictors[8]) { - uint32_t i; + unsigned int i; if (pMB->acpred_directions[block] == 1) { - for (i = 1; i < 8; i++) { + for (i = 1; i < 8; i++) qcoeff[i] = predictors[i]; - } } else { - for (i = 1; i < 8; i++) { + for (i = 1; i < 8; i++) qcoeff[i * 8] = predictors[i]; - } } } @@ -377,7 +439,7 @@ int32_t j; int32_t iDcScaler, iQuant = frame->quant; - int32_t S = 0; + int S = 0; int16_t predictors[6][8]; MACROBLOCK *pMB = &frame->mbs[x + y * mb_width]; @@ -385,205 +447,27 @@ if ((pMB->mode == MODE_INTRA) || (pMB->mode == MODE_INTRA_Q)) { for (j = 0; j < 6; j++) { - iDcScaler = get_dc_scaler(iQuant, (j < 4) ? 1 : 0); + iDcScaler = get_dc_scaler(iQuant, j<4); predict_acdc(frame->mbs, x, y, mb_width, j, &qcoeff[j * 64], iQuant, iDcScaler, predictors[j], 0); - S += calc_acdc(pMB, j, &qcoeff[j * 64], iDcScaler, predictors[j]); + if ((frame->vop_flags & XVID_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++) { + if (S<=0) { // dont predict + for (j = 0; j < 6; j++) pMB->acpred_directions[j] = 0; - } - } else { - for (j = 0; j < 6; j++) { + }else{ + for (j = 0; j < 6; j++) apply_acdc(pMB, j, &qcoeff[j * 64], predictors[j]); - } } + pMB->cbp = calc_cbp(qcoeff); } } - - - - -/* - get_pmvdata2: get_pmvdata with bounding -*/ -#define OFFSET(x,y,stride) ((x)+((y)*(stride))) - -int -get_pmvdata2(const MACROBLOCK * const pMBs, - const uint32_t x, - const uint32_t y, - const uint32_t x_dim, - const uint32_t block, - VECTOR * const pmv, - int32_t * const psad, - const int bound) -{ - const int mbpos = OFFSET(x, y ,x_dim); - - /* - * pmv are filled with: - * [0]: Median (or whatever is correct in a special case) - * [1]: left neighbour - * [2]: top neighbour - * [3]: topright neighbour - * psad are filled with: - * [0]: minimum of [1] to [3] - * [1]: left neighbour's SAD (NB:[1] to [3] are actually not needed) - * [2]: top neighbour's SAD - * [3]: topright neighbour's SAD - */ - - int xin1, xin2, xin3; - int yin1, yin2, yin3; - int vec1, vec2, vec3; - - int pos1, pos2, pos3; - int num_cand = 0; // number of candidates - int last_cand; // last candidate - - uint32_t index = x + y * x_dim; - const VECTOR zeroMV = { 0, 0 }; - - /* - * MODE_INTER, vm18 page 48 - * MODE_INTER4V vm18 page 51 - * - * (x,y-1) (x+1,y-1) - * [ | ] [ | ] - * [ 2 | 3 ] [ 2 | ] - * - * (x-1,y) (x,y) (x+1,y) - * [ | 1 ] [ 0 | 1 ] [ 0 | ] - * [ | 3 ] [ 2 | 3 ] [ | ] - */ - - switch (block) { - case 0: - xin1 = x - 1; - yin1 = y; - vec1 = 1; /* left */ - xin2 = x; - yin2 = y - 1; - vec2 = 2; /* top */ - xin3 = x + 1; - yin3 = y - 1; - vec3 = 2; /* top right */ - break; - case 1: - xin1 = x; - yin1 = y; - vec1 = 0; - xin2 = x; - yin2 = y - 1; - vec2 = 3; - xin3 = x + 1; - yin3 = y - 1; - vec3 = 2; - break; - case 2: - xin1 = x - 1; - yin1 = y; - vec1 = 3; - xin2 = x; - yin2 = y; - vec2 = 0; - xin3 = x; - yin3 = y; - vec3 = 1; - break; - default: - xin1 = x; - yin1 = y; - vec1 = 2; - xin2 = x; - yin2 = y; - vec2 = 0; - xin3 = x; - yin3 = y; - vec3 = 1; - } - - pos1 = OFFSET(xin1, yin1, x_dim); - pos2 = OFFSET(xin2, yin2, x_dim); - pos3 = OFFSET(xin3, yin3, x_dim); - - // left - if (xin1 < 0 || pos1 < bound) { - pmv[1] = zeroMV; - psad[1] = MV_MAX_ERROR; - } else { - pmv[1] = pMBs[xin1 + yin1 * x_dim].mvs[vec1]; - psad[1] = pMBs[xin1 + yin1 * x_dim].sad8[vec1]; - num_cand++; - last_cand = 1; - } - - // top - if (yin2 < 0 || pos2 < bound) { - pmv[2] = zeroMV; - psad[2] = MV_MAX_ERROR; - } else { - pmv[2] = pMBs[xin2 + yin2 * x_dim].mvs[vec2]; - psad[2] = pMBs[xin2 + yin2 * x_dim].sad8[vec2]; - num_cand++; - last_cand = 2; - } - - - // top right - if (yin3 < 0 || pos3 < bound || xin3 >= (int)x_dim) { - pmv[3] = zeroMV; - psad[3] = MV_MAX_ERROR; - //DPRINTF(DPRINTF_MV, "top-right"); - } else { - pmv[3] = pMBs[xin3 + yin3 * x_dim].mvs[vec3]; - psad[3] = pMBs[xin2 + yin2 * x_dim].sad8[vec3]; - num_cand++; - last_cand = 3; - } - - if (num_cand == 1) - { - /* DPRINTF(DPRINTF_MV,"cand0=(%i,%i), cand1=(%i,%i) cand2=(%i,%i) last=%i", - pmv[1].x, pmv[1].y, - pmv[2].x, pmv[2].y, - pmv[3].x, pmv[3].y, last_cand - 1); - */ - - pmv[0] = pmv[last_cand]; - psad[0] = psad[last_cand]; - return 0; - } - - /* DPRINTF(DPRINTF_MV,"cand0=(%i,%i), cand1=(%i,%i) cand2=(%i,%i)", - pmv[1].x, pmv[1].y, - pmv[2].x, pmv[2].y, - pmv[3].x, pmv[3].y);*/ - - if ((MVequal(pmv[1], pmv[2])) && (MVequal(pmv[1], pmv[3]))) { - pmv[0] = pmv[1]; - psad[0] = MIN(MIN(psad[1], psad[2]), psad[3]); - return 1; - } - - /* median,minimum */ - - 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))); - psad[0] = MIN(MIN(psad[1], psad[2]), psad[3]); - - return 0; -}