[svn] / branches / Isibaar / xvidcore / src / motion / motion_est.c Repository:
ViewVC logotype

Annotation of /branches/Isibaar/xvidcore/src/motion/motion_est.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 184 - (view) (download)
Original Path: trunk/xvidcore/src/motion/motion_est.c

1 : Isibaar 3 /**************************************************************************
2 :     *
3 :     * Modifications:
4 :     *
5 : suxen_drol 152 * 01.05.2002 updated MotionEstimationBVOP
6 : suxen_drol 136 * 25.04.2002 partial prevMB conversion
7 : chenm001 132 * 22.04.2002 remove some compile warning by chenm001 <chenm001@163.com>
8 :     * 14.04.2002 added MotionEstimationBVOP()
9 : chl 96 * 02.04.2002 add EPZS(^2) as ME algorithm, use PMV_USESQUARES to choose between
10 :     * EPZS and EPZS^2
11 : Isibaar 3 * 08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop
12 :     * PMVFast_Refine to support multiple searches with different start points
13 : edgomez 78 * 07.01.2002 uv-block-based interpolation
14 : Isibaar 3 * 06.01.2002 INTER/INTRA-decision is now done before any SEARCH8 (speedup)
15 : edgomez 78 * changed INTER_BIAS to 150 (as suggested by suxen_drol)
16 :     * removed halfpel refinement step in PMVfastSearch8 + quality=5
17 :     * added new quality mode = 6 which performs halfpel refinement
18 :     * filesize difference between quality 5 and 6 is smaller than 1%
19 : Isibaar 3 * (Isibaar)
20 :     * 31.12.2001 PMVfastSearch16 and PMVfastSearch8 (gruel)
21 : edgomez 78 * 30.12.2001 get_range/MotionSearchX simplified; blue/green bug fix
22 :     * 22.12.2001 commented best_point==99 check
23 :     * 19.12.2001 modified get_range (purple bug fix)
24 : Isibaar 3 * 15.12.2001 moved pmv displacement from mbprediction
25 :     * 02.12.2001 motion estimation/compensation split (Isibaar)
26 : edgomez 78 * 16.11.2001 rewrote/tweaked search algorithms; pross@cs.rmit.edu.au
27 : Isibaar 3 * 10.11.2001 support for sad16/sad8 functions
28 :     * 28.08.2001 reactivated MODE_INTER4V for EXT_MODE
29 :     * 24.08.2001 removed MODE_INTER4V_Q, disabled MODE_INTER4V for EXT_MODE
30 : edgomez 78 * 22.08.2001 added MODE_INTER4V_Q
31 : Isibaar 3 * 20.08.2001 added pragma to get rid of internal compiler error with VC6
32 :     * idea by Cyril. Thanks.
33 :     *
34 :     * Michael Militzer <isibaar@videocoding.de>
35 :     *
36 :     **************************************************************************/
37 :    
38 :     #include <assert.h>
39 :     #include <stdio.h>
40 : chl 96 #include <stdlib.h>
41 : Isibaar 3
42 :     #include "../encoder.h"
43 :     #include "../utils/mbfunctions.h"
44 :     #include "../prediction/mbprediction.h"
45 :     #include "../global.h"
46 :     #include "../utils/timer.h"
47 : suxen_drol 118 #include "motion.h"
48 : Isibaar 3 #include "sad.h"
49 :    
50 :     // very large value
51 :     #define MV_MAX_ERROR (4096 * 256)
52 :    
53 :     // stop search if sdelta < THRESHOLD
54 :     #define MV16_THRESHOLD 192
55 :     #define MV8_THRESHOLD 56
56 :    
57 : chl 175 #define NEIGH_MOVE_THRESH 0
58 : chl 174 // how much a block's MV must differ from his neighbour
59 :     // to be search for INTER4V. The more, the faster...
60 :    
61 : Isibaar 3 /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */
62 :     /* nb = vop pixels * 2^(bpp-8) */
63 :     #define MV16_00_BIAS (128+1)
64 : chl 140 #define MV8_00_BIAS (0)
65 : Isibaar 3
66 :     /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */
67 : chl 172 #define MV16_INTER_BIAS 512
68 : Isibaar 3
69 :     /* Parameters which control inter/inter4v decision */
70 :     #define IMV16X16 5
71 :    
72 :     /* vector map (vlc delta size) smoother parameters */
73 :     #define NEIGH_TEND_16X16 2
74 :     #define NEIGH_TEND_8X8 2
75 :    
76 :     // fast ((A)/2)*2
77 :     #define EVEN(A) (((A)<0?(A)+1:(A)) & ~1)
78 :    
79 : chl 172 #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )
80 :     #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )
81 : Isibaar 3
82 : chl 96 int32_t PMVfastSearch16(
83 :     const uint8_t * const pRef,
84 :     const uint8_t * const pRefH,
85 :     const uint8_t * const pRefV,
86 :     const uint8_t * const pRefHV,
87 :     const IMAGE * const pCur,
88 :     const int x, const int y,
89 :     const uint32_t MotionFlags,
90 : suxen_drol 136 const uint32_t iQuant,
91 :     const uint32_t iFcode,
92 : chl 96 const MBParam * const pParam,
93 : suxen_drol 136 const MACROBLOCK * const pMBs,
94 :     const MACROBLOCK * const prevMBs,
95 : chl 96 VECTOR * const currMV,
96 :     VECTOR * const currPMV);
97 : Isibaar 3
98 : chl 96 int32_t EPZSSearch16(
99 :     const uint8_t * const pRef,
100 :     const uint8_t * const pRefH,
101 :     const uint8_t * const pRefV,
102 :     const uint8_t * const pRefHV,
103 :     const IMAGE * const pCur,
104 :     const int x, const int y,
105 :     const uint32_t MotionFlags,
106 : suxen_drol 136 const uint32_t iQuant,
107 :     const uint32_t iFcode,
108 : chl 96 const MBParam * const pParam,
109 : suxen_drol 136 const MACROBLOCK * const pMBs,
110 :     const MACROBLOCK * const prevMBs,
111 : chl 96 VECTOR * const currMV,
112 :     VECTOR * const currPMV);
113 :    
114 :    
115 : Isibaar 3 int32_t PMVfastSearch8(
116 : chl 96 const uint8_t * const pRef,
117 :     const uint8_t * const pRefH,
118 :     const uint8_t * const pRefV,
119 :     const uint8_t * const pRefHV,
120 :     const IMAGE * const pCur,
121 :     const int x, const int y,
122 : suxen_drol 136 const int start_x, const int start_y,
123 : chl 96 const uint32_t MotionFlags,
124 : suxen_drol 136 const uint32_t iQuant,
125 :     const uint32_t iFcode,
126 : chl 96 const MBParam * const pParam,
127 : suxen_drol 136 const MACROBLOCK * const pMBs,
128 :     const MACROBLOCK * const prevMBs,
129 : chl 96 VECTOR * const currMV,
130 :     VECTOR * const currPMV);
131 :    
132 :     int32_t EPZSSearch8(
133 :     const uint8_t * const pRef,
134 :     const uint8_t * const pRefH,
135 :     const uint8_t * const pRefV,
136 :     const uint8_t * const pRefHV,
137 :     const IMAGE * const pCur,
138 :     const int x, const int y,
139 : suxen_drol 136 const int start_x, const int start_y,
140 : chl 96 const uint32_t MotionFlags,
141 : suxen_drol 136 const uint32_t iQuant,
142 :     const uint32_t iFcode,
143 : chl 96 const MBParam * const pParam,
144 : suxen_drol 136 const MACROBLOCK * const pMBs,
145 :     const MACROBLOCK * const prevMBs,
146 : chl 96 VECTOR * const currMV,
147 :     VECTOR * const currPMV);
148 :    
149 :    
150 :     typedef int32_t (MainSearch16Func)(
151 : edgomez 78 const uint8_t * const pRef,
152 :     const uint8_t * const pRefH,
153 :     const uint8_t * const pRefV,
154 :     const uint8_t * const pRefHV,
155 : chl 96 const uint8_t * const cur,
156 : edgomez 78 const int x, const int y,
157 : chl 96 int32_t startx, int32_t starty,
158 :     int32_t iMinSAD,
159 : edgomez 78 VECTOR * const currMV,
160 : chl 96 const VECTOR * const pmv,
161 :     const int32_t min_dx, const int32_t max_dx,
162 :     const int32_t min_dy, const int32_t max_dy,
163 :     const int32_t iEdgedWidth,
164 :     const int32_t iDiamondSize,
165 :     const int32_t iFcode,
166 :     const int32_t iQuant,
167 :     int iFound);
168 : Isibaar 3
169 : chl 96 typedef MainSearch16Func* MainSearch16FuncPtr;
170 :    
171 :    
172 :     typedef int32_t (MainSearch8Func)(
173 : edgomez 78 const uint8_t * const pRef,
174 :     const uint8_t * const pRefH,
175 :     const uint8_t * const pRefV,
176 :     const uint8_t * const pRefHV,
177 : chl 96 const uint8_t * const cur,
178 : edgomez 78 const int x, const int y,
179 : chl 96 int32_t startx, int32_t starty,
180 :     int32_t iMinSAD,
181 : edgomez 78 VECTOR * const currMV,
182 : chl 96 const VECTOR * const pmv,
183 :     const int32_t min_dx, const int32_t max_dx,
184 :     const int32_t min_dy, const int32_t max_dy,
185 :     const int32_t iEdgedWidth,
186 :     const int32_t iDiamondSize,
187 :     const int32_t iFcode,
188 :     const int32_t iQuant,
189 :     int iFound);
190 : Isibaar 3
191 : chl 96 typedef MainSearch8Func* MainSearch8FuncPtr;
192 : Isibaar 3
193 : chl 141 static int32_t lambda_vec16[32] = /* rounded values for lambda param for weight of motion bits as in modified H.26L */
194 :     { 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),
195 :     (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),
196 :     (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),
197 :     (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),
198 :     (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),
199 :     (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),
200 :     (int)(36.4949+0.5) };
201 :    
202 :     static int32_t *lambda_vec8 = lambda_vec16; /* same table for INTER and INTER4V for now*/
203 :    
204 :    
205 :    
206 : Isibaar 3 // mv.length table
207 :     static const uint32_t mvtab[33] = {
208 :     1, 2, 3, 4, 6, 7, 7, 7,
209 :     9, 9, 9, 10, 10, 10, 10, 10,
210 :     10, 10, 10, 10, 10, 10, 10, 10,
211 :     10, 11, 11, 11, 11, 11, 11, 12, 12
212 :     };
213 :    
214 :    
215 :     static __inline uint32_t mv_bits(int32_t component, const uint32_t iFcode)
216 :     {
217 :     if (component == 0)
218 :     return 1;
219 :    
220 :     if (component < 0)
221 :     component = -component;
222 :    
223 :     if (iFcode == 1)
224 :     {
225 :     if (component > 32)
226 :     component = 32;
227 :    
228 :     return mvtab[component] + 1;
229 :     }
230 :    
231 :     component += (1 << (iFcode - 1)) - 1;
232 :     component >>= (iFcode - 1);
233 :    
234 :     if (component > 32)
235 :     component = 32;
236 :    
237 :     return mvtab[component] + 1 + iFcode - 1;
238 :     }
239 :    
240 :    
241 : chl 141 static __inline uint32_t calc_delta_16(const int32_t dx, const int32_t dy, const uint32_t iFcode, const uint32_t iQuant)
242 : Isibaar 3 {
243 : chl 141 return NEIGH_TEND_16X16 * lambda_vec16[iQuant] * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));
244 : Isibaar 3 }
245 :    
246 : chl 141 static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode, const uint32_t iQuant)
247 : Isibaar 3
248 :     {
249 : chl 141 return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));
250 : Isibaar 3 }
251 :    
252 :    
253 :    
254 :    
255 :    
256 :     #ifndef SEARCH16
257 :     #define SEARCH16 PMVfastSearch16
258 : chl 96 //#define SEARCH16 FullSearch16
259 :     //#define SEARCH16 EPZSSearch16
260 : Isibaar 3 #endif
261 :    
262 :     #ifndef SEARCH8
263 :     #define SEARCH8 PMVfastSearch8
264 : chl 96 //#define SEARCH8 EPZSSearch8
265 : Isibaar 3 #endif
266 :    
267 :     bool MotionEstimation(
268 : edgomez 78 MBParam * const pParam,
269 : suxen_drol 136 FRAMEINFO * const current,
270 :     FRAMEINFO * const reference,
271 : edgomez 78 const IMAGE * const pRefH,
272 :     const IMAGE * const pRefV,
273 :     const IMAGE * const pRefHV,
274 : chl 184 const uint32_t iLimit)
275 : Isibaar 3 {
276 : edgomez 78 const uint32_t iWcount = pParam->mb_width;
277 :     const uint32_t iHcount = pParam->mb_height;
278 : chl 184 MACROBLOCK * const pMBs = current->mbs;
279 :     MACROBLOCK * const prevMBs = reference->mbs;
280 : chl 172 const IMAGE * const pCurrent = &current->image;
281 : chl 184 const IMAGE * const pRef = &reference->image;
282 : suxen_drol 136
283 : chl 184 const VECTOR zeroMV = {0,0};
284 :    
285 : chl 172 int32_t x, y;
286 :     int32_t iIntra = 0;
287 :     VECTOR pmv;
288 : suxen_drol 136
289 : chl 184 if (sadInit)
290 :     (*sadInit)();
291 :    
292 : chl 172 for (y = 0; y < iHcount; y++)
293 :     for (x = 0; x < iWcount; x++)
294 : Isibaar 3 {
295 : chl 172 MACROBLOCK* const pMB = &pMBs[x + y * iWcount];
296 : Isibaar 3
297 : chl 184 pMB->sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
298 :     x, y, current->motion_flags, current->quant, current->fcode,
299 :     pParam, pMBs, prevMBs, &pMB->mv16, &pMB->pmvs[0]);
300 :    
301 : chl 172 if (0 < (pMB->sad16 - MV16_INTER_BIAS))
302 : edgomez 78 {
303 : chl 172 int32_t deviation;
304 : chl 184 deviation = dev16(pCurrent->y + x*16 + y*16*pParam->edged_width, pParam->edged_width);
305 :    
306 : chl 172 if (deviation < (pMB->sad16 - MV16_INTER_BIAS))
307 :     {
308 :     pMB->mode = MODE_INTRA;
309 : chl 184 pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = zeroMV;
310 :     pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = 0;
311 :    
312 : chl 172 iIntra++;
313 :     if (iIntra >= iLimit)
314 : chl 184 return 1;
315 :    
316 : chl 172 continue;
317 :     }
318 : chl 184 }
319 : chl 175
320 : chl 184 pmv = pMB->pmvs[0];
321 :     if (current->global_flags & XVID_INTER4V)
322 : chl 175 if ( (!(current->global_flags & XVID_LUMIMASKING) || pMB->dquant == NO_CHANGE) )
323 :     {
324 : chl 184 int32_t sad8 = IMV16X16 * current->quant; if (sad8 < pMB->sad16)
325 :    
326 :     sad8 += pMB->sad8[0] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
327 :     2*x, 2*y, pMB->mv16.x, pMB->mv16.y,
328 :     current->motion_flags, current->quant, current->fcode,
329 :     pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]);
330 :    
331 : chl 175 if (sad8 < pMB->sad16)
332 : chl 184 sad8 += pMB->sad8[1] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
333 :     2*x+1, 2*y, pMB->mv16.x, pMB->mv16.y,
334 :     current->motion_flags, current->quant, current->fcode,
335 :     pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]);
336 :    
337 : chl 175 if (sad8 < pMB->sad16)
338 : chl 184 sad8 += pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
339 :     2*x, 2*y+1, pMB->mv16.x, pMB->mv16.y,
340 :     current->motion_flags, current->quant, current->fcode,
341 :     pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]);
342 : Isibaar 3
343 : chl 175 if (sad8 < pMB->sad16)
344 : chl 184 sad8 += pMB->sad8[3] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
345 :     2*x+1, 2*y+1, pMB->mv16.x, pMB->mv16.y,
346 :     current->motion_flags, current->quant, current->fcode,
347 :     pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]);
348 :    
349 :     /* decide: MODE_INTER or MODE_INTER4V
350 :     mpeg4: if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
351 :     */
352 :    
353 : chl 175 if (sad8 < pMB->sad16)
354 :     {
355 :     pMB->mode = MODE_INTER4V;
356 : chl 184 pMB->sad8[0] *= 4;
357 : chl 175 pMB->sad8[1] *= 4;
358 :     pMB->sad8[2] *= 4;
359 :     pMB->sad8[3] *= 4;
360 :     continue;
361 :     }
362 : chl 184
363 :     }
364 :    
365 :     pMB->mode = MODE_INTER;
366 :     pMB->pmvs[0] = pmv; /* pMB->pmvs[1] = pMB->pmvs[2] = pMB->pmvs[3] are not needed for INTER */
367 :     pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
368 :     pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = pMB->sad16;
369 : chl 175
370 : chl 184 }
371 :     return 0;
372 : Isibaar 3 }
373 :    
374 :     #define CHECK_MV16_ZERO {\
375 :     if ( (0 <= max_dx) && (0 >= min_dx) \
376 :     && (0 <= max_dy) && (0 >= min_dy) ) \
377 :     { \
378 :     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \
379 : chl 141 iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\
380 : Isibaar 3 if (iSAD < iMinSAD) \
381 :     { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } } \
382 :     }
383 :    
384 : chl 96 #define NOCHECK_MV16_CANDIDATE(X,Y) { \
385 :     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
386 : chl 141 iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
387 : chl 96 if (iSAD < iMinSAD) \
388 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
389 :     }
390 : Isibaar 3
391 :     #define CHECK_MV16_CANDIDATE(X,Y) { \
392 :     if ( ((X) <= max_dx) && ((X) >= min_dx) \
393 :     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
394 :     { \
395 :     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
396 : chl 141 iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
397 : Isibaar 3 if (iSAD < iMinSAD) \
398 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
399 :     }
400 :    
401 :     #define CHECK_MV16_CANDIDATE_DIR(X,Y,D) { \
402 :     if ( ((X) <= max_dx) && ((X) >= min_dx) \
403 :     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
404 :     { \
405 :     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
406 : chl 141 iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
407 : Isibaar 3 if (iSAD < iMinSAD) \
408 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
409 :     }
410 :    
411 :     #define CHECK_MV16_CANDIDATE_FOUND(X,Y,D) { \
412 :     if ( ((X) <= max_dx) && ((X) >= min_dx) \
413 :     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
414 :     { \
415 :     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
416 : chl 141 iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
417 : Isibaar 3 if (iSAD < iMinSAD) \
418 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
419 :     }
420 :    
421 :    
422 :     #define CHECK_MV8_ZERO {\
423 :     iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \
424 : chl 141 iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\
425 : Isibaar 3 if (iSAD < iMinSAD) \
426 :     { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
427 :     }
428 :    
429 : chl 96 #define NOCHECK_MV8_CANDIDATE(X,Y) \
430 :     { \
431 :     iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
432 : chl 141 iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
433 : chl 96 if (iSAD < iMinSAD) \
434 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
435 :     }
436 : Isibaar 3
437 :     #define CHECK_MV8_CANDIDATE(X,Y) { \
438 :     if ( ((X) <= max_dx) && ((X) >= min_dx) \
439 :     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
440 :     { \
441 :     iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
442 : chl 141 iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
443 : Isibaar 3 if (iSAD < iMinSAD) \
444 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
445 :     }
446 :    
447 :     #define CHECK_MV8_CANDIDATE_DIR(X,Y,D) { \
448 :     if ( ((X) <= max_dx) && ((X) >= min_dx) \
449 :     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
450 :     { \
451 :     iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
452 : chl 141 iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
453 : Isibaar 3 if (iSAD < iMinSAD) \
454 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
455 :     }
456 :    
457 :     #define CHECK_MV8_CANDIDATE_FOUND(X,Y,D) { \
458 :     if ( ((X) <= max_dx) && ((X) >= min_dx) \
459 :     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
460 :     { \
461 :     iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
462 : chl 141 iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
463 : Isibaar 3 if (iSAD < iMinSAD) \
464 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
465 :     }
466 :    
467 :     /* too slow and not fully functional at the moment */
468 :     /*
469 :     int32_t ZeroSearch16(
470 :     const uint8_t * const pRef,
471 :     const uint8_t * const pRefH,
472 :     const uint8_t * const pRefV,
473 :     const uint8_t * const pRefHV,
474 :     const IMAGE * const pCur,
475 :     const int x, const int y,
476 :     const uint32_t MotionFlags,
477 : suxen_drol 136 const uint32_t iQuant,
478 :     const uint32_t iFcode,
479 : Isibaar 3 MBParam * const pParam,
480 : suxen_drol 136 const MACROBLOCK * const pMBs,
481 :     const MACROBLOCK * const prevMBs,
482 : Isibaar 3 VECTOR * const currMV,
483 :     VECTOR * const currPMV)
484 :     {
485 :     const int32_t iEdgedWidth = pParam->edged_width;
486 :     const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
487 :     int32_t iSAD;
488 :     int32_t pred_x,pred_y;
489 :    
490 :     get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);
491 :    
492 :     iSAD = sad16( cur,
493 :     get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),
494 :     iEdgedWidth, MV_MAX_ERROR);
495 :     if (iSAD <= iQuant * 96)
496 :     iSAD -= MV16_00_BIAS;
497 :    
498 :     currMV->x = 0;
499 :     currMV->y = 0;
500 :     currPMV->x = -pred_x;
501 :     currPMV->y = -pred_y;
502 :    
503 :     return iSAD;
504 :    
505 :     }
506 :     */
507 :    
508 : chl 96 int32_t Diamond16_MainSearch(
509 : edgomez 78 const uint8_t * const pRef,
510 :     const uint8_t * const pRefH,
511 :     const uint8_t * const pRefV,
512 :     const uint8_t * const pRefHV,
513 :     const uint8_t * const cur,
514 :     const int x, const int y,
515 :     int32_t startx, int32_t starty,
516 :     int32_t iMinSAD,
517 :     VECTOR * const currMV,
518 :     const VECTOR * const pmv,
519 :     const int32_t min_dx, const int32_t max_dx,
520 :     const int32_t min_dy, const int32_t max_dy,
521 :     const int32_t iEdgedWidth,
522 :     const int32_t iDiamondSize,
523 :     const int32_t iFcode,
524 :     const int32_t iQuant,
525 :     int iFound)
526 : Isibaar 3 {
527 :     /* Do a diamond search around given starting point, return SAD of best */
528 :    
529 :     int32_t iDirection=0;
530 :     int32_t iSAD;
531 :     VECTOR backupMV;
532 :     backupMV.x = startx;
533 :     backupMV.y = starty;
534 :    
535 :     /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
536 :    
537 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
538 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
539 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
540 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
541 :    
542 :     if (iDirection)
543 :     while (!iFound)
544 :     {
545 :     iFound = 1;
546 :     backupMV=*currMV;
547 :    
548 :     if ( iDirection != 2)
549 :     CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
550 :     if ( iDirection != 1)
551 :     CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);
552 :     if ( iDirection != 4)
553 :     CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);
554 :     if ( iDirection != 3)
555 :     CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);
556 :     }
557 :     else
558 : edgomez 78 {
559 :     currMV->x = startx;
560 :     currMV->y = starty;
561 :     }
562 : Isibaar 3 return iMinSAD;
563 :     }
564 :    
565 : chl 96 int32_t Square16_MainSearch(
566 :     const uint8_t * const pRef,
567 :     const uint8_t * const pRefH,
568 :     const uint8_t * const pRefV,
569 :     const uint8_t * const pRefHV,
570 :     const uint8_t * const cur,
571 :     const int x, const int y,
572 :     int32_t startx, int32_t starty,
573 :     int32_t iMinSAD,
574 :     VECTOR * const currMV,
575 :     const VECTOR * const pmv,
576 :     const int32_t min_dx, const int32_t max_dx,
577 :     const int32_t min_dy, const int32_t max_dy,
578 :     const int32_t iEdgedWidth,
579 :     const int32_t iDiamondSize,
580 :     const int32_t iFcode,
581 :     const int32_t iQuant,
582 :     int iFound)
583 :     {
584 :     /* Do a square search around given starting point, return SAD of best */
585 :    
586 :     int32_t iDirection=0;
587 :     int32_t iSAD;
588 :     VECTOR backupMV;
589 :     backupMV.x = startx;
590 :     backupMV.y = starty;
591 :    
592 :     /* It's one search with full square pattern, and new parts for all following diamonds */
593 :    
594 :     /* new direction are extra, so 1-4 is normal diamond
595 :     537
596 :     1*2
597 :     648
598 :     */
599 :    
600 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
601 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
602 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
603 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
604 :    
605 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
606 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
607 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
608 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
609 :    
610 :    
611 :     if (iDirection)
612 :     while (!iFound)
613 :     {
614 :     iFound = 1;
615 :     backupMV=*currMV;
616 :    
617 :     switch (iDirection)
618 :     {
619 :     case 1:
620 :     CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
621 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
622 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
623 :     break;
624 :     case 2:
625 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
626 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
627 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
628 :     break;
629 :    
630 :     case 3:
631 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
632 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
633 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
634 :     break;
635 :    
636 :     case 4:
637 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
638 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
639 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
640 :     break;
641 :    
642 :     case 5:
643 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
644 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
645 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
646 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
647 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
648 :     break;
649 :    
650 :     case 6:
651 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
652 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
653 :    
654 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
655 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
656 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
657 :    
658 :     break;
659 :    
660 :     case 7:
661 :     CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
662 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
663 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
664 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
665 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
666 :     break;
667 :    
668 :     case 8:
669 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
670 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
671 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
672 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
673 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
674 :     break;
675 :     default:
676 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
677 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
678 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
679 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
680 :    
681 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
682 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
683 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
684 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
685 :     break;
686 :     }
687 :     }
688 :     else
689 :     {
690 :     currMV->x = startx;
691 :     currMV->y = starty;
692 :     }
693 :     return iMinSAD;
694 :     }
695 :    
696 :    
697 :     int32_t Full16_MainSearch(
698 :     const uint8_t * const pRef,
699 :     const uint8_t * const pRefH,
700 :     const uint8_t * const pRefV,
701 :     const uint8_t * const pRefHV,
702 :     const uint8_t * const cur,
703 :     const int x, const int y,
704 :     int32_t startx, int32_t starty,
705 :     int32_t iMinSAD,
706 :     VECTOR * const currMV,
707 :     const VECTOR * const pmv,
708 :     const int32_t min_dx, const int32_t max_dx,
709 :     const int32_t min_dy, const int32_t max_dy,
710 :     const int32_t iEdgedWidth,
711 :     const int32_t iDiamondSize,
712 :     const int32_t iFcode,
713 :     const int32_t iQuant,
714 :     int iFound)
715 :     {
716 :     int32_t iSAD;
717 :     int32_t dx,dy;
718 :     VECTOR backupMV;
719 :     backupMV.x = startx;
720 :     backupMV.y = starty;
721 :    
722 :     for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
723 :     for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
724 :     NOCHECK_MV16_CANDIDATE(dx,dy);
725 :    
726 :     return iMinSAD;
727 :     }
728 :    
729 : chl 181 int32_t AdvDiamond16_MainSearch(
730 :     const uint8_t * const pRef,
731 :     const uint8_t * const pRefH,
732 :     const uint8_t * const pRefV,
733 :     const uint8_t * const pRefHV,
734 :     const uint8_t * const cur,
735 :     const int x, const int y,
736 :     int32_t startx, int32_t starty,
737 :     int32_t iMinSAD,
738 :     VECTOR * const currMV,
739 :     const VECTOR * const pmv,
740 :     const int32_t min_dx, const int32_t max_dx,
741 :     const int32_t min_dy, const int32_t max_dy,
742 :     const int32_t iEdgedWidth,
743 :     const int32_t iDiamondSize,
744 :     const int32_t iFcode,
745 :     const int32_t iQuant,
746 :     int iDirection)
747 :     {
748 :    
749 :     int32_t iSAD;
750 :    
751 :     /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
752 :    
753 :     if (iDirection)
754 :     {
755 :     CHECK_MV16_CANDIDATE(startx-iDiamondSize, starty);
756 :     CHECK_MV16_CANDIDATE(startx+iDiamondSize, starty);
757 :     CHECK_MV16_CANDIDATE(startx, starty-iDiamondSize);
758 :     CHECK_MV16_CANDIDATE(startx, starty+iDiamondSize);
759 :     }
760 :     else
761 :     {
762 :     int bDirection = 1+2+4+8;
763 :     do
764 :     {
765 :     iDirection = 0;
766 :     if (bDirection&1) //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
767 :     CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize,starty,1);
768 :    
769 :     if (bDirection&2)
770 :     CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize,starty,2);
771 :    
772 :     if (bDirection&4)
773 :     CHECK_MV16_CANDIDATE_DIR(startx,starty-iDiamondSize,4);
774 :    
775 :     if (bDirection&8)
776 :     CHECK_MV16_CANDIDATE_DIR(startx,starty+iDiamondSize,8);
777 :    
778 :     /* now we're doing diagonal checks near our candidate */
779 :    
780 :     if (iDirection) //checking if anything found
781 :     {
782 :     bDirection = iDirection;
783 :     iDirection = 0;
784 :     startx=currMV->x; starty=currMV->y;
785 :     if (bDirection & 3) //our candidate is left or right
786 :     {
787 :     CHECK_MV16_CANDIDATE_DIR(startx,starty+iDiamondSize, 8);
788 :     CHECK_MV16_CANDIDATE_DIR(startx,starty-iDiamondSize, 4);
789 :     }
790 :     else // what remains here is up or down
791 :     {
792 :     CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty, 2);
793 :     CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty, 1);
794 :     }
795 :    
796 :     if (iDirection)
797 :     { bDirection+=iDirection;
798 :     startx=currMV->x; starty=currMV->y;
799 :     }
800 :     }
801 :     else //about to quit, eh? not so fast....
802 :     {
803 :     switch (bDirection)
804 :     {
805 :     case 2:
806 :     CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);
807 :     CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);
808 :     break;
809 :     case 1:
810 :     CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);
811 :     CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);
812 :     break;
813 :     case 2+4:
814 :     CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);
815 :     CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);
816 :     CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);
817 :     break;
818 :     case 4:
819 :     CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);
820 :     CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);
821 :     break;
822 :     case 8:
823 :     CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);
824 :     CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);
825 :     break;
826 :     case 1+4:
827 :     CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);
828 :     CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);
829 :     CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);
830 :     break;
831 :     case 2+8:
832 :     CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);
833 :     CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);
834 :     CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);
835 :     break;
836 :     case 1+8:
837 :     CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);
838 :     CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);
839 :     CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);
840 :     break;
841 :     default: //1+2+4+8 == we didn't find anything at all
842 :     CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);
843 :     CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);
844 :     CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);
845 :     CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);
846 :     break;
847 :     }
848 :     if (!iDirection) break; //ok, the end. really
849 :     else
850 :     { bDirection=iDirection;
851 :     startx=currMV->x; starty=currMV->y;
852 :     }
853 :     }
854 :     }
855 :     while (1); //forever
856 :     }
857 :     return iMinSAD;
858 :     }
859 :    
860 :     int32_t AdvDiamond8_MainSearch(
861 :     const uint8_t * const pRef,
862 :     const uint8_t * const pRefH,
863 :     const uint8_t * const pRefV,
864 :     const uint8_t * const pRefHV,
865 :     const uint8_t * const cur,
866 :     const int x, const int y,
867 :     int32_t startx, int32_t starty,
868 :     int32_t iMinSAD,
869 :     VECTOR * const currMV,
870 :     const VECTOR * const pmv,
871 :     const int32_t min_dx, const int32_t max_dx,
872 :     const int32_t min_dy, const int32_t max_dy,
873 :     const int32_t iEdgedWidth,
874 :     const int32_t iDiamondSize,
875 :     const int32_t iFcode,
876 :     const int32_t iQuant,
877 :     int iDirection)
878 :     {
879 :    
880 :     int32_t iSAD;
881 :    
882 :     /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
883 :    
884 :     if (iDirection)
885 :     {
886 :     CHECK_MV8_CANDIDATE(startx-iDiamondSize, starty);
887 :     CHECK_MV8_CANDIDATE(startx+iDiamondSize, starty);
888 :     CHECK_MV8_CANDIDATE(startx, starty-iDiamondSize);
889 :     CHECK_MV8_CANDIDATE(startx, starty+iDiamondSize);
890 :     }
891 :     else
892 :     {
893 :     int bDirection = 1+2+4+8;
894 :     do
895 :     {
896 :     iDirection = 0;
897 :     if (bDirection&1) //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
898 :     CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize,starty,1);
899 :    
900 :     if (bDirection&2)
901 :     CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize,starty,2);
902 :    
903 :     if (bDirection&4)
904 :     CHECK_MV8_CANDIDATE_DIR(startx,starty-iDiamondSize,4);
905 :    
906 :     if (bDirection&8)
907 :     CHECK_MV8_CANDIDATE_DIR(startx,starty+iDiamondSize,8);
908 :    
909 :     /* now we're doing diagonal checks near our candidate */
910 :    
911 :     if (iDirection) //checking if anything found
912 :     {
913 :     bDirection = iDirection;
914 :     iDirection = 0;
915 :     startx=currMV->x; starty=currMV->y;
916 :     if (bDirection & 3) //our candidate is left or right
917 :     {
918 :     CHECK_MV8_CANDIDATE_DIR(startx,starty+iDiamondSize, 8);
919 :     CHECK_MV8_CANDIDATE_DIR(startx,starty-iDiamondSize, 4);
920 :     }
921 :     else // what remains here is up or down
922 :     {
923 :     CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty, 2);
924 :     CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty, 1);
925 :     }
926 :    
927 :     if (iDirection)
928 :     { bDirection+=iDirection;
929 :     startx=currMV->x; starty=currMV->y;
930 :     }
931 :     }
932 :     else //about to quit, eh? not so fast....
933 :     {
934 :     switch (bDirection)
935 :     {
936 :     case 2:
937 :     CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);
938 :     CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);
939 :     break;
940 :     case 1:
941 :     CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);
942 :     CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);
943 :     break;
944 :     case 2+4:
945 :     CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);
946 :     CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);
947 :     CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);
948 :     break;
949 :     case 4:
950 :     CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);
951 :     CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);
952 :     break;
953 :     case 8:
954 :     CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);
955 :     CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);
956 :     break;
957 :     case 1+4:
958 :     CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);
959 :     CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);
960 :     CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);
961 :     break;
962 :     case 2+8:
963 :     CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);
964 :     CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);
965 :     CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);
966 :     break;
967 :     case 1+8:
968 :     CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);
969 :     CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);
970 :     CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);
971 :     break;
972 :     default: //1+2+4+8 == we didn't find anything at all
973 :     CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);
974 :     CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);
975 :     CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);
976 :     CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);
977 :     break;
978 :     }
979 :     if (!(iDirection)) break; //ok, the end. really
980 :     else
981 :     { bDirection=iDirection;
982 :     startx=currMV->x; starty=currMV->y;
983 :     }
984 :     }
985 :     }
986 :     while (1); //forever
987 :     }
988 :     return iMinSAD;
989 :     }
990 :    
991 :    
992 : chl 96 int32_t Full8_MainSearch(
993 :     const uint8_t * const pRef,
994 :     const uint8_t * const pRefH,
995 :     const uint8_t * const pRefV,
996 :     const uint8_t * const pRefHV,
997 :     const uint8_t * const cur,
998 :     const int x, const int y,
999 :     int32_t startx, int32_t starty,
1000 :     int32_t iMinSAD,
1001 :     VECTOR * const currMV,
1002 :     const VECTOR * const pmv,
1003 :     const int32_t min_dx, const int32_t max_dx,
1004 :     const int32_t min_dy, const int32_t max_dy,
1005 :     const int32_t iEdgedWidth,
1006 :     const int32_t iDiamondSize,
1007 :     const int32_t iFcode,
1008 :     const int32_t iQuant,
1009 :     int iFound)
1010 :     {
1011 :     int32_t iSAD;
1012 :     int32_t dx,dy;
1013 :     VECTOR backupMV;
1014 :     backupMV.x = startx;
1015 :     backupMV.y = starty;
1016 :    
1017 :     for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
1018 :     for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
1019 :     NOCHECK_MV8_CANDIDATE(dx,dy);
1020 :    
1021 :     return iMinSAD;
1022 :     }
1023 :    
1024 :    
1025 :    
1026 :     int32_t Halfpel16_Refine(
1027 : edgomez 78 const uint8_t * const pRef,
1028 :     const uint8_t * const pRefH,
1029 :     const uint8_t * const pRefV,
1030 :     const uint8_t * const pRefHV,
1031 :     const uint8_t * const cur,
1032 :     const int x, const int y,
1033 :     VECTOR * const currMV,
1034 :     int32_t iMinSAD,
1035 :     const VECTOR * const pmv,
1036 :     const int32_t min_dx, const int32_t max_dx,
1037 :     const int32_t min_dy, const int32_t max_dy,
1038 :     const int32_t iFcode,
1039 :     const int32_t iQuant,
1040 :     const int32_t iEdgedWidth)
1041 : Isibaar 3 {
1042 :     /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
1043 :    
1044 :     int32_t iSAD;
1045 :     VECTOR backupMV = *currMV;
1046 :    
1047 :     CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y-1);
1048 :     CHECK_MV16_CANDIDATE(backupMV.x ,backupMV.y-1);
1049 :     CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y-1);
1050 :     CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y);
1051 :     CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y);
1052 :     CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y+1);
1053 :     CHECK_MV16_CANDIDATE(backupMV.x ,backupMV.y+1);
1054 :     CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y+1);
1055 :    
1056 :     return iMinSAD;
1057 :     }
1058 :    
1059 :     #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1060 :    
1061 : chl 96
1062 : Isibaar 3 int32_t PMVfastSearch16(
1063 : chl 96 const uint8_t * const pRef,
1064 :     const uint8_t * const pRefH,
1065 :     const uint8_t * const pRefV,
1066 :     const uint8_t * const pRefHV,
1067 :     const IMAGE * const pCur,
1068 :     const int x, const int y,
1069 :     const uint32_t MotionFlags,
1070 : suxen_drol 136 const uint32_t iQuant,
1071 :     const uint32_t iFcode,
1072 : chl 96 const MBParam * const pParam,
1073 : suxen_drol 136 const MACROBLOCK * const pMBs,
1074 :     const MACROBLOCK * const prevMBs,
1075 : chl 96 VECTOR * const currMV,
1076 :     VECTOR * const currPMV)
1077 : Isibaar 3 {
1078 : chenm001 132 const uint32_t iWcount = pParam->mb_width;
1079 : Isibaar 3 const int32_t iWidth = pParam->width;
1080 :     const int32_t iHeight = pParam->height;
1081 :     const int32_t iEdgedWidth = pParam->edged_width;
1082 :    
1083 :     const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
1084 :    
1085 :     int32_t iDiamondSize;
1086 :    
1087 :     int32_t min_dx;
1088 :     int32_t max_dx;
1089 :     int32_t min_dy;
1090 :     int32_t max_dy;
1091 :    
1092 :     int32_t iFound;
1093 :    
1094 :     VECTOR newMV;
1095 :     VECTOR backupMV; /* just for PMVFAST */
1096 :    
1097 :     VECTOR pmv[4];
1098 :     int32_t psad[4];
1099 : chl 181
1100 :     MainSearch16FuncPtr MainSearchPtr;
1101 : Isibaar 3
1102 : chl 172 // const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
1103 : suxen_drol 136 const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1104 : Isibaar 3
1105 :     static int32_t threshA,threshB;
1106 :     int32_t bPredEq;
1107 :     int32_t iMinSAD,iSAD;
1108 :    
1109 :     /* Get maximum range */
1110 :     get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1111 : edgomez 78 x, y, 16, iWidth, iHeight, iFcode);
1112 : Isibaar 3
1113 :     /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1114 :    
1115 :     if (!(MotionFlags & PMV_HALFPEL16 ))
1116 :     { min_dx = EVEN(min_dx);
1117 : edgomez 78 max_dx = EVEN(max_dx);
1118 :     min_dy = EVEN(min_dy);
1119 :     max_dy = EVEN(max_dy);
1120 : Isibaar 3 } /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1121 :    
1122 :    
1123 :     bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1124 :    
1125 :     if ((x==0) && (y==0) )
1126 :     {
1127 :     threshA = 512;
1128 :     threshB = 1024;
1129 :    
1130 :     }
1131 :     else
1132 :     {
1133 :     threshA = psad[0];
1134 :     threshB = threshA+256;
1135 :     if (threshA< 512) threshA = 512;
1136 :     if (threshA>1024) threshA = 1024;
1137 :     if (threshB>1792) threshB = 1792;
1138 :     }
1139 :    
1140 :     iFound=0;
1141 :    
1142 :     /* Step 4: Calculate SAD around the Median prediction.
1143 : edgomez 78 MinSAD=SAD
1144 :     If Motion Vector equal to Previous frame motion vector
1145 :     and MinSAD<PrevFrmSAD goto Step 10.
1146 :     If SAD<=256 goto Step 10.
1147 : Isibaar 3 */
1148 :    
1149 :     *currMV=pmv[0]; /* current best := prediction */
1150 :     if (!(MotionFlags & PMV_HALFPEL16 ))
1151 :     { /* This should NOT be necessary! */
1152 :     currMV->x = EVEN(currMV->x);
1153 :     currMV->y = EVEN(currMV->y);
1154 :     }
1155 :    
1156 :     if (currMV->x > max_dx)
1157 : edgomez 78 {
1158 :     currMV->x=max_dx;
1159 :     }
1160 : Isibaar 3 if (currMV->x < min_dx)
1161 : edgomez 78 {
1162 :     currMV->x=min_dx;
1163 :     }
1164 : Isibaar 3 if (currMV->y > max_dy)
1165 : edgomez 78 {
1166 :     currMV->y=max_dy;
1167 :     }
1168 : Isibaar 3 if (currMV->y < min_dy)
1169 : edgomez 78 {
1170 :     currMV->y=min_dy;
1171 :     }
1172 : Isibaar 3
1173 :     iMinSAD = sad16( cur,
1174 : edgomez 78 get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
1175 :     iEdgedWidth, MV_MAX_ERROR);
1176 : chl 141 iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);
1177 : Isibaar 3
1178 : suxen_drol 136 if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
1179 : edgomez 78 {
1180 : chl 169 if (iMinSAD < 2*iQuant) // high chances for SKIP-mode
1181 :     {
1182 :     if (!MVzero(*currMV))
1183 :     {
1184 :     iMinSAD += MV16_00_BIAS;
1185 :     CHECK_MV16_ZERO; // (0,0) saves space for letterboxed pictures
1186 :     iMinSAD -= MV16_00_BIAS;
1187 :     }
1188 :     }
1189 :    
1190 : edgomez 78 if (MotionFlags & PMV_QUICKSTOP16)
1191 : chl 96 goto PMVfast16_Terminate_without_Refine;
1192 :     if (MotionFlags & PMV_EARLYSTOP16)
1193 :     goto PMVfast16_Terminate_with_Refine;
1194 : edgomez 78 }
1195 : Isibaar 3
1196 : chl 169
1197 :     /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1198 :     vector of the median.
1199 :     If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1200 :     */
1201 :    
1202 :     if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[0]) ) )
1203 :     iFound=2;
1204 :    
1205 :     /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1206 :     Otherwise select large Diamond Search.
1207 :     */
1208 :    
1209 :     if ( (!MVzero(pmv[0])) || (threshB<1536) || (bPredEq) )
1210 :     iDiamondSize=1; // halfpel!
1211 :     else
1212 :     iDiamondSize=2; // halfpel!
1213 :    
1214 :     if (!(MotionFlags & PMV_HALFPELDIAMOND16) )
1215 :     iDiamondSize*=2;
1216 :    
1217 : Isibaar 3 /*
1218 : edgomez 78 Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
1219 :     Also calculate (0,0) but do not subtract offset.
1220 :     Let MinSAD be the smallest SAD up to this point.
1221 : chl 140 If MV is (0,0) subtract offset.
1222 : Isibaar 3 */
1223 :    
1224 :     // (0,0) is always possible
1225 :    
1226 : chl 169 if (!MVzero(pmv[0]))
1227 :     CHECK_MV16_ZERO;
1228 : Isibaar 3
1229 :     // previous frame MV is always possible
1230 : chl 169
1231 :     if (!MVzero(prevMB->mvs[0]))
1232 :     if (!MVequal(prevMB->mvs[0],pmv[0]))
1233 :     CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1234 : Isibaar 3
1235 :     // left neighbour, if allowed
1236 : chl 169
1237 :     if (!MVzero(pmv[1]))
1238 :     if (!MVequal(pmv[1],prevMB->mvs[0]))
1239 :     if (!MVequal(pmv[1],pmv[0]))
1240 : Isibaar 3 {
1241 :     if (!(MotionFlags & PMV_HALFPEL16 ))
1242 :     { pmv[1].x = EVEN(pmv[1].x);
1243 : chl 169 pmv[1].y = EVEN(pmv[1].y);
1244 : Isibaar 3 }
1245 : chl 169
1246 : Isibaar 3 CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1247 :     }
1248 :    
1249 :     // top neighbour, if allowed
1250 : chl 169 if (!MVzero(pmv[2]))
1251 :     if (!MVequal(pmv[2],prevMB->mvs[0]))
1252 :     if (!MVequal(pmv[2],pmv[0]))
1253 :     if (!MVequal(pmv[2],pmv[1]))
1254 : Isibaar 3 {
1255 :     if (!(MotionFlags & PMV_HALFPEL16 ))
1256 :     { pmv[2].x = EVEN(pmv[2].x);
1257 : chl 169 pmv[2].y = EVEN(pmv[2].y);
1258 : Isibaar 3 }
1259 :     CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1260 :    
1261 :     // top right neighbour, if allowed
1262 : chl 169 if (!MVzero(pmv[3]))
1263 :     if (!MVequal(pmv[3],prevMB->mvs[0]))
1264 :     if (!MVequal(pmv[3],pmv[0]))
1265 :     if (!MVequal(pmv[3],pmv[1]))
1266 :     if (!MVequal(pmv[3],pmv[2]))
1267 : Isibaar 3 {
1268 :     if (!(MotionFlags & PMV_HALFPEL16 ))
1269 :     { pmv[3].x = EVEN(pmv[3].x);
1270 : chl 169 pmv[3].y = EVEN(pmv[3].y);
1271 : Isibaar 3 }
1272 :     CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
1273 :     }
1274 :     }
1275 : chl 140
1276 : chl 141 if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96)*/ )
1277 : chl 140 iMinSAD -= MV16_00_BIAS;
1278 : Isibaar 3
1279 : chl 140
1280 : Isibaar 3 /* Step 6: If MinSAD <= thresa goto Step 10.
1281 :     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
1282 :     */
1283 :    
1284 : suxen_drol 136 if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
1285 : edgomez 78 {
1286 :     if (MotionFlags & PMV_QUICKSTOP16)
1287 : chl 96 goto PMVfast16_Terminate_without_Refine;
1288 :     if (MotionFlags & PMV_EARLYSTOP16)
1289 :     goto PMVfast16_Terminate_with_Refine;
1290 : edgomez 78 }
1291 : Isibaar 3
1292 :    
1293 :     /************ (Diamond Search) **************/
1294 :     /*
1295 : edgomez 78 Step 7: Perform Diamond search, with either the small or large diamond.
1296 :     If Found=2 only examine one Diamond pattern, and afterwards goto step 10
1297 :     Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
1298 :     If center then goto step 10.
1299 :     Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
1300 :     Refine by using small diamond and goto step 10.
1301 : Isibaar 3 */
1302 :    
1303 : chl 181 if (MotionFlags & PMV_USESQUARES16)
1304 :     MainSearchPtr = Square16_MainSearch;
1305 :     else
1306 :     if (MotionFlags & PMV_ADVANCEDDIAMOND16)
1307 :     MainSearchPtr = AdvDiamond16_MainSearch;
1308 :     else
1309 :     MainSearchPtr = Diamond16_MainSearch;
1310 :    
1311 : Isibaar 3 backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1312 :    
1313 :     /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1314 : chl 181 iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1315 : edgomez 78 x, y,
1316 :     currMV->x, currMV->y, iMinSAD, &newMV,
1317 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
1318 : Isibaar 3
1319 :     if (iSAD < iMinSAD)
1320 :     {
1321 :     *currMV = newMV;
1322 :     iMinSAD = iSAD;
1323 :     }
1324 :    
1325 :     if (MotionFlags & PMV_EXTSEARCH16)
1326 :     {
1327 :     /* extended: search (up to) two more times: orignal prediction and (0,0) */
1328 :    
1329 :     if (!(MVequal(pmv[0],backupMV)) )
1330 : chl 181 { iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1331 : edgomez 78 x, y,
1332 :     pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1333 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
1334 : Isibaar 3
1335 : edgomez 78 if (iSAD < iMinSAD)
1336 :     {
1337 :     *currMV = newMV;
1338 :     iMinSAD = iSAD;
1339 : Isibaar 3 }
1340 : edgomez 78 }
1341 : Isibaar 3
1342 :     if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1343 : chl 181 { iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1344 : edgomez 78 x, y,
1345 :     0, 0, iMinSAD, &newMV,
1346 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
1347 : Isibaar 3
1348 : edgomez 78 if (iSAD < iMinSAD)
1349 :     {
1350 :     *currMV = newMV;
1351 :     iMinSAD = iSAD;
1352 : Isibaar 3 }
1353 : edgomez 78 }
1354 : Isibaar 3 }
1355 :    
1356 :     /*
1357 : edgomez 78 Step 10: The motion vector is chosen according to the block corresponding to MinSAD.
1358 : Isibaar 3 */
1359 :    
1360 : chl 96 PMVfast16_Terminate_with_Refine:
1361 : Isibaar 3 if (MotionFlags & PMV_HALFPELREFINE16) // perform final half-pel step
1362 : chl 96 iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1363 :     x, y,
1364 :     currMV, iMinSAD,
1365 :     pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1366 : Isibaar 3
1367 : chl 96 PMVfast16_Terminate_without_Refine:
1368 : Isibaar 3 currPMV->x = currMV->x - pmv[0].x;
1369 :     currPMV->y = currMV->y - pmv[0].y;
1370 :     return iMinSAD;
1371 :     }
1372 :    
1373 :    
1374 :    
1375 :    
1376 :    
1377 :    
1378 : chl 96 int32_t Diamond8_MainSearch(
1379 : edgomez 78 const uint8_t * const pRef,
1380 :     const uint8_t * const pRefH,
1381 :     const uint8_t * const pRefV,
1382 :     const uint8_t * const pRefHV,
1383 :     const uint8_t * const cur,
1384 :     const int x, const int y,
1385 :     int32_t startx, int32_t starty,
1386 :     int32_t iMinSAD,
1387 :     VECTOR * const currMV,
1388 :     const VECTOR * const pmv,
1389 :     const int32_t min_dx, const int32_t max_dx,
1390 :     const int32_t min_dy, const int32_t max_dy,
1391 :     const int32_t iEdgedWidth,
1392 :     const int32_t iDiamondSize,
1393 :     const int32_t iFcode,
1394 :     const int32_t iQuant,
1395 :     int iFound)
1396 : Isibaar 3 {
1397 :     /* Do a diamond search around given starting point, return SAD of best */
1398 :    
1399 :     int32_t iDirection=0;
1400 :     int32_t iSAD;
1401 :     VECTOR backupMV;
1402 :     backupMV.x = startx;
1403 :     backupMV.y = starty;
1404 :    
1405 :     /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1406 :    
1407 :     CHECK_MV8_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
1408 :     CHECK_MV8_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
1409 :     CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
1410 :     CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1411 :    
1412 :     if (iDirection)
1413 :     while (!iFound)
1414 :     {
1415 :     iFound = 1;
1416 :     backupMV=*currMV; // since iDirection!=0, this is well defined!
1417 :    
1418 :     if ( iDirection != 2)
1419 :     CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
1420 :     if ( iDirection != 1)
1421 :     CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);
1422 :     if ( iDirection != 4)
1423 :     CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);
1424 :     if ( iDirection != 3)
1425 :     CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);
1426 :     }
1427 :     else
1428 : edgomez 78 {
1429 :     currMV->x = startx;
1430 :     currMV->y = starty;
1431 :     }
1432 : Isibaar 3 return iMinSAD;
1433 :     }
1434 :    
1435 : chl 96 int32_t Halfpel8_Refine(
1436 : edgomez 78 const uint8_t * const pRef,
1437 :     const uint8_t * const pRefH,
1438 :     const uint8_t * const pRefV,
1439 :     const uint8_t * const pRefHV,
1440 :     const uint8_t * const cur,
1441 :     const int x, const int y,
1442 :     VECTOR * const currMV,
1443 :     int32_t iMinSAD,
1444 :     const VECTOR * const pmv,
1445 :     const int32_t min_dx, const int32_t max_dx,
1446 :     const int32_t min_dy, const int32_t max_dy,
1447 :     const int32_t iFcode,
1448 :     const int32_t iQuant,
1449 :     const int32_t iEdgedWidth)
1450 : Isibaar 3 {
1451 :     /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
1452 :    
1453 :     int32_t iSAD;
1454 :     VECTOR backupMV = *currMV;
1455 :    
1456 :     CHECK_MV8_CANDIDATE(backupMV.x-1,backupMV.y-1);
1457 :     CHECK_MV8_CANDIDATE(backupMV.x ,backupMV.y-1);
1458 :     CHECK_MV8_CANDIDATE(backupMV.x+1,backupMV.y-1);
1459 :     CHECK_MV8_CANDIDATE(backupMV.x-1,backupMV.y);
1460 :     CHECK_MV8_CANDIDATE(backupMV.x+1,backupMV.y);
1461 :     CHECK_MV8_CANDIDATE(backupMV.x-1,backupMV.y+1);
1462 :     CHECK_MV8_CANDIDATE(backupMV.x ,backupMV.y+1);
1463 :     CHECK_MV8_CANDIDATE(backupMV.x+1,backupMV.y+1);
1464 :    
1465 :     return iMinSAD;
1466 :     }
1467 :    
1468 :    
1469 :     #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1470 :    
1471 :     int32_t PMVfastSearch8(
1472 : chl 96 const uint8_t * const pRef,
1473 :     const uint8_t * const pRefH,
1474 :     const uint8_t * const pRefV,
1475 :     const uint8_t * const pRefHV,
1476 :     const IMAGE * const pCur,
1477 :     const int x, const int y,
1478 : suxen_drol 136 const int start_x, const int start_y,
1479 : chl 96 const uint32_t MotionFlags,
1480 : suxen_drol 136 const uint32_t iQuant,
1481 :     const uint32_t iFcode,
1482 : chl 96 const MBParam * const pParam,
1483 : suxen_drol 136 const MACROBLOCK * const pMBs,
1484 :     const MACROBLOCK * const prevMBs,
1485 : chl 96 VECTOR * const currMV,
1486 :     VECTOR * const currPMV)
1487 : Isibaar 3 {
1488 : suxen_drol 136 const uint32_t iWcount = pParam->mb_width;
1489 : Isibaar 3 const int32_t iWidth = pParam->width;
1490 :     const int32_t iHeight = pParam->height;
1491 :     const int32_t iEdgedWidth = pParam->edged_width;
1492 :    
1493 :     const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;
1494 :    
1495 :     int32_t iDiamondSize;
1496 :    
1497 :     int32_t min_dx;
1498 :     int32_t max_dx;
1499 :     int32_t min_dy;
1500 :     int32_t max_dy;
1501 :    
1502 :     VECTOR pmv[4];
1503 :     int32_t psad[4];
1504 :     VECTOR newMV;
1505 :     VECTOR backupMV;
1506 : edgomez 170 VECTOR startMV;
1507 : Isibaar 3
1508 : chl 172 // const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1509 : suxen_drol 136 const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1510 : Isibaar 3
1511 :     static int32_t threshA,threshB;
1512 :     int32_t iFound,bPredEq;
1513 :     int32_t iMinSAD,iSAD;
1514 :    
1515 : chl 169 int32_t iSubBlock = (y&1)+(y&1) + (x&1);
1516 : Isibaar 3
1517 : chl 181 MainSearch8FuncPtr MainSearchPtr;
1518 :    
1519 : edgomez 170 /* Init variables */
1520 :     startMV.x = start_x;
1521 :     startMV.y = start_y;
1522 :    
1523 :     /* Get maximum range */
1524 : edgomez 78 get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1525 :     x, y, 8, iWidth, iHeight, iFcode);
1526 : Isibaar 3
1527 :     if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))
1528 :     { min_dx = EVEN(min_dx);
1529 : chl 169 max_dx = EVEN(max_dx);
1530 :     min_dy = EVEN(min_dy);
1531 :     max_dy = EVEN(max_dy);
1532 : Isibaar 3 } /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
1533 :    
1534 :    
1535 :     bPredEq = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);
1536 :    
1537 :     if ((x==0) && (y==0) )
1538 :     {
1539 :     threshA = 512/4;
1540 :     threshB = 1024/4;
1541 :    
1542 :     }
1543 :     else
1544 :     {
1545 :     threshA = psad[0]/4; /* good estimate */
1546 :     threshB = threshA+256/4;
1547 :     if (threshA< 512/4) threshA = 512/4;
1548 :     if (threshA>1024/4) threshA = 1024/4;
1549 :     if (threshB>1792/4) threshB = 1792/4;
1550 :     }
1551 :    
1552 :     iFound=0;
1553 :    
1554 :     /* Step 4: Calculate SAD around the Median prediction.
1555 : edgomez 78 MinSAD=SAD
1556 :     If Motion Vector equal to Previous frame motion vector
1557 :     and MinSAD<PrevFrmSAD goto Step 10.
1558 :     If SAD<=256 goto Step 10.
1559 : Isibaar 3 */
1560 :    
1561 :    
1562 :     // Prepare for main loop
1563 :    
1564 : chl 181 // if (MotionFlags & PMV_USESQUARES8)
1565 :     // MainSearchPtr = Square8_MainSearch;
1566 :     // else
1567 :    
1568 :     if (MotionFlags & PMV_ADVANCEDDIAMOND8)
1569 :     MainSearchPtr = AdvDiamond8_MainSearch;
1570 :     else
1571 :     MainSearchPtr = Diamond8_MainSearch;
1572 :    
1573 :    
1574 : chl 169 *currMV = startMV;
1575 : Isibaar 3
1576 :     iMinSAD = sad8( cur,
1577 : edgomez 78 get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
1578 :     iEdgedWidth);
1579 : chl 141 iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode, iQuant);
1580 : Isibaar 3
1581 : chl 169 if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock]))
1582 :     && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1583 : edgomez 78 {
1584 : chl 96 if (MotionFlags & PMV_QUICKSTOP16)
1585 :     goto PMVfast8_Terminate_without_Refine;
1586 :     if (MotionFlags & PMV_EARLYSTOP16)
1587 :     goto PMVfast8_Terminate_with_Refine;
1588 : edgomez 78 }
1589 : Isibaar 3
1590 : chl 169 /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1591 :     vector of the median.
1592 :     If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1593 :     */
1594 : chl 96
1595 : chl 169 if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[iSubBlock]) ) )
1596 :     iFound=2;
1597 :    
1598 :     /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1599 :     Otherwise select large Diamond Search.
1600 :     */
1601 :    
1602 :     if ( (!MVzero(pmv[0])) || (threshB<1536/4) || (bPredEq) )
1603 :     iDiamondSize=1; // 1 halfpel!
1604 :     else
1605 :     iDiamondSize=2; // 2 halfpel = 1 full pixel!
1606 :    
1607 :     if (!(MotionFlags & PMV_HALFPELDIAMOND8) )
1608 :     iDiamondSize*=2;
1609 :    
1610 :    
1611 : Isibaar 3 /*
1612 : edgomez 78 Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
1613 :     Also calculate (0,0) but do not subtract offset.
1614 :     Let MinSAD be the smallest SAD up to this point.
1615 : chl 140 If MV is (0,0) subtract offset.
1616 : Isibaar 3 */
1617 :    
1618 : chl 169 // the median prediction might be even better than mv16
1619 : Isibaar 3
1620 : chl 169 if (!MVequal(pmv[0],startMV))
1621 :     CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);
1622 :    
1623 :     // (0,0) if needed
1624 :     if (!MVzero(pmv[0]))
1625 :     if (!MVzero(startMV))
1626 : Isibaar 3 CHECK_MV8_ZERO;
1627 :    
1628 : chl 169 // previous frame MV if needed
1629 :     if (!MVzero(prevMB->mvs[iSubBlock]))
1630 :     if (!MVequal(prevMB->mvs[iSubBlock],startMV))
1631 :     if (!MVequal(prevMB->mvs[iSubBlock],pmv[0]))
1632 : chl 140 CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
1633 : chl 169
1634 :     if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1635 :     {
1636 :     if (MotionFlags & PMV_QUICKSTOP16)
1637 :     goto PMVfast8_Terminate_without_Refine;
1638 :     if (MotionFlags & PMV_EARLYSTOP16)
1639 :     goto PMVfast8_Terminate_with_Refine;
1640 :     }
1641 :    
1642 :    
1643 :     // left neighbour, if allowed and needed
1644 :     if (!MVzero(pmv[1]))
1645 :     if (!MVequal(pmv[1],startMV))
1646 :     if (!MVequal(pmv[1],prevMB->mvs[iSubBlock]))
1647 :     if (!MVequal(pmv[1],pmv[0]))
1648 : Isibaar 3 {
1649 :     if (!(MotionFlags & PMV_HALFPEL8 ))
1650 :     { pmv[1].x = EVEN(pmv[1].x);
1651 : chl 169 pmv[1].y = EVEN(pmv[1].y);
1652 : Isibaar 3 }
1653 :     CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1654 :     }
1655 :    
1656 : chl 169 // top neighbour, if allowed and needed
1657 :     if (!MVzero(pmv[2]))
1658 :     if (!MVequal(pmv[2],startMV))
1659 :     if (!MVequal(pmv[2],prevMB->mvs[iSubBlock]))
1660 :     if (!MVequal(pmv[2],pmv[0]))
1661 :     if (!MVequal(pmv[2],pmv[1]))
1662 : Isibaar 3 {
1663 :     if (!(MotionFlags & PMV_HALFPEL8 ))
1664 :     { pmv[2].x = EVEN(pmv[2].x);
1665 : chl 169 pmv[2].y = EVEN(pmv[2].y);
1666 : Isibaar 3 }
1667 :     CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1668 :    
1669 : chl 169 // top right neighbour, if allowed and needed
1670 :     if (!MVzero(pmv[3]))
1671 :     if (!MVequal(pmv[3],startMV))
1672 :     if (!MVequal(pmv[3],prevMB->mvs[iSubBlock]))
1673 :     if (!MVequal(pmv[3],pmv[0]))
1674 :     if (!MVequal(pmv[3],pmv[1]))
1675 :     if (!MVequal(pmv[3],pmv[2]))
1676 : Isibaar 3 {
1677 : edgomez 78 if (!(MotionFlags & PMV_HALFPEL8 ))
1678 :     { pmv[3].x = EVEN(pmv[3].x);
1679 : chl 169 pmv[3].y = EVEN(pmv[3].y);
1680 : edgomez 78 }
1681 : Isibaar 3 CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);
1682 :     }
1683 :     }
1684 :    
1685 : chl 141 if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1686 : chl 140 iMinSAD -= MV8_00_BIAS;
1687 :    
1688 :    
1689 : Isibaar 3 /* Step 6: If MinSAD <= thresa goto Step 10.
1690 :     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
1691 :     */
1692 :    
1693 : chl 140 if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1694 : edgomez 78 {
1695 : chl 96 if (MotionFlags & PMV_QUICKSTOP16)
1696 :     goto PMVfast8_Terminate_without_Refine;
1697 :     if (MotionFlags & PMV_EARLYSTOP16)
1698 :     goto PMVfast8_Terminate_with_Refine;
1699 : edgomez 78 }
1700 : Isibaar 3
1701 :     /************ (Diamond Search) **************/
1702 :     /*
1703 : edgomez 78 Step 7: Perform Diamond search, with either the small or large diamond.
1704 :     If Found=2 only examine one Diamond pattern, and afterwards goto step 10
1705 :     Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
1706 :     If center then goto step 10.
1707 :     Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
1708 :     Refine by using small diamond and goto step 10.
1709 : Isibaar 3 */
1710 :    
1711 :     backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1712 :    
1713 :     /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1714 : chl 181 iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1715 : edgomez 78 x, y,
1716 :     currMV->x, currMV->y, iMinSAD, &newMV,
1717 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
1718 : Isibaar 3
1719 :     if (iSAD < iMinSAD)
1720 :     {
1721 :     *currMV = newMV;
1722 :     iMinSAD = iSAD;
1723 :     }
1724 :    
1725 :     if (MotionFlags & PMV_EXTSEARCH8)
1726 :     {
1727 :     /* extended: search (up to) two more times: orignal prediction and (0,0) */
1728 :    
1729 :     if (!(MVequal(pmv[0],backupMV)) )
1730 : chl 181 { iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1731 : edgomez 78 x, y,
1732 :     pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1733 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
1734 : Isibaar 3
1735 : edgomez 78 if (iSAD < iMinSAD)
1736 :     {
1737 :     *currMV = newMV;
1738 :     iMinSAD = iSAD;
1739 : Isibaar 3 }
1740 : edgomez 78 }
1741 : Isibaar 3
1742 :     if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1743 : chl 181 { iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1744 : edgomez 78 x, y,
1745 :     0, 0, iMinSAD, &newMV,
1746 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
1747 : Isibaar 3
1748 : edgomez 78 if (iSAD < iMinSAD)
1749 :     {
1750 :     *currMV = newMV;
1751 :     iMinSAD = iSAD;
1752 : Isibaar 3 }
1753 : edgomez 78 }
1754 : Isibaar 3 }
1755 :    
1756 :     /* Step 10: The motion vector is chosen according to the block corresponding to MinSAD.
1757 : edgomez 78 By performing an optional local half-pixel search, we can refine this result even further.
1758 : Isibaar 3 */
1759 :    
1760 : chl 96 PMVfast8_Terminate_with_Refine:
1761 : Isibaar 3 if (MotionFlags & PMV_HALFPELREFINE8) // perform final half-pel step
1762 : chl 96 iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1763 : edgomez 78 x, y,
1764 :     currMV, iMinSAD,
1765 :     pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1766 : Isibaar 3
1767 :    
1768 : chl 96 PMVfast8_Terminate_without_Refine:
1769 : Isibaar 3 currPMV->x = currMV->x - pmv[0].x;
1770 :     currPMV->y = currMV->y - pmv[0].y;
1771 :    
1772 :     return iMinSAD;
1773 :     }
1774 : chl 96
1775 :     int32_t EPZSSearch16(
1776 :     const uint8_t * const pRef,
1777 :     const uint8_t * const pRefH,
1778 :     const uint8_t * const pRefV,
1779 :     const uint8_t * const pRefHV,
1780 :     const IMAGE * const pCur,
1781 :     const int x, const int y,
1782 :     const uint32_t MotionFlags,
1783 : suxen_drol 136 const uint32_t iQuant,
1784 :     const uint32_t iFcode,
1785 : chl 96 const MBParam * const pParam,
1786 : suxen_drol 136 const MACROBLOCK * const pMBs,
1787 :     const MACROBLOCK * const prevMBs,
1788 : chl 96 VECTOR * const currMV,
1789 :     VECTOR * const currPMV)
1790 :     {
1791 : chenm001 132 const uint32_t iWcount = pParam->mb_width;
1792 :     const uint32_t iHcount = pParam->mb_height;
1793 : chl 96
1794 :     const int32_t iWidth = pParam->width;
1795 :     const int32_t iHeight = pParam->height;
1796 :     const int32_t iEdgedWidth = pParam->edged_width;
1797 :    
1798 :     const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
1799 :    
1800 :     int32_t min_dx;
1801 :     int32_t max_dx;
1802 :     int32_t min_dy;
1803 :     int32_t max_dy;
1804 :    
1805 :     VECTOR newMV;
1806 :     VECTOR backupMV;
1807 :    
1808 :     VECTOR pmv[4];
1809 :     int32_t psad[8];
1810 :    
1811 :     static MACROBLOCK * oldMBs = NULL;
1812 : chl 172 // const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
1813 : suxen_drol 136 const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1814 : chl 96 MACROBLOCK * oldMB = NULL;
1815 :    
1816 :     static int32_t thresh2;
1817 :     int32_t bPredEq;
1818 :     int32_t iMinSAD,iSAD=9999;
1819 :    
1820 : chl 181 MainSearch16FuncPtr MainSearchPtr;
1821 : chl 96
1822 :     if (oldMBs == NULL)
1823 : chl 141 { oldMBs = (MACROBLOCK*) calloc(iWcount*iHcount,sizeof(MACROBLOCK));
1824 : chl 140 // fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
1825 : chl 96 }
1826 :     oldMB = oldMBs + x + y * iWcount;
1827 :    
1828 :     /* Get maximum range */
1829 :     get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1830 :     x, y, 16, iWidth, iHeight, iFcode);
1831 :    
1832 :     if (!(MotionFlags & PMV_HALFPEL16 ))
1833 :     { min_dx = EVEN(min_dx);
1834 :     max_dx = EVEN(max_dx);
1835 :     min_dy = EVEN(min_dy);
1836 :     max_dy = EVEN(max_dy);
1837 :     } /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1838 :    
1839 :     bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1840 :    
1841 :     /* Step 4: Calculate SAD around the Median prediction.
1842 :     MinSAD=SAD
1843 :     If Motion Vector equal to Previous frame motion vector
1844 :     and MinSAD<PrevFrmSAD goto Step 10.
1845 :     If SAD<=256 goto Step 10.
1846 :     */
1847 :    
1848 :     // Prepare for main loop
1849 :    
1850 :     *currMV=pmv[0]; /* current best := median prediction */
1851 :     if (!(MotionFlags & PMV_HALFPEL16))
1852 :     {
1853 :     currMV->x = EVEN(currMV->x);
1854 :     currMV->y = EVEN(currMV->y);
1855 :     }
1856 :    
1857 :     if (currMV->x > max_dx)
1858 :     currMV->x=max_dx;
1859 :     if (currMV->x < min_dx)
1860 :     currMV->x=min_dx;
1861 :     if (currMV->y > max_dy)
1862 :     currMV->y=max_dy;
1863 :     if (currMV->y < min_dy)
1864 :     currMV->y=min_dy;
1865 :    
1866 :     /***************** This is predictor SET A: only median prediction ******************/
1867 :    
1868 :     iMinSAD = sad16( cur,
1869 :     get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
1870 :     iEdgedWidth, MV_MAX_ERROR);
1871 : chl 141 iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);
1872 : chl 96
1873 :     // thresh1 is fixed to 256
1874 : chl 141 if ( (iMinSAD < 256 ) || ( (MVequal(*currMV, prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
1875 : chl 96 {
1876 :     if (MotionFlags & PMV_QUICKSTOP16)
1877 :     goto EPZS16_Terminate_without_Refine;
1878 :     if (MotionFlags & PMV_EARLYSTOP16)
1879 :     goto EPZS16_Terminate_with_Refine;
1880 :     }
1881 :    
1882 :     /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1883 :    
1884 :     // previous frame MV
1885 : chl 141 CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1886 : chl 96
1887 :     // set threshhold based on Min of Prediction and SAD of collocated block
1888 :     // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
1889 :    
1890 :     if ((x==0) && (y==0) )
1891 :     {
1892 :     thresh2 = 512;
1893 :     }
1894 :     else
1895 :     {
1896 :     /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128; [Tourapis, 2002] */
1897 :    
1898 :     thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
1899 :     }
1900 :    
1901 :     // MV=(0,0) is often a good choice
1902 :    
1903 :     CHECK_MV16_ZERO;
1904 :    
1905 :    
1906 :     // left neighbour, if allowed
1907 :     if (x != 0)
1908 :     {
1909 :     if (!(MotionFlags & PMV_HALFPEL16 ))
1910 :     { pmv[1].x = EVEN(pmv[1].x);
1911 :     pmv[1].y = EVEN(pmv[1].y);
1912 :     }
1913 :     CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1914 :     }
1915 :    
1916 :     // top neighbour, if allowed
1917 :     if (y != 0)
1918 :     {
1919 :     if (!(MotionFlags & PMV_HALFPEL16 ))
1920 :     { pmv[2].x = EVEN(pmv[2].x);
1921 :     pmv[2].y = EVEN(pmv[2].y);
1922 :     }
1923 :     CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1924 :    
1925 :     // top right neighbour, if allowed
1926 : chenm001 132 if ((uint32_t)x != (iWcount-1))
1927 : chl 96 {
1928 :     if (!(MotionFlags & PMV_HALFPEL16 ))
1929 :     { pmv[3].x = EVEN(pmv[3].x);
1930 :     pmv[3].y = EVEN(pmv[3].y);
1931 :     }
1932 :     CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
1933 :     }
1934 :     }
1935 :    
1936 :     /* Terminate if MinSAD <= T_2
1937 :     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1938 :     */
1939 :    
1940 :     if ( (iMinSAD <= thresh2)
1941 : chl 141 || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )
1942 : chl 96 {
1943 :     if (MotionFlags & PMV_QUICKSTOP16)
1944 :     goto EPZS16_Terminate_without_Refine;
1945 :     if (MotionFlags & PMV_EARLYSTOP16)
1946 :     goto EPZS16_Terminate_with_Refine;
1947 :     }
1948 :    
1949 :     /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
1950 :    
1951 : chl 141 backupMV = prevMB->mvs[0]; // collocated MV
1952 :     backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x ); // acceleration X
1953 :     backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y ); // acceleration Y
1954 : chl 96
1955 : chl 141 CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);
1956 : chl 96
1957 :     // left neighbour
1958 :     if (x != 0)
1959 : chl 141 CHECK_MV16_CANDIDATE((prevMB-1)->mvs[0].x,(prevMB-1)->mvs[0].y);
1960 : chl 96
1961 :     // top neighbour
1962 :     if (y != 0)
1963 : chl 141 CHECK_MV16_CANDIDATE((prevMB-iWcount)->mvs[0].x,(prevMB-iWcount)->mvs[0].y);
1964 : chl 96
1965 :     // right neighbour, if allowed (this value is not written yet, so take it from pMB->mvs
1966 :    
1967 : chenm001 132 if ((uint32_t)x != iWcount-1)
1968 : chl 141 CHECK_MV16_CANDIDATE((prevMB+1)->mvs[0].x,(prevMB+1)->mvs[0].y);
1969 : chl 96
1970 :     // bottom neighbour, dito
1971 : chenm001 132 if ((uint32_t)y != iHcount-1)
1972 : chl 141 CHECK_MV16_CANDIDATE((prevMB+iWcount)->mvs[0].x,(prevMB+iWcount)->mvs[0].y);
1973 : chl 96
1974 :     /* Terminate if MinSAD <= T_3 (here T_3 = T_2) */
1975 :     if (iMinSAD <= thresh2)
1976 :     {
1977 :     if (MotionFlags & PMV_QUICKSTOP16)
1978 :     goto EPZS16_Terminate_without_Refine;
1979 :     if (MotionFlags & PMV_EARLYSTOP16)
1980 :     goto EPZS16_Terminate_with_Refine;
1981 :     }
1982 :    
1983 :     /************ (if Diamond Search) **************/
1984 :    
1985 :     backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1986 :    
1987 : chl 184 if (MotionFlags & PMV_USESQUARES8)
1988 :     MainSearchPtr = Square16_MainSearch;
1989 :     else
1990 :    
1991 :     if (MotionFlags & PMV_ADVANCEDDIAMOND8)
1992 :     MainSearchPtr = AdvDiamond16_MainSearch;
1993 :     else
1994 :     MainSearchPtr = Diamond16_MainSearch;
1995 :    
1996 : chl 96 /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1997 :    
1998 : chl 181 iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1999 : chl 96 x, y,
2000 :     currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2001 :     2, iFcode, iQuant, 0);
2002 :    
2003 :     if (iSAD < iMinSAD)
2004 :     {
2005 :     *currMV = newMV;
2006 :     iMinSAD = iSAD;
2007 :     }
2008 :    
2009 :    
2010 :     if (MotionFlags & PMV_EXTSEARCH16)
2011 :     {
2012 :     /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2013 :    
2014 :     if (!(MVequal(pmv[0],backupMV)) )
2015 :     {
2016 : chl 181 iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
2017 : chl 96 x, y,
2018 :     pmv[0].x, pmv[0].y, iMinSAD, &newMV,
2019 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2020 :     }
2021 :    
2022 :     if (iSAD < iMinSAD)
2023 :     {
2024 :     *currMV = newMV;
2025 :     iMinSAD = iSAD;
2026 :     }
2027 :    
2028 :     if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
2029 :     {
2030 : chl 181 iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
2031 : chl 96 x, y,
2032 :     0, 0, iMinSAD, &newMV,
2033 : chl 141 pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2034 : chl 96
2035 :     if (iSAD < iMinSAD)
2036 :     {
2037 :     *currMV = newMV;
2038 :     iMinSAD = iSAD;
2039 :     }
2040 :     }
2041 :     }
2042 :    
2043 :     /*************** Choose best MV found **************/
2044 :    
2045 :     EPZS16_Terminate_with_Refine:
2046 :     if (MotionFlags & PMV_HALFPELREFINE16) // perform final half-pel step
2047 :     iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
2048 :     x, y,
2049 :     currMV, iMinSAD,
2050 :     pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
2051 :    
2052 :     EPZS16_Terminate_without_Refine:
2053 :    
2054 : chl 141 *oldMB = *prevMB;
2055 : chl 96
2056 :     currPMV->x = currMV->x - pmv[0].x;
2057 :     currPMV->y = currMV->y - pmv[0].y;
2058 :     return iMinSAD;
2059 :     }
2060 :    
2061 :    
2062 :     int32_t EPZSSearch8(
2063 :     const uint8_t * const pRef,
2064 :     const uint8_t * const pRefH,
2065 :     const uint8_t * const pRefV,
2066 :     const uint8_t * const pRefHV,
2067 :     const IMAGE * const pCur,
2068 :     const int x, const int y,
2069 :     const int start_x, const int start_y,
2070 :     const uint32_t MotionFlags,
2071 : suxen_drol 136 const uint32_t iQuant,
2072 :     const uint32_t iFcode,
2073 : chl 96 const MBParam * const pParam,
2074 : suxen_drol 136 const MACROBLOCK * const pMBs,
2075 :     const MACROBLOCK * const prevMBs,
2076 : chl 96 VECTOR * const currMV,
2077 :     VECTOR * const currPMV)
2078 :     {
2079 : chl 141 /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
2080 :    
2081 :     const uint32_t iWcount = pParam->mb_width;
2082 : chl 96 const int32_t iWidth = pParam->width;
2083 :     const int32_t iHeight = pParam->height;
2084 :     const int32_t iEdgedWidth = pParam->edged_width;
2085 :    
2086 :     const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;
2087 :    
2088 :     int32_t iDiamondSize=1;
2089 :    
2090 :     int32_t min_dx;
2091 :     int32_t max_dx;
2092 :     int32_t min_dy;
2093 :     int32_t max_dy;
2094 :    
2095 :     VECTOR newMV;
2096 :     VECTOR backupMV;
2097 :    
2098 :     VECTOR pmv[4];
2099 :     int32_t psad[8];
2100 :    
2101 :     const int32_t iSubBlock = ((y&1)<<1) + (x&1);
2102 :    
2103 : chl 172 // const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2104 : suxen_drol 136 const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
2105 : chl 96
2106 :     int32_t bPredEq;
2107 :     int32_t iMinSAD,iSAD=9999;
2108 :    
2109 : chl 181 MainSearch8FuncPtr MainSearchPtr;
2110 : chl 96
2111 :     /* Get maximum range */
2112 :     get_range(&min_dx, &max_dx, &min_dy, &max_dy,
2113 :     x, y, 8, iWidth, iHeight, iFcode);
2114 :    
2115 :     /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2116 :    
2117 :     if (!(MotionFlags & PMV_HALFPEL8 ))
2118 :     { min_dx = EVEN(min_dx);
2119 :     max_dx = EVEN(max_dx);
2120 :     min_dy = EVEN(min_dy);
2121 :     max_dy = EVEN(max_dy);
2122 :     } /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2123 :    
2124 :     bPredEq = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);
2125 :    
2126 :    
2127 :     /* Step 4: Calculate SAD around the Median prediction.
2128 :     MinSAD=SAD
2129 :     If Motion Vector equal to Previous frame motion vector
2130 :     and MinSAD<PrevFrmSAD goto Step 10.
2131 :     If SAD<=256 goto Step 10.
2132 :     */
2133 :    
2134 :     // Prepare for main loop
2135 :    
2136 :    
2137 :     if (!(MotionFlags & PMV_HALFPEL8))
2138 :     {
2139 :     currMV->x = EVEN(currMV->x);
2140 :     currMV->y = EVEN(currMV->y);
2141 :     }
2142 :    
2143 :     if (currMV->x > max_dx)
2144 :     currMV->x=max_dx;
2145 :     if (currMV->x < min_dx)
2146 :     currMV->x=min_dx;
2147 :     if (currMV->y > max_dy)
2148 :     currMV->y=max_dy;
2149 :     if (currMV->y < min_dy)
2150 :     currMV->y=min_dy;
2151 :    
2152 :     /***************** This is predictor SET A: only median prediction ******************/
2153 :    
2154 :    
2155 :     iMinSAD = sad8( cur,
2156 :     get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
2157 :     iEdgedWidth);
2158 : chl 141 iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);
2159 : chl 96
2160 :    
2161 :     // thresh1 is fixed to 256
2162 :     if (iMinSAD < 256/4 )
2163 :     {
2164 :     if (MotionFlags & PMV_QUICKSTOP8)
2165 :     goto EPZS8_Terminate_without_Refine;
2166 :     if (MotionFlags & PMV_EARLYSTOP8)
2167 :     goto EPZS8_Terminate_with_Refine;
2168 :     }
2169 :    
2170 :     /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2171 :    
2172 :    
2173 :     // MV=(0,0) is often a good choice
2174 :     CHECK_MV8_ZERO;
2175 :    
2176 : chl 141 // previous frame MV
2177 :     CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
2178 :    
2179 :     // left neighbour, if allowed
2180 :     if (psad[1] != MV_MAX_ERROR)
2181 :     {
2182 :     if (!(MotionFlags & PMV_HALFPEL8 ))
2183 :     { pmv[1].x = EVEN(pmv[1].x);
2184 :     pmv[1].y = EVEN(pmv[1].y);
2185 :     }
2186 :     CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
2187 :     }
2188 :    
2189 :     // top neighbour, if allowed
2190 :     if (psad[2] != MV_MAX_ERROR)
2191 :     {
2192 :     if (!(MotionFlags & PMV_HALFPEL8 ))
2193 :     { pmv[2].x = EVEN(pmv[2].x);
2194 :     pmv[2].y = EVEN(pmv[2].y);
2195 :     }
2196 :     CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
2197 :    
2198 :     // top right neighbour, if allowed
2199 :     if (psad[3] != MV_MAX_ERROR)
2200 :     {
2201 :     if (!(MotionFlags & PMV_HALFPEL8 ))
2202 :     { pmv[3].x = EVEN(pmv[3].x);
2203 :     pmv[3].y = EVEN(pmv[3].y);
2204 :     }
2205 :     CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);
2206 :     }
2207 :     }
2208 :    
2209 :     /* // this bias is zero anyway, at the moment!
2210 :    
2211 :     if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
2212 :     iMinSAD -= MV8_00_BIAS;
2213 :    
2214 :     */
2215 :    
2216 : chl 96 /* Terminate if MinSAD <= T_2
2217 :     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
2218 :     */
2219 :    
2220 :     if (iMinSAD < 512/4) /* T_2 == 512/4 hardcoded */
2221 :     {
2222 :     if (MotionFlags & PMV_QUICKSTOP8)
2223 :     goto EPZS8_Terminate_without_Refine;
2224 :     if (MotionFlags & PMV_EARLYSTOP8)
2225 :     goto EPZS8_Terminate_with_Refine;
2226 :     }
2227 :    
2228 : chl 141 /************ (Diamond Search) **************/
2229 : chl 96
2230 :     backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2231 :    
2232 :     if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2233 :     iDiamondSize *= 2;
2234 :    
2235 : chl 141 /* default: use best prediction as starting point for one call of EPZS_MainSearch */
2236 : chl 96
2237 : chl 184 // there is no EPZS^2 for inter4v at the moment
2238 : chl 141
2239 : chl 181 // if (MotionFlags & PMV_USESQUARES8)
2240 :     // MainSearchPtr = Square8_MainSearch;
2241 :     // else
2242 :    
2243 :     if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2244 :     MainSearchPtr = AdvDiamond8_MainSearch;
2245 :     else
2246 :     MainSearchPtr = Diamond8_MainSearch;
2247 :    
2248 :     iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
2249 : chl 96 x, y,
2250 :     currMV->x, currMV->y, iMinSAD, &newMV,
2251 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2252 : chl 141 iDiamondSize, iFcode, iQuant, 0);
2253 : chl 96
2254 : chl 141
2255 : chl 96 if (iSAD < iMinSAD)
2256 :     {
2257 :     *currMV = newMV;
2258 :     iMinSAD = iSAD;
2259 :     }
2260 :    
2261 :     if (MotionFlags & PMV_EXTSEARCH8)
2262 :     {
2263 :     /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2264 :    
2265 :     if (!(MVequal(pmv[0],backupMV)) )
2266 :     {
2267 : chl 181 iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
2268 : chl 96 x, y,
2269 :     pmv[0].x, pmv[0].y, iMinSAD, &newMV,
2270 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
2271 :    
2272 :     if (iSAD < iMinSAD)
2273 :     {
2274 :     *currMV = newMV;
2275 :     iMinSAD = iSAD;
2276 :     }
2277 :     }
2278 :    
2279 :     if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
2280 :     {
2281 : chl 181 iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
2282 : chl 96 x, y,
2283 :     0, 0, iMinSAD, &newMV,
2284 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
2285 :    
2286 :     if (iSAD < iMinSAD)
2287 :     {
2288 :     *currMV = newMV;
2289 :     iMinSAD = iSAD;
2290 :     }
2291 :     }
2292 :     }
2293 :    
2294 :     /*************** Choose best MV found **************/
2295 :    
2296 :     EPZS8_Terminate_with_Refine:
2297 :     if (MotionFlags & PMV_HALFPELREFINE8) // perform final half-pel step
2298 :     iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
2299 :     x, y,
2300 :     currMV, iMinSAD,
2301 :     pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
2302 :    
2303 :     EPZS8_Terminate_without_Refine:
2304 :    
2305 :     currPMV->x = currMV->x - pmv[0].x;
2306 :     currPMV->y = currMV->y - pmv[0].y;
2307 :     return iMinSAD;
2308 :     }
2309 :    
2310 : suxen_drol 118
2311 :    
2312 :    
2313 :    
2314 :     /* ***********************************************************
2315 :     bvop motion estimation
2316 :     // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)
2317 :     ***************************************************************/
2318 :    
2319 : suxen_drol 152
2320 : suxen_drol 118 void MotionEstimationBVOP(
2321 :     MBParam * const pParam,
2322 :     FRAMEINFO * const frame,
2323 :    
2324 :     // forward (past) reference
2325 :     const MACROBLOCK * const f_mbs,
2326 :     const IMAGE * const f_ref,
2327 :     const IMAGE * const f_refH,
2328 :     const IMAGE * const f_refV,
2329 :     const IMAGE * const f_refHV,
2330 :     // backward (future) reference
2331 :     const MACROBLOCK * const b_mbs,
2332 :     const IMAGE * const b_ref,
2333 :     const IMAGE * const b_refH,
2334 :     const IMAGE * const b_refV,
2335 :     const IMAGE * const b_refHV)
2336 :     {
2337 :     const uint32_t mb_width = pParam->mb_width;
2338 :     const uint32_t mb_height = pParam->mb_height;
2339 :     const int32_t edged_width = pParam->edged_width;
2340 :    
2341 : suxen_drol 152 uint32_t i,j;
2342 : suxen_drol 118
2343 :     int32_t f_sad16;
2344 :     int32_t b_sad16;
2345 :     int32_t i_sad16;
2346 :     int32_t d_sad16;
2347 :     int32_t best_sad;
2348 :    
2349 :     VECTOR pmv_dontcare;
2350 :    
2351 :     // note: i==horizontal, j==vertical
2352 :     for (j = 0; j < mb_height; j++)
2353 :     {
2354 :     for (i = 0; i < mb_width; i++)
2355 :     {
2356 :     MACROBLOCK *mb = &frame->mbs[i + j*mb_width];
2357 :     const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];
2358 :     const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];
2359 :    
2360 :     if (b_mb->mode == MODE_INTER
2361 :     && b_mb->cbp == 0
2362 :     && b_mb->mvs[0].x == 0
2363 :     && b_mb->mvs[0].y == 0)
2364 :     {
2365 : suxen_drol 152 mb->mode = MODE_NOT_CODED;
2366 : suxen_drol 118 mb->mvs[0].x = 0;
2367 :     mb->mvs[0].y = 0;
2368 :     mb->b_mvs[0].x = 0;
2369 :     mb->b_mvs[0].y = 0;
2370 :     continue;
2371 :     }
2372 :    
2373 :    
2374 :     // forward search
2375 :     f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2376 :     &frame->image,
2377 :     i, j,
2378 :     frame->motion_flags, frame->quant, frame->fcode,
2379 :     pParam,
2380 : suxen_drol 152 f_mbs, f_mbs /* todo */,
2381 : suxen_drol 118 &mb->mvs[0], &pmv_dontcare); // ignore pmv
2382 :    
2383 :     // backward search
2384 :     b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2385 :     &frame->image,
2386 :     i, j,
2387 :     frame->motion_flags, frame->quant, frame->bcode,
2388 :     pParam,
2389 : suxen_drol 152 b_mbs, b_mbs, /* todo */
2390 : suxen_drol 118 &mb->b_mvs[0], &pmv_dontcare); // ignore pmv
2391 :    
2392 :     // interpolate search (simple, but effective)
2393 :     i_sad16 = sad16bi_c(
2394 :     frame->image.y + i*16 + j*16*edged_width,
2395 :     get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2396 :     i, j, 16, mb->mvs[0].x, mb->mvs[0].y, edged_width),
2397 :     get_ref(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2398 :     i, j, 16, mb->b_mvs[0].x, mb->b_mvs[0].x, edged_width),
2399 :     edged_width);
2400 :    
2401 :     // TODO: direct search
2402 :     // predictor + range of [-32,32]
2403 :     d_sad16 = 65535;
2404 :    
2405 :    
2406 :     if (f_sad16 < b_sad16)
2407 :     {
2408 :     best_sad = f_sad16;
2409 : suxen_drol 152 mb->mode = MODE_FORWARD;
2410 : suxen_drol 118 }
2411 :     else
2412 :     {
2413 :     best_sad = b_sad16;
2414 : suxen_drol 152 mb->mode = MODE_BACKWARD;
2415 : suxen_drol 118 }
2416 :    
2417 :     if (i_sad16 < best_sad)
2418 :     {
2419 :     best_sad = i_sad16;
2420 : suxen_drol 152 mb->mode = MODE_INTERPOLATE;
2421 : suxen_drol 118 }
2422 :    
2423 :     if (d_sad16 < best_sad)
2424 :     {
2425 :     best_sad = d_sad16;
2426 : suxen_drol 152 mb->mode = MODE_DIRECT;
2427 : suxen_drol 118 }
2428 :    
2429 :     }
2430 :     }
2431 :     }

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.4