--- trunk/xvidcore/src/prediction/mbprediction.c 2002/09/21 03:11:36 499 +++ trunk/xvidcore/src/prediction/mbprediction.c 2003/02/15 15:22:19 851 @@ -1,52 +1,64 @@ -/***************************************************************************** - * - * XVID MPEG-4 VIDEO CODEC - * - Prediction functions - - * - * Copyright(C) 2001-2002 - Michael Militzer - * Copyright(C) 2001-2002 - Peter Ross - * - * This program is an implementation of a part of one or more MPEG-4 - * Video tools as specified in ISO/IEC 14496-2 standard. Those intending - * to use this software module in hardware or software products are - * advised that its use may infringe existing patents or copyrights, and - * any such use would be at such party's own risk. The original - * developer of this software module and his/her company, and subsequent - * editors and their companies, will have no liability for use of this - * software or modifications or derivatives thereof. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: mbprediction.c,v 1.9 2002-09-21 03:07:56 suxen_drol Exp $ - * - ****************************************************************************/ + /****************************************************************************** + * * + * This file is part of XviD, a free MPEG-4 video encoder/decoder * + * * + * XviD is an implementation of a part of one or more MPEG-4 Video tools * + * as specified in ISO/IEC 14496-2 standard. Those intending to use this * + * software module in hardware or software products are advised that its * + * use may infringe existing patents or copyrights, and any such use * + * would be at such party's own risk. The original developer of this * + * software module and his/her company, and subsequent editors and their * + * companies, will have no liability for use of this software or * + * modifications or derivatives thereof. * + * * + * XviD is free software; you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * XviD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software * + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * * + ******************************************************************************/ + + /****************************************************************************** + * * + * mbprediction.c * + * * + * Copyright (C) 2001 - Michael Militzer * + * Copyright (C) 2001 - Peter Ross * + * * + * For more information visit the XviD homepage: http://www.xvid.org * + * * + ******************************************************************************/ + + /****************************************************************************** + * * + * Revision history: * + * * + * 29.06.2002 predict_acdc() bounding * + * 12.12.2001 improved calc_acdc_prediction; removed need for memcpy * + * 15.12.2001 moved pmv displacement to motion estimation * + * 30.11.2001 mmx cbp support * + * 17.11.2001 initial version * + * * + ******************************************************************************/ +#include "../global.h" #include "../encoder.h" #include "mbprediction.h" #include "../utils/mbfunctions.h" #include "../bitstream/cbp.h" +#include "../bitstream/mbcoding.h" +#include "../bitstream/zigzag.h" -#define ABS(X) (((X)>0)?(X):-(X)) -#define DIV_DIV(A,B) ( (A) > 0 ? ((A)+((B)>>1))/(B) : ((A)-((B)>>1))/(B) ) - - -/***************************************************************************** - * Local inlined function - ****************************************************************************/ - static int __inline rescale(int predict_quant, int current_quant, @@ -57,10 +69,6 @@ } -/***************************************************************************** - * Local data - ****************************************************************************/ - static const int16_t default_acdc_values[15] = { 1024, 0, 0, 0, 0, 0, 0, 0, @@ -68,11 +76,6 @@ }; -/***************************************************************************** - * Functions - ****************************************************************************/ - - /* get dc/ac prediction direction for a single block and place predictor values into MB->pred_values[j][..] */ @@ -280,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, @@ -297,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 */ @@ -341,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 @@ -349,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]; - } } } @@ -373,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]; @@ -381,25 +447,26 @@ 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->global_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); }