📄 motion_est.c
字号:
/***************************************************************************** * * XVID MPEG-4 VIDEO CODEC * - Motion Estimation module - * * Copyright(C) 2002 Christoph Lampert <gruel@web.de> * 2002 Michael Militzer <michael@xvid.org> * * This file is part of XviD, a free MPEG-4 video encoder/decoder * * 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. * * 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 * * Under section 8 of the GNU General Public License, the copyright * holders of XVID explicitly forbid distribution in the following * countries: * * - Japan * - United States of America * * Linking XviD statically or dynamically with other modules is making a * combined work based on XviD. Thus, the terms and conditions of the * GNU General Public License cover the whole combination. * * As a special exception, the copyright holders of XviD give you * permission to link XviD with independent modules that communicate with * XviD solely through the VFW1.1 and DShow interfaces, regardless of the * license terms of these independent modules, and to copy and distribute * the resulting combined work under terms of your choice, provided that * every copy of the combined work is accompanied by a complete copy of * the source code of XviD (the version of XviD used to produce the * combined work), being distributed under the terms of the GNU General * Public License plus this exception. An independent module is a module * which is not derived from or based on XviD. * * Note that people who make modified versions of XviD are not obligated * to grant this special exception for their modified versions; it is * their choice whether to do so. The GNU General Public License gives * permission to release a modified version without this exception; this * exception also makes it possible to release a modified version which * carries forward this exception. * * $Id: motion_est.c,v 1.54 2002/11/26 23:44:10 edgomez Exp $ * *************************************************************************/#include <assert.h>#include <stdio.h>#include <stdlib.h>#include "../encoder.h"#include "../utils/mbfunctions.h"#include "../prediction/mbprediction.h"#include "../global.h"#include "../utils/timer.h"#include "motion.h"#include "sad.h"static int32_t lambda_vec16[32] = /* rounded values for lambda param for weight of motion bits as in modified H.26L */{ 0, (int) (1.00235 + 0.5), (int) (1.15582 + 0.5), (int) (1.31976 + 0.5), (int) (1.49591 + 0.5), (int) (1.68601 + 0.5), (int) (1.89187 + 0.5), (int) (2.11542 + 0.5), (int) (2.35878 + 0.5), (int) (2.62429 + 0.5), (int) (2.91455 + 0.5), (int) (3.23253 + 0.5), (int) (3.58158 + 0.5), (int) (3.96555 + 0.5), (int) (4.38887 + 0.5), (int) (4.85673 + 0.5), (int) (5.37519 + 0.5), (int) (5.95144 + 0.5), (int) (6.59408 + 0.5), (int) (7.31349 + 0.5), (int) (8.12242 + 0.5), (int) (9.03669 + 0.5), (int) (10.0763 + 0.5), (int) (11.2669 + 0.5), (int) (12.6426 + 0.5), (int) (14.2493 + 0.5), (int) (16.1512 + 0.5), (int) (18.442 + 0.5), (int) (21.2656 + 0.5), (int) (24.8580 + 0.5), (int) (29.6436 + 0.5), (int) (36.4949 + 0.5)};static int32_t *lambda_vec8 = lambda_vec16; /* same table for INTER and INTER4V for now *//* mv.length table */static const uint32_t mvtab[33] = { 1, 2, 3, 4, 6, 7, 7, 7, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 12, 12};static __inline uint32_tmv_bits(int32_t component, const uint32_t iFcode){ if (component == 0) return 1; if (component < 0) component = -component; if (iFcode == 1) { if (component > 32) component = 32; return mvtab[component] + 1; } component += (1 << (iFcode - 1)) - 1; component >>= (iFcode - 1); if (component > 32) component = 32; return mvtab[component] + 1 + iFcode - 1;}static __inline uint32_tcalc_delta_16(const int32_t dx, const int32_t dy, const uint32_t iFcode, const uint32_t iQuant){ return NEIGH_TEND_16X16 * lambda_vec16[iQuant] * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));}static __inline uint32_tcalc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode, const uint32_t iQuant){ return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));} boolMotionEstimation(MBParam * const pParam, FRAMEINFO * const current, FRAMEINFO * const reference, const IMAGE * const pRefH, const IMAGE * const pRefV, const IMAGE * const pRefHV, const uint32_t iLimit){ const uint32_t iWcount = pParam->mb_width; const uint32_t iHcount = pParam->mb_height; MACROBLOCK *const pMBs = current->mbs; MACROBLOCK *const prevMBs = reference->mbs; const IMAGE *const pCurrent = ¤t->image; const IMAGE *const pRef = &reference->image; static const VECTOR zeroMV = { 0, 0 }; VECTOR predMV; uint32_t x, y; uint32_t iIntra = 0; VECTOR pmv; if (sadInit) (*sadInit) (); for (y = 0; y < iHcount; y++) { for (x = 0; x < iWcount; x ++) { MACROBLOCK *const pMB = &pMBs[x + y * iWcount]; predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0); pMB->sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x, y, predMV.x, predMV.y, predMV.x, predMV.y, current->motion_flags, current->quant, current->fcode, pParam, pMBs, prevMBs, &pMB->mv16, &pMB->pmvs[0]); if (0 < (pMB->sad16 - MV16_INTER_BIAS)) { int32_t deviation; deviation = dev16(pCurrent->y + x * 16 + y * 16 * pParam->edged_width, pParam->edged_width); if (deviation < (pMB->sad16 - MV16_INTER_BIAS)) { pMB->mode = MODE_INTRA; pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = zeroMV; pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = 0; iIntra++; if (iIntra >= iLimit) return 1; continue; } } pmv = pMB->pmvs[0]; if (current->global_flags & XVID_INTER4V) if ((!(current->global_flags & XVID_LUMIMASKING) || pMB->dquant == NO_CHANGE)) { int32_t sad8 = IMV16X16 * current->quant; if (sad8 < pMB->sad16) { sad8 += pMB->sad8[0] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, 2 * x, 2 * y, pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y, current->motion_flags, current->quant, current->fcode, pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]); } if (sad8 < pMB->sad16) { predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 1); sad8 += pMB->sad8[1] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, 2 * x + 1, 2 * y, pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y, current->motion_flags, current->quant, current->fcode, pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]); } if (sad8 < pMB->sad16) { predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 2); sad8 += pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, 2 * x, 2 * y + 1, pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y, current->motion_flags, current->quant, current->fcode, pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]); } if (sad8 < pMB->sad16) { predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 3); sad8 += pMB->sad8[3] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, 2 * x + 1, 2 * y + 1, pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y, current->motion_flags, current->quant, current->fcode, pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]); } /* decide: MODE_INTER or MODE_INTER4V mpeg4: if (sad8 < pMB->sad16 - nb/2+1) use_inter4v */ if (sad8 < pMB->sad16) { pMB->mode = MODE_INTER4V; pMB->sad8[0] *= 4; pMB->sad8[1] *= 4; pMB->sad8[2] *= 4; pMB->sad8[3] *= 4; continue; } } pMB->mode = MODE_INTER; pMB->pmvs[0] = pmv; /* pMB->pmvs[1] = pMB->pmvs[2] = pMB->pmvs[3] are not needed for INTER */ pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16; pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = pMB->sad16; } } return 0;}#define CHECK_MV16_ZERO {\ if ( (0 <= max_dx) && (0 >= min_dx) \ && (0 <= max_dy) && (0 >= min_dy) ) \ { \ iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \ iSAD += calc_delta_16(-center_x, -center_y, (uint8_t)iFcode, iQuant);\ if (iSAD < iMinSAD) \ { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } } \}#define NOCHECK_MV16_CANDIDATE(X,Y) { \ iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \ iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\ if (iSAD < iMinSAD) \ { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \}#define CHECK_MV16_CANDIDATE(X,Y) { \ if ( ((X) <= max_dx) && ((X) >= min_dx) \ && ((Y) <= max_dy) && ((Y) >= min_dy) ) \ { \ iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \ iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\ if (iSAD < iMinSAD) \ { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \}#define CHECK_MV16_CANDIDATE_DIR(X,Y,D) { \ if ( ((X) <= max_dx) && ((X) >= min_dx) \ && ((Y) <= max_dy) && ((Y) >= min_dy) ) \ { \ iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \ iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\ if (iSAD < iMinSAD) \ { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \}#define CHECK_MV16_CANDIDATE_FOUND(X,Y,D) { \ if ( ((X) <= max_dx) && ((X) >= min_dx) \ && ((Y) <= max_dy) && ((Y) >= min_dy) ) \ { \ iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \ iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\ if (iSAD < iMinSAD) \ { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \}#define CHECK_MV8_ZERO {\ iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \ iSAD += calc_delta_8(-center_x, -center_y, (uint8_t)iFcode, iQuant);\ if (iSAD < iMinSAD) \ { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \}#define NOCHECK_MV8_CANDIDATE(X,Y) \ { \ iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \ iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\ if (iSAD < iMinSAD) \ { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \}#define CHECK_MV8_CANDIDATE(X,Y) { \ if ( ((X) <= max_dx) && ((X) >= min_dx) \ && ((Y) <= max_dy) && ((Y) >= min_dy) ) \ { \ iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \ iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\ if (iSAD < iMinSAD) \ { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \}#define CHECK_MV8_CANDIDATE_DIR(X,Y,D) { \ if ( ((X) <= max_dx) && ((X) >= min_dx) \ && ((Y) <= max_dy) && ((Y) >= min_dy) ) \ { \ iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \ iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\ if (iSAD < iMinSAD) \ { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \}#define CHECK_MV8_CANDIDATE_FOUND(X,Y,D) { \ if ( ((X) <= max_dx) && ((X) >= min_dx) \ && ((Y) <= max_dy) && ((Y) >= min_dy) ) \ { \ iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \ iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\ if (iSAD < iMinSAD) \ { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \}#if 0/* too slow and not fully functional at the moment */int32_t ZeroSearch16( const uint8_t * const pRef, const uint8_t * const pRefH, const uint8_t * const pRefV, const uint8_t * const pRefHV, const IMAGE * const pCur, const int x, const int y, const uint32_t MotionFlags, const uint32_t iQuant, const uint32_t iFcode, MBParam * const pParam, const MACROBLOCK * const pMBs, const MACROBLOCK * const prevMBs, VECTOR * const currMV, VECTOR * const currPMV){ const int32_t iEdgedWidth = pParam->edged_width; const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth; int32_t iSAD; VECTOR pred; pred = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0); iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); if (iSAD <= iQuant * 96) iSAD -= MV16_00_BIAS; currMV->x = 0; currMV->y = 0; currPMV->x = -pred.x; currPMV->y = -pred.y; return iSAD;}#endif /* 0 */int32_tDiamond16_MainSearch(const uint8_t * const pRef, const uint8_t * const pRefH, const uint8_t * const pRefV, const uint8_t * const pRefHV, const uint8_t * const cur, const int x, const int y, const int start_x, const int start_y, int iMinSAD, VECTOR * const currMV,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -