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