1 /*****************************************************************************
2 *
3 * XVID MPEG-4 VIDEO CODEC
4 * - Motion Estimation shared functions -
5 *
6 * Copyright(C) 2002 Christoph Lampert <gruel@web.de>
7 * 2002 Michael Militzer <michael@xvid.org>
8 * 2002-2003 Radoslaw Czyz <xvid@syskin.cjb.net>
9 *
10 * This program is free software ; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation ; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY ; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program ; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * $Id: motion_inlines.h 1985 2011-05-18 09:02:35Z Isibaar $
25 *
26 ****************************************************************************/
27
28 #ifndef _MOTION_INLINES_
29 #define _MOTION_INLINES_
30
31 #include <stdlib.h>
32
33 /*
34 * Calculate the min/max range
35 * relative to the _MACROBLOCK_ position
36 */
37 static void __inline
get_range(int32_t * const min_dx,int32_t * const max_dx,int32_t * const min_dy,int32_t * const max_dy,const uint32_t x,const uint32_t y,uint32_t block_sz,const uint32_t width,const uint32_t height,const int fcode,const int precision)38 get_range(int32_t * const min_dx,
39 int32_t * const max_dx,
40 int32_t * const min_dy,
41 int32_t * const max_dy,
42 const uint32_t x,
43 const uint32_t y,
44 uint32_t block_sz, /* block dimension, 3(8) or 4(16) */
45 const uint32_t width,
46 const uint32_t height,
47 const int fcode,
48 const int precision) /* 2 for qpel, 1 for halfpel */
49 {
50 int k;
51 const int search_range = 1 << (4+fcode);
52 int high = search_range - 1;
53 int low = -search_range;
54
55 k = (int)(width - (x<<block_sz))<<precision;
56 *max_dx = MIN(high, k);
57 k = (int)(height - (y<<block_sz))<<precision;
58 *max_dy = MIN(high, k);
59
60 k = (-(int)((x+1)<<block_sz))<<precision;
61 *min_dx = MAX(low, k);
62 k = (-(int)((y+1)<<block_sz))<<precision;
63 *min_dy = MAX(low, k);
64 }
65
66 /* reversed mv.length table */
67 static const int r_mvtab[65] = {
68 11, 12, 12, 12, 12, 12, 12, 12, 12,
69 12, 12, 12, 12, 12, 12, 12, 12,
70 12, 12, 12, 12, 12, 12, 12, 12,
71 12, 12, 12, 12, 12, 12, 12, 12,
72 12, 11, 11, 11, 11, 11, 11, 10,
73 10, 10, 10, 10, 10, 10, 10, 10,
74 10, 10, 10, 10, 10, 9, 9, 9,
75 7, 7, 7, 6, 4, 3, 2, 1
76 };
77
78 static __inline uint32_t
d_mv_bits(int x,int y,const VECTOR pred,const uint32_t iFcode,const int qpel)79 d_mv_bits(int x, int y, const VECTOR pred, const uint32_t iFcode, const int qpel)
80 {
81 unsigned int bits;
82
83 x <<= qpel;
84 y <<= qpel;
85
86 x -= pred.x;
87 bits = (x != 0 ? iFcode:0);
88 x = -abs(x);
89 x >>= (iFcode - 1);
90 bits += r_mvtab[x+64];
91
92 y -= pred.y;
93 bits += (y != 0 ? iFcode:0);
94 y = -abs(y);
95 y >>= (iFcode - 1);
96 bits += r_mvtab[y+64];
97
98 return bits;
99 }
100
101 static __inline const uint8_t *
GetReference(const int x,const int y,const SearchData * const data)102 GetReference(const int x, const int y, const SearchData * const data)
103 {
104 const int picture = ((x&1)<<1) | (y&1);
105 const int offset = (x>>1) + (y>>1)*data->iEdgedWidth;
106 return data->RefP[picture] + offset;
107 }
108
109 static __inline const uint8_t *
GetReferenceB(const int x,const int y,const uint32_t dir,const SearchData * const data)110 GetReferenceB(const int x, const int y, const uint32_t dir, const SearchData * const data)
111 {
112 /* dir : 0 = forward, 1 = backward */
113 const uint8_t *const *const direction = ( dir == 0 ? data->RefP : data->b_RefP );
114 const int picture = ((x&1)<<1) | (y&1);
115 const int offset = (x>>1) + (y>>1)*data->iEdgedWidth;
116 return direction[picture] + offset;
117 }
118
119 static __inline void
ZeroMacroblockP(MACROBLOCK * pMB,const int32_t sad)120 ZeroMacroblockP(MACROBLOCK *pMB, const int32_t sad)
121 {
122 pMB->mode = MODE_INTER;
123 pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = zeroMV;
124 pMB->qmvs[0] = pMB->qmvs[1] = pMB->qmvs[2] = pMB->qmvs[3] = zeroMV;
125 pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = sad;
126 pMB->mcsel = 0;
127 pMB->cbp = 0;
128 }
129
130 /* check if given vector is equal to any vector checked before */
131 static __inline int
vector_repeats(const VECTOR * const pmv,const unsigned int i)132 vector_repeats(const VECTOR * const pmv, const unsigned int i)
133 {
134 unsigned int j;
135 for (j = 0; j < i; j++)
136 if (MVequal(pmv[i], pmv[j])) return 1; /* same vector has been checked already */
137 return 0;
138 }
139
140 /* make a binary mask that prevents diamonds/squares
141 from checking a vector which has been checked as a prediction */
142 static __inline int
make_mask(const VECTOR * const pmv,const unsigned int i,const unsigned int current)143 make_mask(const VECTOR * const pmv, const unsigned int i, const unsigned int current)
144 {
145 unsigned int mask = 255, j;
146 for (j = 0; j < i; j++) {
147 if (pmv[current].x == pmv[j].x) {
148 if (pmv[current].y == pmv[j].y + iDiamondSize) mask &= ~4;
149 else if (pmv[current].y == pmv[j].y - iDiamondSize) mask &= ~8;
150 } else
151 if (pmv[current].y == pmv[j].y) {
152 if (pmv[current].x == pmv[j].x + iDiamondSize) mask &= ~1;
153 else if (pmv[current].x == pmv[j].x - iDiamondSize) mask &= ~2;
154 }
155 }
156 return mask;
157 }
158
159 #endif /* _MOTION_INLINES_ */
160