📄 motion_comp.c
字号:
/***************************************************************************** * * XVID MPEG-4 VIDEO CODEC * - Motion Compensation related code - * * Copyright(C) 2002 Peter Ross <pross@xvid.org> * 2003 Christoph Lampert <gruel@web.de> * * 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$ * ****************************************************************************/#include <stdio.h>#include "../encoder.h"#include "../utils/mbfunctions.h"#include "../image/interpolate8x8.h"#include "../image/qpel.h"#include "../image/reduced.h"#include "../utils/timer.h"#include "motion.h"#ifndef RSHIFT#define RSHIFT(a,b) ((a) > 0 ? ((a) + (1<<((b)-1)))>>(b) : ((a) + (1<<((b)-1))-1)>>(b))#endif/* assume b>0 */#ifndef RDIV#define RDIV(a,b) (((a)>0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b))#endif/* This is borrowed from bitstream.c until we find a common solution */static uint32_t __inlinelog2bin(uint32_t value){/* Changed by Chenm001 */#if !defined(_MSC_VER) int n = 0; while (value) { value >>= 1; n++; } return n;#else __asm { bsr eax, value inc eax }#endif}/* * getref: calculate reference image pointer * the decision to use interpolation h/v/hv or the normal image is * based on dx & dy. */static __inline const uint8_t *get_ref(const uint8_t * const refn, const uint8_t * const refh, const uint8_t * const refv, const uint8_t * const refhv, const uint32_t x, const uint32_t y, const uint32_t block, const int32_t dx, const int32_t dy, const int32_t stride){ switch (((dx & 1) << 1) + (dy & 1)) { case 0: return refn + (int) ((x * block + dx / 2) + (y * block + dy / 2) * stride); case 1: return refv + (int) ((x * block + dx / 2) + (y * block + (dy - 1) / 2) * stride); case 2: return refh + (int) ((x * block + (dx - 1) / 2) + (y * block + dy / 2) * stride); default: return refhv + (int) ((x * block + (dx - 1) / 2) + (y * block + (dy - 1) / 2) * stride); }}static __inline voidcompensate16x16_interpolate(int16_t * const dct_codes, uint8_t * const cur, const uint8_t * const ref, const uint8_t * const refh, const uint8_t * const refv, const uint8_t * const refhv, uint8_t * const tmp, uint32_t x, uint32_t y, const int32_t dx, const int32_t dy, const int32_t stride, const int quarterpel, const int reduced_resolution, const int32_t rounding){ const uint8_t * ptr; if (!reduced_resolution) { if(quarterpel) { if ((dx&3) | (dy&3)) {#if defined(ARCH_IS_IA32) /* new_interpolate is only faster on x86 (MMX) machines */ new_interpolate16x16_quarterpel(tmp - y * stride - x, (uint8_t *) ref, tmp + 32, tmp + 64, tmp + 96, x, y, dx, dy, stride, rounding);#else interpolate16x16_quarterpel(tmp - y * stride - x, (uint8_t *) ref, tmp + 32, tmp + 64, tmp + 96, x, y, dx, dy, stride, rounding);#endif ptr = tmp; } else ptr = ref + (y + dy/4)*stride + x + dx/4; /* fullpixel position */ } else ptr = get_ref(ref, refh, refv, refhv, x, y, 1, dx, dy, stride); transfer_8to16sub(dct_codes, cur + y * stride + x, ptr, stride); transfer_8to16sub(dct_codes+64, cur + y * stride + x + 8, ptr + 8, stride); transfer_8to16sub(dct_codes+128, cur + y * stride + x + 8*stride, ptr + 8*stride, stride); transfer_8to16sub(dct_codes+192, cur + y * stride + x + 8*stride+8, ptr + 8*stride + 8, stride); } else { /* reduced_resolution */ x *= 2; y *= 2; ptr = get_ref(ref, refh, refv, refhv, x, y, 1, dx, dy, stride); filter_18x18_to_8x8(dct_codes, cur+y*stride + x, stride); filter_diff_18x18_to_8x8(dct_codes, ptr, stride); filter_18x18_to_8x8(dct_codes+64, cur+y*stride + x + 16, stride); filter_diff_18x18_to_8x8(dct_codes+64, ptr + 16, stride); filter_18x18_to_8x8(dct_codes+128, cur+(y+16)*stride + x, stride); filter_diff_18x18_to_8x8(dct_codes+128, ptr + 16*stride, stride); filter_18x18_to_8x8(dct_codes+192, cur+(y+16)*stride + x + 16, stride); filter_diff_18x18_to_8x8(dct_codes+192, ptr + 16*stride + 16, stride); transfer32x32_copy(cur + y*stride + x, ptr, stride); }}static __inline voidcompensate8x8_interpolate( int16_t * const dct_codes, uint8_t * const cur, const uint8_t * const ref, const uint8_t * const refh, const uint8_t * const refv, const uint8_t * const refhv, uint8_t * const tmp, uint32_t x, uint32_t y, const int32_t dx, const int32_t dy, const int32_t stride, const int32_t quarterpel, const int reduced_resolution, const int32_t rounding){ const uint8_t * ptr; if (!reduced_resolution) { if(quarterpel) { if ((dx&3) | (dy&3)) {#if defined(ARCH_IS_IA32) /* new_interpolate is only faster on x86 (MMX) machines */ new_interpolate8x8_quarterpel(tmp - y*stride - x, (uint8_t *) ref, tmp + 32, tmp + 64, tmp + 96, x, y, dx, dy, stride, rounding);#else interpolate8x8_quarterpel(tmp - y*stride - x, (uint8_t *) ref, tmp + 32, tmp + 64, tmp + 96, x, y, dx, dy, stride, rounding);#endif ptr = tmp; } else ptr = ref + (y + dy/4)*stride + x + dx/4; /* fullpixel position */ } else ptr = get_ref(ref, refh, refv, refhv, x, y, 1, dx, dy, stride); transfer_8to16sub(dct_codes, cur + y * stride + x, ptr, stride); } else { /* reduced_resolution */ x *= 2; y *= 2; ptr = get_ref(ref, refh, refv, refhv, x, y, 1, dx, dy, stride); filter_18x18_to_8x8(dct_codes, cur+y*stride + x, stride); filter_diff_18x18_to_8x8(dct_codes, ptr, stride); transfer16x16_copy(cur + y*stride + x, ptr, stride); }}/* XXX: slow, inelegant... */static voidinterpolate18x18_switch(uint8_t * const cur, const uint8_t * const refn, const uint32_t x, const uint32_t y, const int32_t dx, const int dy, const int32_t stride, const int32_t rounding){ interpolate8x8_switch(cur, refn, x-1, y-1, dx, dy, stride, rounding); interpolate8x8_switch(cur, refn, x+7, y-1, dx, dy, stride, rounding); interpolate8x8_switch(cur, refn, x+9, y-1, dx, dy, stride, rounding); interpolate8x8_switch(cur, refn, x-1, y+7, dx, dy, stride, rounding); interpolate8x8_switch(cur, refn, x+7, y+7, dx, dy, stride, rounding); interpolate8x8_switch(cur, refn, x+9, y+7, dx, dy, stride, rounding); interpolate8x8_switch(cur, refn, x-1, y+9, dx, dy, stride, rounding); interpolate8x8_switch(cur, refn, x+7, y+9, dx, dy, stride, rounding); interpolate8x8_switch(cur, refn, x+9, y+9, dx, dy, stride, rounding);}static voidCompensateChroma( int dx, int dy, const int i, const int j, IMAGE * const Cur, const IMAGE * const Ref, uint8_t * const temp, int16_t * const coeff, const int32_t stride, const int rounding, const int rrv){ /* uv-block-based compensation */ if (!rrv) { transfer_8to16sub(coeff, Cur->u + 8 * j * stride + 8 * i, interpolate8x8_switch2(temp, Ref->u, 8 * i, 8 * j, dx, dy, stride, rounding), stride); transfer_8to16sub(coeff + 64, Cur->v + 8 * j * stride + 8 * i, interpolate8x8_switch2(temp, Ref->v, 8 * i, 8 * j, dx, dy, stride, rounding), stride); } else { uint8_t * current, * reference; current = Cur->u + 16*j*stride + 16*i; reference = temp - 16*j*stride - 16*i; interpolate18x18_switch(reference, Ref->u, 16*i, 16*j, dx, dy, stride, rounding); filter_18x18_to_8x8(coeff, current, stride); filter_diff_18x18_to_8x8(coeff, temp, stride); transfer16x16_copy(current, temp, stride); current = Cur->v + 16*j*stride + 16*i; interpolate18x18_switch(reference, Ref->v, 16*i, 16*j, dx, dy, stride, rounding); filter_18x18_to_8x8(coeff + 64, current, stride); filter_diff_18x18_to_8x8(coeff + 64, temp, stride); transfer16x16_copy(current, temp, stride); }}voidMBMotionCompensation(MACROBLOCK * const mb, const uint32_t i, const uint32_t j, const IMAGE * const ref,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -