⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mbprediction.cpp

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 CPP
字号:
/***************************************************************************** * *  XVID MPEG-4 VIDEO CODEC *  - Prediction module - * *  Copyright (C) 2001-2003 Michael Militzer <isibaar@xvid.org> *                2001-2003 Peter Ross <pross@xvid.org> * *  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.cpp,v 1.1.1.1 2005/07/13 14:36:15 jeanlf Exp $ * ****************************************************************************/#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};//----------------------------/* get dc/ac prediction direction for a single block and place   predictor values into MB->pred_values[j][..]*/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;  /* current macroblock */   int *acpred_direction = &pMBs[index].acpred_directions[block];   dword i;   left = top = diag = current = 0;   /* grab left,top and diag macroblocks */   /* left macroblock */   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;   }   /* top macroblock */   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;   }   /* diag macroblock */   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];   /* now grab pLeft, pTop, pDiag _blocks_ */   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;   }   /*    * determine ac prediction direction & ac/dc predictor place rescaled ac/dc    * predictions into predictors[] for later use    */   if(ABS(pLeft[0] - pDiag[0]) < ABS(pDiag[0] - pTop[0])){                              //vertical      *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{                              //horizontal      *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]);   }}//----------------------------/* decoder: add predictors to dct_codes[] and   store current coeffs to pred_values[] for future prediction*/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];   /* dc prediction */   pCurrent[0] = dct_codes[0] * iDcScaler;   if(acpred_direction == 1){      for(int i = 1; i < 8; i++){         int level = dct_codes[i] + predictors[i];         //DPRINTF(XVID_DEBUG_COEFF,"predictor[%i] %i\n",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];         //DPRINTF(XVID_DEBUG_COEFF,"predictor[%i] %i\n",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;      /* 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}//----------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -