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

Annotation of /trunk/xvidcore/src/motion/motion_est.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 174 - (view) (download)

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 174 #define NEIGH_MOVE_THRESH 8
58 :     // 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 :     const uint32_t iLimit)
275 : Isibaar 3
276 :     {
277 : edgomez 78 const uint32_t iWcount = pParam->mb_width;
278 :     const uint32_t iHcount = pParam->mb_height;
279 : chl 172 MACROBLOCK * const pMBs = current->mbs;
280 :     MACROBLOCK * const prevMBs = reference->mbs; // previous frame
281 : suxen_drol 136
282 : chl 172 const IMAGE * const pCurrent = &current->image;
283 :     const IMAGE * const pRef = &reference->image;
284 : suxen_drol 136
285 : chl 172 const VECTOR zeroMV = {0,0};
286 : Isibaar 3
287 : chl 172 int32_t x, y;
288 :     int32_t iIntra = 0;
289 :     VECTOR pmv;
290 :    
291 : canard 117 if (sadInit)
292 : canard 115 (*sadInit)();
293 : suxen_drol 136
294 : chl 172 for (y = 0; y < iHcount; y++)
295 :     for (x = 0; x < iWcount; x++)
296 : Isibaar 3 {
297 : chl 172 MACROBLOCK* const pMB = &pMBs[x + y * iWcount];
298 : Isibaar 3
299 : chl 172 pMB->sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
300 :     x, y, current->motion_flags, current->quant, current->fcode,
301 :     pParam, pMBs, prevMBs, &pMB->mv16, &pMB->pmvs[0]);
302 :     }
303 : Isibaar 3
304 : chl 172 for (y = 0; y < iHcount; y++)
305 :     for (x = 0; x < iWcount; x++)
306 :     {
307 :     MACROBLOCK* const pMB = &pMBs[x + y * iWcount];
308 : Isibaar 3
309 : chl 172 if (0 < (pMB->sad16 - MV16_INTER_BIAS))
310 : edgomez 78 {
311 : chl 172 int32_t deviation;
312 :     deviation = dev16(pCurrent->y + x*16 + y*16*pParam->edged_width,
313 :     pParam->edged_width);
314 :    
315 :     if (deviation < (pMB->sad16 - MV16_INTER_BIAS))
316 :     {
317 :     pMB->mode = MODE_INTRA;
318 :     pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]
319 :     = pMB->mvs[2] = pMB->mvs[3] = zeroMV;
320 :     pMB->sad16 = pMB->sad8[0] = pMB->sad8[1]
321 :     = pMB->sad8[2] = pMB->sad8[3] = 0;
322 : Isibaar 3
323 : chl 172 iIntra++;
324 :     if (iIntra >= iLimit)
325 :     return 1;
326 : suxen_drol 136
327 : chl 172 continue;
328 :     }
329 : edgomez 78 }
330 : Isibaar 3
331 : chl 172 if ( (current->global_flags & XVID_INTER4V)
332 :     && (!(current->global_flags & XVID_LUMIMASKING)
333 :     || pMB->dquant == NO_CHANGE) )
334 : edgomez 78 {
335 : chl 174 int32_t neigh=0;
336 : chl 172
337 : chl 174 if (x>0)
338 :     { neigh += abs((pMB->mv16.x)-((pMB-1)->mv16.x));
339 :     neigh += abs((pMB->mv16.y)-((pMB-1)->mv16.y));
340 :     }
341 :     if (y>0)
342 :     { neigh += abs((pMB->mv16.x)-((pMB-iWcount)->mv16.x));
343 :     neigh += abs((pMB->mv16.y)-((pMB-iWcount)->mv16.y));
344 :     }
345 :     if (x<(iWcount-1))
346 :     { neigh += abs((pMB->mv16.x)-((pMB+1)->mv16.x));
347 :     neigh += abs((pMB->mv16.y)-((pMB+1)->mv16.y));
348 :     }
349 :     if (y<(iHcount-1))
350 :     { neigh += abs((pMB->mv16.x)-((pMB+iHcount)->mv16.x));
351 :     neigh += abs((pMB->mv16.y)-((pMB+iHcount)->mv16.y));
352 :     }
353 :    
354 :     if (neigh > NEIGH_MOVE_THRESH)
355 :     {
356 :     int32_t sad8 = 129; //IMV16X16 * current->quant;
357 :    
358 : chl 172 if (sad8 < pMB->sad16)
359 :     sad8 += pMB->sad8[0]
360 :     = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
361 :     2*x, 2*y, pMB->mv16.x, pMB->mv16.y,
362 : suxen_drol 136 current->motion_flags, current->quant, current->fcode,
363 :     pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]);
364 : Isibaar 3
365 : chl 172 if (sad8 < pMB->sad16)
366 :     sad8 += pMB->sad8[1]
367 :     = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
368 :     2*x+1, 2*y, pMB->mv16.x, pMB->mv16.y,
369 :     current->motion_flags, current->quant, current->fcode,
370 :     pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]);
371 : Isibaar 3
372 : chl 172 if (sad8 < pMB->sad16)
373 :     sad8 += pMB->sad8[2]
374 :     = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
375 :     2*x, 2*y+1, pMB->mv16.x, pMB->mv16.y,
376 :     current->motion_flags, current->quant, current->fcode,
377 :     pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]);
378 : Isibaar 3
379 : chl 172 if (sad8 < pMB->sad16)
380 :     sad8 += pMB->sad8[3]
381 :     = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
382 :     2*x+1, 2*y+1, pMB->mv16.x, pMB->mv16.y,
383 :     current->motion_flags, current->quant, current->fcode,
384 :     pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]);
385 : Isibaar 3
386 : edgomez 78 /* decide: MODE_INTER or MODE_INTER4V
387 : chl 172 mpeg4: if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
388 : edgomez 78 */
389 : Isibaar 3
390 : chl 172 if (sad8 < pMB->sad16)
391 : chl 167 {
392 : edgomez 78 pMB->mode = MODE_INTER4V;
393 : chl 172 pMB->sad8[0] *= 4;
394 : chl 167 pMB->sad8[1] *= 4;
395 :     pMB->sad8[2] *= 4;
396 :     pMB->sad8[3] *= 4;
397 : chl 172 continue;
398 : chl 167 }
399 : chl 174 }
400 : edgomez 78 }
401 : chl 167
402 : chl 172 pMB->mode = MODE_INTER;
403 :     pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
404 :     pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = pMB->sad16;
405 :    
406 : chl 174 pmv = get_pmv(pMBs, x, y, pParam->mb_width, 0);
407 :     // get_pmv has to be called again.
408 :     // intra-decision and inter4v change predictors
409 : chl 172
410 :     pMB->pmvs[0].x = pMB->mv16.x - pmv.x;
411 :     pMB->pmvs[0].y = pMB->mv16.y - pmv.y;
412 : Isibaar 3 }
413 : chl 174
414 : Isibaar 3 return 0;
415 :     }
416 :    
417 :     #define CHECK_MV16_ZERO {\
418 :     if ( (0 <= max_dx) && (0 >= min_dx) \
419 :     && (0 <= max_dy) && (0 >= min_dy) ) \
420 :     { \
421 :     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \
422 : chl 141 iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\
423 : Isibaar 3 if (iSAD < iMinSAD) \
424 :     { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } } \
425 :     }
426 :    
427 : chl 96 #define NOCHECK_MV16_CANDIDATE(X,Y) { \
428 :     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
429 : chl 141 iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
430 : chl 96 if (iSAD < iMinSAD) \
431 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
432 :     }
433 : Isibaar 3
434 :     #define CHECK_MV16_CANDIDATE(X,Y) { \
435 :     if ( ((X) <= max_dx) && ((X) >= min_dx) \
436 :     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
437 :     { \
438 :     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
439 : chl 141 iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
440 : Isibaar 3 if (iSAD < iMinSAD) \
441 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
442 :     }
443 :    
444 :     #define CHECK_MV16_CANDIDATE_DIR(X,Y,D) { \
445 :     if ( ((X) <= max_dx) && ((X) >= min_dx) \
446 :     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
447 :     { \
448 :     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
449 : chl 141 iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
450 : Isibaar 3 if (iSAD < iMinSAD) \
451 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
452 :     }
453 :    
454 :     #define CHECK_MV16_CANDIDATE_FOUND(X,Y,D) { \
455 :     if ( ((X) <= max_dx) && ((X) >= min_dx) \
456 :     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
457 :     { \
458 :     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
459 : chl 141 iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
460 : Isibaar 3 if (iSAD < iMinSAD) \
461 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
462 :     }
463 :    
464 :    
465 :     #define CHECK_MV8_ZERO {\
466 :     iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \
467 : chl 141 iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\
468 : Isibaar 3 if (iSAD < iMinSAD) \
469 :     { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
470 :     }
471 :    
472 : chl 96 #define NOCHECK_MV8_CANDIDATE(X,Y) \
473 :     { \
474 :     iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
475 : chl 141 iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
476 : chl 96 if (iSAD < iMinSAD) \
477 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
478 :     }
479 : Isibaar 3
480 :     #define CHECK_MV8_CANDIDATE(X,Y) { \
481 :     if ( ((X) <= max_dx) && ((X) >= min_dx) \
482 :     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
483 :     { \
484 :     iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
485 : chl 141 iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
486 : Isibaar 3 if (iSAD < iMinSAD) \
487 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
488 :     }
489 :    
490 :     #define CHECK_MV8_CANDIDATE_DIR(X,Y,D) { \
491 :     if ( ((X) <= max_dx) && ((X) >= min_dx) \
492 :     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
493 :     { \
494 :     iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
495 : chl 141 iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
496 : Isibaar 3 if (iSAD < iMinSAD) \
497 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
498 :     }
499 :    
500 :     #define CHECK_MV8_CANDIDATE_FOUND(X,Y,D) { \
501 :     if ( ((X) <= max_dx) && ((X) >= min_dx) \
502 :     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
503 :     { \
504 :     iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
505 : chl 141 iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
506 : Isibaar 3 if (iSAD < iMinSAD) \
507 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
508 :     }
509 :    
510 :     /* too slow and not fully functional at the moment */
511 :     /*
512 :     int32_t ZeroSearch16(
513 :     const uint8_t * const pRef,
514 :     const uint8_t * const pRefH,
515 :     const uint8_t * const pRefV,
516 :     const uint8_t * const pRefHV,
517 :     const IMAGE * const pCur,
518 :     const int x, const int y,
519 :     const uint32_t MotionFlags,
520 : suxen_drol 136 const uint32_t iQuant,
521 :     const uint32_t iFcode,
522 : Isibaar 3 MBParam * const pParam,
523 : suxen_drol 136 const MACROBLOCK * const pMBs,
524 :     const MACROBLOCK * const prevMBs,
525 : Isibaar 3 VECTOR * const currMV,
526 :     VECTOR * const currPMV)
527 :     {
528 :     const int32_t iEdgedWidth = pParam->edged_width;
529 :     const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
530 :     int32_t iSAD;
531 :     int32_t pred_x,pred_y;
532 :    
533 :     get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);
534 :    
535 :     iSAD = sad16( cur,
536 :     get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),
537 :     iEdgedWidth, MV_MAX_ERROR);
538 :     if (iSAD <= iQuant * 96)
539 :     iSAD -= MV16_00_BIAS;
540 :    
541 :     currMV->x = 0;
542 :     currMV->y = 0;
543 :     currPMV->x = -pred_x;
544 :     currPMV->y = -pred_y;
545 :    
546 :     return iSAD;
547 :    
548 :     }
549 :     */
550 :    
551 : chl 96 int32_t Diamond16_MainSearch(
552 : edgomez 78 const uint8_t * const pRef,
553 :     const uint8_t * const pRefH,
554 :     const uint8_t * const pRefV,
555 :     const uint8_t * const pRefHV,
556 :     const uint8_t * const cur,
557 :     const int x, const int y,
558 :     int32_t startx, int32_t starty,
559 :     int32_t iMinSAD,
560 :     VECTOR * const currMV,
561 :     const VECTOR * const pmv,
562 :     const int32_t min_dx, const int32_t max_dx,
563 :     const int32_t min_dy, const int32_t max_dy,
564 :     const int32_t iEdgedWidth,
565 :     const int32_t iDiamondSize,
566 :     const int32_t iFcode,
567 :     const int32_t iQuant,
568 :     int iFound)
569 : Isibaar 3 {
570 :     /* Do a diamond search around given starting point, return SAD of best */
571 :    
572 :     int32_t iDirection=0;
573 :     int32_t iSAD;
574 :     VECTOR backupMV;
575 :     backupMV.x = startx;
576 :     backupMV.y = starty;
577 :    
578 :     /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
579 :    
580 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
581 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
582 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
583 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
584 :    
585 :     if (iDirection)
586 :     while (!iFound)
587 :     {
588 :     iFound = 1;
589 :     backupMV=*currMV;
590 :    
591 :     if ( iDirection != 2)
592 :     CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
593 :     if ( iDirection != 1)
594 :     CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);
595 :     if ( iDirection != 4)
596 :     CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);
597 :     if ( iDirection != 3)
598 :     CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);
599 :     }
600 :     else
601 : edgomez 78 {
602 :     currMV->x = startx;
603 :     currMV->y = starty;
604 :     }
605 : Isibaar 3 return iMinSAD;
606 :     }
607 :    
608 : chl 96 int32_t Square16_MainSearch(
609 :     const uint8_t * const pRef,
610 :     const uint8_t * const pRefH,
611 :     const uint8_t * const pRefV,
612 :     const uint8_t * const pRefHV,
613 :     const uint8_t * const cur,
614 :     const int x, const int y,
615 :     int32_t startx, int32_t starty,
616 :     int32_t iMinSAD,
617 :     VECTOR * const currMV,
618 :     const VECTOR * const pmv,
619 :     const int32_t min_dx, const int32_t max_dx,
620 :     const int32_t min_dy, const int32_t max_dy,
621 :     const int32_t iEdgedWidth,
622 :     const int32_t iDiamondSize,
623 :     const int32_t iFcode,
624 :     const int32_t iQuant,
625 :     int iFound)
626 :     {
627 :     /* Do a square search around given starting point, return SAD of best */
628 :    
629 :     int32_t iDirection=0;
630 :     int32_t iSAD;
631 :     VECTOR backupMV;
632 :     backupMV.x = startx;
633 :     backupMV.y = starty;
634 :    
635 :     /* It's one search with full square pattern, and new parts for all following diamonds */
636 :    
637 :     /* new direction are extra, so 1-4 is normal diamond
638 :     537
639 :     1*2
640 :     648
641 :     */
642 :    
643 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
644 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
645 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
646 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
647 :    
648 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
649 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
650 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
651 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
652 :    
653 :    
654 :     if (iDirection)
655 :     while (!iFound)
656 :     {
657 :     iFound = 1;
658 :     backupMV=*currMV;
659 :    
660 :     switch (iDirection)
661 :     {
662 :     case 1:
663 :     CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
664 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
665 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
666 :     break;
667 :     case 2:
668 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
669 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
670 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
671 :     break;
672 :    
673 :     case 3:
674 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
675 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
676 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
677 :     break;
678 :    
679 :     case 4:
680 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
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 :     break;
684 :    
685 :     case 5:
686 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
687 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
688 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
689 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
690 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
691 :     break;
692 :    
693 :     case 6:
694 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
695 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
696 :    
697 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
698 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
699 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
700 :    
701 :     break;
702 :    
703 :     case 7:
704 :     CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
705 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
706 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
707 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
708 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
709 :     break;
710 :    
711 :     case 8:
712 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
713 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
714 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
715 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
716 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
717 :     break;
718 :     default:
719 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
720 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
721 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
722 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
723 :    
724 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
725 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
726 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
727 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
728 :     break;
729 :     }
730 :     }
731 :     else
732 :     {
733 :     currMV->x = startx;
734 :     currMV->y = starty;
735 :     }
736 :     return iMinSAD;
737 :     }
738 :    
739 :    
740 :     int32_t Full16_MainSearch(
741 :     const uint8_t * const pRef,
742 :     const uint8_t * const pRefH,
743 :     const uint8_t * const pRefV,
744 :     const uint8_t * const pRefHV,
745 :     const uint8_t * const cur,
746 :     const int x, const int y,
747 :     int32_t startx, int32_t starty,
748 :     int32_t iMinSAD,
749 :     VECTOR * const currMV,
750 :     const VECTOR * const pmv,
751 :     const int32_t min_dx, const int32_t max_dx,
752 :     const int32_t min_dy, const int32_t max_dy,
753 :     const int32_t iEdgedWidth,
754 :     const int32_t iDiamondSize,
755 :     const int32_t iFcode,
756 :     const int32_t iQuant,
757 :     int iFound)
758 :     {
759 :     int32_t iSAD;
760 :     int32_t dx,dy;
761 :     VECTOR backupMV;
762 :     backupMV.x = startx;
763 :     backupMV.y = starty;
764 :    
765 :     for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
766 :     for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
767 :     NOCHECK_MV16_CANDIDATE(dx,dy);
768 :    
769 :     return iMinSAD;
770 :     }
771 :    
772 :     int32_t Full8_MainSearch(
773 :     const uint8_t * const pRef,
774 :     const uint8_t * const pRefH,
775 :     const uint8_t * const pRefV,
776 :     const uint8_t * const pRefHV,
777 :     const uint8_t * const cur,
778 :     const int x, const int y,
779 :     int32_t startx, int32_t starty,
780 :     int32_t iMinSAD,
781 :     VECTOR * const currMV,
782 :     const VECTOR * const pmv,
783 :     const int32_t min_dx, const int32_t max_dx,
784 :     const int32_t min_dy, const int32_t max_dy,
785 :     const int32_t iEdgedWidth,
786 :     const int32_t iDiamondSize,
787 :     const int32_t iFcode,
788 :     const int32_t iQuant,
789 :     int iFound)
790 :     {
791 :     int32_t iSAD;
792 :     int32_t dx,dy;
793 :     VECTOR backupMV;
794 :     backupMV.x = startx;
795 :     backupMV.y = starty;
796 :    
797 :     for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
798 :     for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
799 :     NOCHECK_MV8_CANDIDATE(dx,dy);
800 :    
801 :     return iMinSAD;
802 :     }
803 :    
804 :    
805 :    
806 :     int32_t Halfpel16_Refine(
807 : edgomez 78 const uint8_t * const pRef,
808 :     const uint8_t * const pRefH,
809 :     const uint8_t * const pRefV,
810 :     const uint8_t * const pRefHV,
811 :     const uint8_t * const cur,
812 :     const int x, const int y,
813 :     VECTOR * const currMV,
814 :     int32_t iMinSAD,
815 :     const VECTOR * const pmv,
816 :     const int32_t min_dx, const int32_t max_dx,
817 :     const int32_t min_dy, const int32_t max_dy,
818 :     const int32_t iFcode,
819 :     const int32_t iQuant,
820 :     const int32_t iEdgedWidth)
821 : Isibaar 3 {
822 :     /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
823 :    
824 :     int32_t iSAD;
825 :     VECTOR backupMV = *currMV;
826 :    
827 :     CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y-1);
828 :     CHECK_MV16_CANDIDATE(backupMV.x ,backupMV.y-1);
829 :     CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y-1);
830 :     CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y);
831 :     CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y);
832 :     CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y+1);
833 :     CHECK_MV16_CANDIDATE(backupMV.x ,backupMV.y+1);
834 :     CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y+1);
835 :    
836 :     return iMinSAD;
837 :     }
838 :    
839 :     #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
840 :    
841 : chl 96
842 : Isibaar 3 int32_t PMVfastSearch16(
843 : chl 96 const uint8_t * const pRef,
844 :     const uint8_t * const pRefH,
845 :     const uint8_t * const pRefV,
846 :     const uint8_t * const pRefHV,
847 :     const IMAGE * const pCur,
848 :     const int x, const int y,
849 :     const uint32_t MotionFlags,
850 : suxen_drol 136 const uint32_t iQuant,
851 :     const uint32_t iFcode,
852 : chl 96 const MBParam * const pParam,
853 : suxen_drol 136 const MACROBLOCK * const pMBs,
854 :     const MACROBLOCK * const prevMBs,
855 : chl 96 VECTOR * const currMV,
856 :     VECTOR * const currPMV)
857 : Isibaar 3 {
858 : chenm001 132 const uint32_t iWcount = pParam->mb_width;
859 : Isibaar 3 const int32_t iWidth = pParam->width;
860 :     const int32_t iHeight = pParam->height;
861 :     const int32_t iEdgedWidth = pParam->edged_width;
862 :    
863 :     const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
864 :    
865 :     int32_t iDiamondSize;
866 :    
867 :     int32_t min_dx;
868 :     int32_t max_dx;
869 :     int32_t min_dy;
870 :     int32_t max_dy;
871 :    
872 :     int32_t iFound;
873 :    
874 :     VECTOR newMV;
875 :     VECTOR backupMV; /* just for PMVFAST */
876 :    
877 :     VECTOR pmv[4];
878 :     int32_t psad[4];
879 :    
880 : chl 172 // const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
881 : suxen_drol 136 const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
882 : Isibaar 3
883 :     static int32_t threshA,threshB;
884 :     int32_t bPredEq;
885 :     int32_t iMinSAD,iSAD;
886 :    
887 :     /* Get maximum range */
888 :     get_range(&min_dx, &max_dx, &min_dy, &max_dy,
889 : edgomez 78 x, y, 16, iWidth, iHeight, iFcode);
890 : Isibaar 3
891 :     /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
892 :    
893 :     if (!(MotionFlags & PMV_HALFPEL16 ))
894 :     { min_dx = EVEN(min_dx);
895 : edgomez 78 max_dx = EVEN(max_dx);
896 :     min_dy = EVEN(min_dy);
897 :     max_dy = EVEN(max_dy);
898 : Isibaar 3 } /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
899 :    
900 :    
901 :     bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
902 :    
903 :     if ((x==0) && (y==0) )
904 :     {
905 :     threshA = 512;
906 :     threshB = 1024;
907 :    
908 :     }
909 :     else
910 :     {
911 :     threshA = psad[0];
912 :     threshB = threshA+256;
913 :     if (threshA< 512) threshA = 512;
914 :     if (threshA>1024) threshA = 1024;
915 :     if (threshB>1792) threshB = 1792;
916 :     }
917 :    
918 :     iFound=0;
919 :    
920 :     /* Step 4: Calculate SAD around the Median prediction.
921 : edgomez 78 MinSAD=SAD
922 :     If Motion Vector equal to Previous frame motion vector
923 :     and MinSAD<PrevFrmSAD goto Step 10.
924 :     If SAD<=256 goto Step 10.
925 : Isibaar 3 */
926 :    
927 :     *currMV=pmv[0]; /* current best := prediction */
928 :     if (!(MotionFlags & PMV_HALFPEL16 ))
929 :     { /* This should NOT be necessary! */
930 :     currMV->x = EVEN(currMV->x);
931 :     currMV->y = EVEN(currMV->y);
932 :     }
933 :    
934 :     if (currMV->x > max_dx)
935 : edgomez 78 {
936 :     currMV->x=max_dx;
937 :     }
938 : Isibaar 3 if (currMV->x < min_dx)
939 : edgomez 78 {
940 :     currMV->x=min_dx;
941 :     }
942 : Isibaar 3 if (currMV->y > max_dy)
943 : edgomez 78 {
944 :     currMV->y=max_dy;
945 :     }
946 : Isibaar 3 if (currMV->y < min_dy)
947 : edgomez 78 {
948 :     currMV->y=min_dy;
949 :     }
950 : Isibaar 3
951 :     iMinSAD = sad16( cur,
952 : edgomez 78 get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
953 :     iEdgedWidth, MV_MAX_ERROR);
954 : chl 141 iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);
955 : Isibaar 3
956 : suxen_drol 136 if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
957 : edgomez 78 {
958 : chl 169 if (iMinSAD < 2*iQuant) // high chances for SKIP-mode
959 :     {
960 :     if (!MVzero(*currMV))
961 :     {
962 :     iMinSAD += MV16_00_BIAS;
963 :     CHECK_MV16_ZERO; // (0,0) saves space for letterboxed pictures
964 :     iMinSAD -= MV16_00_BIAS;
965 :     }
966 :     }
967 :    
968 : edgomez 78 if (MotionFlags & PMV_QUICKSTOP16)
969 : chl 96 goto PMVfast16_Terminate_without_Refine;
970 :     if (MotionFlags & PMV_EARLYSTOP16)
971 :     goto PMVfast16_Terminate_with_Refine;
972 : edgomez 78 }
973 : Isibaar 3
974 : chl 169
975 :     /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
976 :     vector of the median.
977 :     If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
978 :     */
979 :    
980 :     if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[0]) ) )
981 :     iFound=2;
982 :    
983 :     /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
984 :     Otherwise select large Diamond Search.
985 :     */
986 :    
987 :     if ( (!MVzero(pmv[0])) || (threshB<1536) || (bPredEq) )
988 :     iDiamondSize=1; // halfpel!
989 :     else
990 :     iDiamondSize=2; // halfpel!
991 :    
992 :     if (!(MotionFlags & PMV_HALFPELDIAMOND16) )
993 :     iDiamondSize*=2;
994 :    
995 : Isibaar 3 /*
996 : edgomez 78 Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
997 :     Also calculate (0,0) but do not subtract offset.
998 :     Let MinSAD be the smallest SAD up to this point.
999 : chl 140 If MV is (0,0) subtract offset.
1000 : Isibaar 3 */
1001 :    
1002 :     // (0,0) is always possible
1003 :    
1004 : chl 169 if (!MVzero(pmv[0]))
1005 :     CHECK_MV16_ZERO;
1006 : Isibaar 3
1007 :     // previous frame MV is always possible
1008 : chl 169
1009 :     if (!MVzero(prevMB->mvs[0]))
1010 :     if (!MVequal(prevMB->mvs[0],pmv[0]))
1011 :     CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1012 : Isibaar 3
1013 :     // left neighbour, if allowed
1014 : chl 169
1015 :     if (!MVzero(pmv[1]))
1016 :     if (!MVequal(pmv[1],prevMB->mvs[0]))
1017 :     if (!MVequal(pmv[1],pmv[0]))
1018 : Isibaar 3 {
1019 :     if (!(MotionFlags & PMV_HALFPEL16 ))
1020 :     { pmv[1].x = EVEN(pmv[1].x);
1021 : chl 169 pmv[1].y = EVEN(pmv[1].y);
1022 : Isibaar 3 }
1023 : chl 169
1024 : Isibaar 3 CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1025 :     }
1026 :    
1027 :     // top neighbour, if allowed
1028 : chl 169 if (!MVzero(pmv[2]))
1029 :     if (!MVequal(pmv[2],prevMB->mvs[0]))
1030 :     if (!MVequal(pmv[2],pmv[0]))
1031 :     if (!MVequal(pmv[2],pmv[1]))
1032 : Isibaar 3 {
1033 :     if (!(MotionFlags & PMV_HALFPEL16 ))
1034 :     { pmv[2].x = EVEN(pmv[2].x);
1035 : chl 169 pmv[2].y = EVEN(pmv[2].y);
1036 : Isibaar 3 }
1037 :     CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1038 :    
1039 :     // top right neighbour, if allowed
1040 : chl 169 if (!MVzero(pmv[3]))
1041 :     if (!MVequal(pmv[3],prevMB->mvs[0]))
1042 :     if (!MVequal(pmv[3],pmv[0]))
1043 :     if (!MVequal(pmv[3],pmv[1]))
1044 :     if (!MVequal(pmv[3],pmv[2]))
1045 : Isibaar 3 {
1046 :     if (!(MotionFlags & PMV_HALFPEL16 ))
1047 :     { pmv[3].x = EVEN(pmv[3].x);
1048 : chl 169 pmv[3].y = EVEN(pmv[3].y);
1049 : Isibaar 3 }
1050 :     CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
1051 :     }
1052 :     }
1053 : chl 140
1054 : chl 141 if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96)*/ )
1055 : chl 140 iMinSAD -= MV16_00_BIAS;
1056 : Isibaar 3
1057 : chl 140
1058 : Isibaar 3 /* Step 6: If MinSAD <= thresa goto Step 10.
1059 :     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
1060 :     */
1061 :    
1062 : suxen_drol 136 if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
1063 : edgomez 78 {
1064 :     if (MotionFlags & PMV_QUICKSTOP16)
1065 : chl 96 goto PMVfast16_Terminate_without_Refine;
1066 :     if (MotionFlags & PMV_EARLYSTOP16)
1067 :     goto PMVfast16_Terminate_with_Refine;
1068 : edgomez 78 }
1069 : Isibaar 3
1070 :    
1071 :     /************ (Diamond Search) **************/
1072 :     /*
1073 : edgomez 78 Step 7: Perform Diamond search, with either the small or large diamond.
1074 :     If Found=2 only examine one Diamond pattern, and afterwards goto step 10
1075 :     Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
1076 :     If center then goto step 10.
1077 :     Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
1078 :     Refine by using small diamond and goto step 10.
1079 : Isibaar 3 */
1080 :    
1081 :     backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1082 :    
1083 :     /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1084 : chl 96 iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1085 : edgomez 78 x, y,
1086 :     currMV->x, currMV->y, iMinSAD, &newMV,
1087 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
1088 : Isibaar 3
1089 :     if (iSAD < iMinSAD)
1090 :     {
1091 :     *currMV = newMV;
1092 :     iMinSAD = iSAD;
1093 :     }
1094 :    
1095 :     if (MotionFlags & PMV_EXTSEARCH16)
1096 :     {
1097 :     /* extended: search (up to) two more times: orignal prediction and (0,0) */
1098 :    
1099 :     if (!(MVequal(pmv[0],backupMV)) )
1100 : chl 96 { iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1101 : edgomez 78 x, y,
1102 :     pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1103 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
1104 : Isibaar 3
1105 : edgomez 78 if (iSAD < iMinSAD)
1106 :     {
1107 :     *currMV = newMV;
1108 :     iMinSAD = iSAD;
1109 : Isibaar 3 }
1110 : edgomez 78 }
1111 : Isibaar 3
1112 :     if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1113 : chl 96 { iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1114 : edgomez 78 x, y,
1115 :     0, 0, iMinSAD, &newMV,
1116 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
1117 : Isibaar 3
1118 : edgomez 78 if (iSAD < iMinSAD)
1119 :     {
1120 :     *currMV = newMV;
1121 :     iMinSAD = iSAD;
1122 : Isibaar 3 }
1123 : edgomez 78 }
1124 : Isibaar 3 }
1125 :    
1126 :     /*
1127 : edgomez 78 Step 10: The motion vector is chosen according to the block corresponding to MinSAD.
1128 : Isibaar 3 */
1129 :    
1130 : chl 96 PMVfast16_Terminate_with_Refine:
1131 : Isibaar 3 if (MotionFlags & PMV_HALFPELREFINE16) // perform final half-pel step
1132 : chl 96 iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1133 :     x, y,
1134 :     currMV, iMinSAD,
1135 :     pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1136 : Isibaar 3
1137 : chl 96 PMVfast16_Terminate_without_Refine:
1138 : Isibaar 3 currPMV->x = currMV->x - pmv[0].x;
1139 :     currPMV->y = currMV->y - pmv[0].y;
1140 :     return iMinSAD;
1141 :     }
1142 :    
1143 :    
1144 :    
1145 :    
1146 :    
1147 :    
1148 : chl 96 int32_t Diamond8_MainSearch(
1149 : edgomez 78 const uint8_t * const pRef,
1150 :     const uint8_t * const pRefH,
1151 :     const uint8_t * const pRefV,
1152 :     const uint8_t * const pRefHV,
1153 :     const uint8_t * const cur,
1154 :     const int x, const int y,
1155 :     int32_t startx, int32_t starty,
1156 :     int32_t iMinSAD,
1157 :     VECTOR * const currMV,
1158 :     const VECTOR * const pmv,
1159 :     const int32_t min_dx, const int32_t max_dx,
1160 :     const int32_t min_dy, const int32_t max_dy,
1161 :     const int32_t iEdgedWidth,
1162 :     const int32_t iDiamondSize,
1163 :     const int32_t iFcode,
1164 :     const int32_t iQuant,
1165 :     int iFound)
1166 : Isibaar 3 {
1167 :     /* Do a diamond search around given starting point, return SAD of best */
1168 :    
1169 :     int32_t iDirection=0;
1170 :     int32_t iSAD;
1171 :     VECTOR backupMV;
1172 :     backupMV.x = startx;
1173 :     backupMV.y = starty;
1174 :    
1175 :     /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1176 :    
1177 :     CHECK_MV8_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
1178 :     CHECK_MV8_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
1179 :     CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
1180 :     CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1181 :    
1182 :     if (iDirection)
1183 :     while (!iFound)
1184 :     {
1185 :     iFound = 1;
1186 :     backupMV=*currMV; // since iDirection!=0, this is well defined!
1187 :    
1188 :     if ( iDirection != 2)
1189 :     CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
1190 :     if ( iDirection != 1)
1191 :     CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);
1192 :     if ( iDirection != 4)
1193 :     CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);
1194 :     if ( iDirection != 3)
1195 :     CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);
1196 :     }
1197 :     else
1198 : edgomez 78 {
1199 :     currMV->x = startx;
1200 :     currMV->y = starty;
1201 :     }
1202 : Isibaar 3 return iMinSAD;
1203 :     }
1204 :    
1205 : chl 96 int32_t Halfpel8_Refine(
1206 : edgomez 78 const uint8_t * const pRef,
1207 :     const uint8_t * const pRefH,
1208 :     const uint8_t * const pRefV,
1209 :     const uint8_t * const pRefHV,
1210 :     const uint8_t * const cur,
1211 :     const int x, const int y,
1212 :     VECTOR * const currMV,
1213 :     int32_t iMinSAD,
1214 :     const VECTOR * const pmv,
1215 :     const int32_t min_dx, const int32_t max_dx,
1216 :     const int32_t min_dy, const int32_t max_dy,
1217 :     const int32_t iFcode,
1218 :     const int32_t iQuant,
1219 :     const int32_t iEdgedWidth)
1220 : Isibaar 3 {
1221 :     /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
1222 :    
1223 :     int32_t iSAD;
1224 :     VECTOR backupMV = *currMV;
1225 :    
1226 :     CHECK_MV8_CANDIDATE(backupMV.x-1,backupMV.y-1);
1227 :     CHECK_MV8_CANDIDATE(backupMV.x ,backupMV.y-1);
1228 :     CHECK_MV8_CANDIDATE(backupMV.x+1,backupMV.y-1);
1229 :     CHECK_MV8_CANDIDATE(backupMV.x-1,backupMV.y);
1230 :     CHECK_MV8_CANDIDATE(backupMV.x+1,backupMV.y);
1231 :     CHECK_MV8_CANDIDATE(backupMV.x-1,backupMV.y+1);
1232 :     CHECK_MV8_CANDIDATE(backupMV.x ,backupMV.y+1);
1233 :     CHECK_MV8_CANDIDATE(backupMV.x+1,backupMV.y+1);
1234 :    
1235 :     return iMinSAD;
1236 :     }
1237 :    
1238 :    
1239 :     #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1240 :    
1241 :     int32_t PMVfastSearch8(
1242 : chl 96 const uint8_t * const pRef,
1243 :     const uint8_t * const pRefH,
1244 :     const uint8_t * const pRefV,
1245 :     const uint8_t * const pRefHV,
1246 :     const IMAGE * const pCur,
1247 :     const int x, const int y,
1248 : suxen_drol 136 const int start_x, const int start_y,
1249 : chl 96 const uint32_t MotionFlags,
1250 : suxen_drol 136 const uint32_t iQuant,
1251 :     const uint32_t iFcode,
1252 : chl 96 const MBParam * const pParam,
1253 : suxen_drol 136 const MACROBLOCK * const pMBs,
1254 :     const MACROBLOCK * const prevMBs,
1255 : chl 96 VECTOR * const currMV,
1256 :     VECTOR * const currPMV)
1257 : Isibaar 3 {
1258 : suxen_drol 136 const uint32_t iWcount = pParam->mb_width;
1259 : Isibaar 3 const int32_t iWidth = pParam->width;
1260 :     const int32_t iHeight = pParam->height;
1261 :     const int32_t iEdgedWidth = pParam->edged_width;
1262 :    
1263 :     const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;
1264 :    
1265 :     int32_t iDiamondSize;
1266 :    
1267 :     int32_t min_dx;
1268 :     int32_t max_dx;
1269 :     int32_t min_dy;
1270 :     int32_t max_dy;
1271 :    
1272 :     VECTOR pmv[4];
1273 :     int32_t psad[4];
1274 :     VECTOR newMV;
1275 :     VECTOR backupMV;
1276 : edgomez 170 VECTOR startMV;
1277 : Isibaar 3
1278 : chl 172 // const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1279 : suxen_drol 136 const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1280 : Isibaar 3
1281 :     static int32_t threshA,threshB;
1282 :     int32_t iFound,bPredEq;
1283 :     int32_t iMinSAD,iSAD;
1284 :    
1285 : chl 169 int32_t iSubBlock = (y&1)+(y&1) + (x&1);
1286 : Isibaar 3
1287 : edgomez 170 /* Init variables */
1288 :     startMV.x = start_x;
1289 :     startMV.y = start_y;
1290 :    
1291 :     /* Get maximum range */
1292 : edgomez 78 get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1293 :     x, y, 8, iWidth, iHeight, iFcode);
1294 : Isibaar 3
1295 :     if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))
1296 :     { min_dx = EVEN(min_dx);
1297 : chl 169 max_dx = EVEN(max_dx);
1298 :     min_dy = EVEN(min_dy);
1299 :     max_dy = EVEN(max_dy);
1300 : Isibaar 3 } /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
1301 :    
1302 :    
1303 :     bPredEq = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);
1304 :    
1305 :     if ((x==0) && (y==0) )
1306 :     {
1307 :     threshA = 512/4;
1308 :     threshB = 1024/4;
1309 :    
1310 :     }
1311 :     else
1312 :     {
1313 :     threshA = psad[0]/4; /* good estimate */
1314 :     threshB = threshA+256/4;
1315 :     if (threshA< 512/4) threshA = 512/4;
1316 :     if (threshA>1024/4) threshA = 1024/4;
1317 :     if (threshB>1792/4) threshB = 1792/4;
1318 :     }
1319 :    
1320 :     iFound=0;
1321 :    
1322 :     /* Step 4: Calculate SAD around the Median prediction.
1323 : edgomez 78 MinSAD=SAD
1324 :     If Motion Vector equal to Previous frame motion vector
1325 :     and MinSAD<PrevFrmSAD goto Step 10.
1326 :     If SAD<=256 goto Step 10.
1327 : Isibaar 3 */
1328 :    
1329 :    
1330 :     // Prepare for main loop
1331 :    
1332 : chl 169 *currMV = startMV;
1333 : Isibaar 3
1334 :     iMinSAD = sad8( cur,
1335 : edgomez 78 get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
1336 :     iEdgedWidth);
1337 : chl 141 iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode, iQuant);
1338 : Isibaar 3
1339 : chl 169 if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock]))
1340 :     && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1341 : edgomez 78 {
1342 : chl 96 if (MotionFlags & PMV_QUICKSTOP16)
1343 :     goto PMVfast8_Terminate_without_Refine;
1344 :     if (MotionFlags & PMV_EARLYSTOP16)
1345 :     goto PMVfast8_Terminate_with_Refine;
1346 : edgomez 78 }
1347 : Isibaar 3
1348 : chl 169 /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1349 :     vector of the median.
1350 :     If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1351 :     */
1352 : chl 96
1353 : chl 169 if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[iSubBlock]) ) )
1354 :     iFound=2;
1355 :    
1356 :     /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1357 :     Otherwise select large Diamond Search.
1358 :     */
1359 :    
1360 :     if ( (!MVzero(pmv[0])) || (threshB<1536/4) || (bPredEq) )
1361 :     iDiamondSize=1; // 1 halfpel!
1362 :     else
1363 :     iDiamondSize=2; // 2 halfpel = 1 full pixel!
1364 :    
1365 :     if (!(MotionFlags & PMV_HALFPELDIAMOND8) )
1366 :     iDiamondSize*=2;
1367 :    
1368 :    
1369 : Isibaar 3 /*
1370 : edgomez 78 Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
1371 :     Also calculate (0,0) but do not subtract offset.
1372 :     Let MinSAD be the smallest SAD up to this point.
1373 : chl 140 If MV is (0,0) subtract offset.
1374 : Isibaar 3 */
1375 :    
1376 : chl 169 // the median prediction might be even better than mv16
1377 : Isibaar 3
1378 : chl 169 if (!MVequal(pmv[0],startMV))
1379 :     CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);
1380 :    
1381 :     // (0,0) if needed
1382 :     if (!MVzero(pmv[0]))
1383 :     if (!MVzero(startMV))
1384 : Isibaar 3 CHECK_MV8_ZERO;
1385 :    
1386 : chl 169 // previous frame MV if needed
1387 :     if (!MVzero(prevMB->mvs[iSubBlock]))
1388 :     if (!MVequal(prevMB->mvs[iSubBlock],startMV))
1389 :     if (!MVequal(prevMB->mvs[iSubBlock],pmv[0]))
1390 : chl 140 CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
1391 : chl 169
1392 :     if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1393 :     {
1394 :     if (MotionFlags & PMV_QUICKSTOP16)
1395 :     goto PMVfast8_Terminate_without_Refine;
1396 :     if (MotionFlags & PMV_EARLYSTOP16)
1397 :     goto PMVfast8_Terminate_with_Refine;
1398 :     }
1399 :    
1400 :    
1401 :     // left neighbour, if allowed and needed
1402 :     if (!MVzero(pmv[1]))
1403 :     if (!MVequal(pmv[1],startMV))
1404 :     if (!MVequal(pmv[1],prevMB->mvs[iSubBlock]))
1405 :     if (!MVequal(pmv[1],pmv[0]))
1406 : Isibaar 3 {
1407 :     if (!(MotionFlags & PMV_HALFPEL8 ))
1408 :     { pmv[1].x = EVEN(pmv[1].x);
1409 : chl 169 pmv[1].y = EVEN(pmv[1].y);
1410 : Isibaar 3 }
1411 :     CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1412 :     }
1413 :    
1414 : chl 169 // top neighbour, if allowed and needed
1415 :     if (!MVzero(pmv[2]))
1416 :     if (!MVequal(pmv[2],startMV))
1417 :     if (!MVequal(pmv[2],prevMB->mvs[iSubBlock]))
1418 :     if (!MVequal(pmv[2],pmv[0]))
1419 :     if (!MVequal(pmv[2],pmv[1]))
1420 : Isibaar 3 {
1421 :     if (!(MotionFlags & PMV_HALFPEL8 ))
1422 :     { pmv[2].x = EVEN(pmv[2].x);
1423 : chl 169 pmv[2].y = EVEN(pmv[2].y);
1424 : Isibaar 3 }
1425 :     CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1426 :    
1427 : chl 169 // top right neighbour, if allowed and needed
1428 :     if (!MVzero(pmv[3]))
1429 :     if (!MVequal(pmv[3],startMV))
1430 :     if (!MVequal(pmv[3],prevMB->mvs[iSubBlock]))
1431 :     if (!MVequal(pmv[3],pmv[0]))
1432 :     if (!MVequal(pmv[3],pmv[1]))
1433 :     if (!MVequal(pmv[3],pmv[2]))
1434 : Isibaar 3 {
1435 : edgomez 78 if (!(MotionFlags & PMV_HALFPEL8 ))
1436 :     { pmv[3].x = EVEN(pmv[3].x);
1437 : chl 169 pmv[3].y = EVEN(pmv[3].y);
1438 : edgomez 78 }
1439 : Isibaar 3 CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);
1440 :     }
1441 :     }
1442 :    
1443 : chl 141 if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1444 : chl 140 iMinSAD -= MV8_00_BIAS;
1445 :    
1446 :    
1447 : Isibaar 3 /* Step 6: If MinSAD <= thresa goto Step 10.
1448 :     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
1449 :     */
1450 :    
1451 : chl 140 if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1452 : edgomez 78 {
1453 : chl 96 if (MotionFlags & PMV_QUICKSTOP16)
1454 :     goto PMVfast8_Terminate_without_Refine;
1455 :     if (MotionFlags & PMV_EARLYSTOP16)
1456 :     goto PMVfast8_Terminate_with_Refine;
1457 : edgomez 78 }
1458 : Isibaar 3
1459 :     /************ (Diamond Search) **************/
1460 :     /*
1461 : edgomez 78 Step 7: Perform Diamond search, with either the small or large diamond.
1462 :     If Found=2 only examine one Diamond pattern, and afterwards goto step 10
1463 :     Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
1464 :     If center then goto step 10.
1465 :     Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
1466 :     Refine by using small diamond and goto step 10.
1467 : Isibaar 3 */
1468 :    
1469 :     backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1470 :    
1471 :     /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1472 : chl 96 iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1473 : edgomez 78 x, y,
1474 :     currMV->x, currMV->y, iMinSAD, &newMV,
1475 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
1476 : Isibaar 3
1477 :     if (iSAD < iMinSAD)
1478 :     {
1479 :     *currMV = newMV;
1480 :     iMinSAD = iSAD;
1481 :     }
1482 :    
1483 :     if (MotionFlags & PMV_EXTSEARCH8)
1484 :     {
1485 :     /* extended: search (up to) two more times: orignal prediction and (0,0) */
1486 :    
1487 :     if (!(MVequal(pmv[0],backupMV)) )
1488 : chl 96 { iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1489 : edgomez 78 x, y,
1490 :     pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1491 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
1492 : Isibaar 3
1493 : edgomez 78 if (iSAD < iMinSAD)
1494 :     {
1495 :     *currMV = newMV;
1496 :     iMinSAD = iSAD;
1497 : Isibaar 3 }
1498 : edgomez 78 }
1499 : Isibaar 3
1500 :     if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1501 : chl 96 { iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1502 : edgomez 78 x, y,
1503 :     0, 0, iMinSAD, &newMV,
1504 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
1505 : Isibaar 3
1506 : edgomez 78 if (iSAD < iMinSAD)
1507 :     {
1508 :     *currMV = newMV;
1509 :     iMinSAD = iSAD;
1510 : Isibaar 3 }
1511 : edgomez 78 }
1512 : Isibaar 3 }
1513 :    
1514 :     /* Step 10: The motion vector is chosen according to the block corresponding to MinSAD.
1515 : edgomez 78 By performing an optional local half-pixel search, we can refine this result even further.
1516 : Isibaar 3 */
1517 :    
1518 : chl 96 PMVfast8_Terminate_with_Refine:
1519 : Isibaar 3 if (MotionFlags & PMV_HALFPELREFINE8) // perform final half-pel step
1520 : chl 96 iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1521 : edgomez 78 x, y,
1522 :     currMV, iMinSAD,
1523 :     pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1524 : Isibaar 3
1525 :    
1526 : chl 96 PMVfast8_Terminate_without_Refine:
1527 : Isibaar 3 currPMV->x = currMV->x - pmv[0].x;
1528 :     currPMV->y = currMV->y - pmv[0].y;
1529 :    
1530 :     return iMinSAD;
1531 :     }
1532 : chl 96
1533 :     int32_t EPZSSearch16(
1534 :     const uint8_t * const pRef,
1535 :     const uint8_t * const pRefH,
1536 :     const uint8_t * const pRefV,
1537 :     const uint8_t * const pRefHV,
1538 :     const IMAGE * const pCur,
1539 :     const int x, const int y,
1540 :     const uint32_t MotionFlags,
1541 : suxen_drol 136 const uint32_t iQuant,
1542 :     const uint32_t iFcode,
1543 : chl 96 const MBParam * const pParam,
1544 : suxen_drol 136 const MACROBLOCK * const pMBs,
1545 :     const MACROBLOCK * const prevMBs,
1546 : chl 96 VECTOR * const currMV,
1547 :     VECTOR * const currPMV)
1548 :     {
1549 : chenm001 132 const uint32_t iWcount = pParam->mb_width;
1550 :     const uint32_t iHcount = pParam->mb_height;
1551 : chl 96
1552 :     const int32_t iWidth = pParam->width;
1553 :     const int32_t iHeight = pParam->height;
1554 :     const int32_t iEdgedWidth = pParam->edged_width;
1555 :    
1556 :     const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
1557 :    
1558 :     int32_t min_dx;
1559 :     int32_t max_dx;
1560 :     int32_t min_dy;
1561 :     int32_t max_dy;
1562 :    
1563 :     VECTOR newMV;
1564 :     VECTOR backupMV;
1565 :    
1566 :     VECTOR pmv[4];
1567 :     int32_t psad[8];
1568 :    
1569 :     static MACROBLOCK * oldMBs = NULL;
1570 : chl 172 // const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
1571 : suxen_drol 136 const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1572 : chl 96 MACROBLOCK * oldMB = NULL;
1573 :    
1574 :     static int32_t thresh2;
1575 :     int32_t bPredEq;
1576 :     int32_t iMinSAD,iSAD=9999;
1577 :    
1578 :     MainSearch16FuncPtr EPZSMainSearchPtr;
1579 :    
1580 :     if (oldMBs == NULL)
1581 : chl 141 { oldMBs = (MACROBLOCK*) calloc(iWcount*iHcount,sizeof(MACROBLOCK));
1582 : chl 140 // fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
1583 : chl 96 }
1584 :     oldMB = oldMBs + x + y * iWcount;
1585 :    
1586 :     /* Get maximum range */
1587 :     get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1588 :     x, y, 16, iWidth, iHeight, iFcode);
1589 :    
1590 :     if (!(MotionFlags & PMV_HALFPEL16 ))
1591 :     { min_dx = EVEN(min_dx);
1592 :     max_dx = EVEN(max_dx);
1593 :     min_dy = EVEN(min_dy);
1594 :     max_dy = EVEN(max_dy);
1595 :     } /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1596 :    
1597 :     bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1598 :    
1599 :     /* Step 4: Calculate SAD around the Median prediction.
1600 :     MinSAD=SAD
1601 :     If Motion Vector equal to Previous frame motion vector
1602 :     and MinSAD<PrevFrmSAD goto Step 10.
1603 :     If SAD<=256 goto Step 10.
1604 :     */
1605 :    
1606 :     // Prepare for main loop
1607 :    
1608 :     *currMV=pmv[0]; /* current best := median prediction */
1609 :     if (!(MotionFlags & PMV_HALFPEL16))
1610 :     {
1611 :     currMV->x = EVEN(currMV->x);
1612 :     currMV->y = EVEN(currMV->y);
1613 :     }
1614 :    
1615 :     if (currMV->x > max_dx)
1616 :     currMV->x=max_dx;
1617 :     if (currMV->x < min_dx)
1618 :     currMV->x=min_dx;
1619 :     if (currMV->y > max_dy)
1620 :     currMV->y=max_dy;
1621 :     if (currMV->y < min_dy)
1622 :     currMV->y=min_dy;
1623 :    
1624 :     /***************** This is predictor SET A: only median prediction ******************/
1625 :    
1626 :     iMinSAD = sad16( cur,
1627 :     get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
1628 :     iEdgedWidth, MV_MAX_ERROR);
1629 : chl 141 iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);
1630 : chl 96
1631 :     // thresh1 is fixed to 256
1632 : chl 141 if ( (iMinSAD < 256 ) || ( (MVequal(*currMV, prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
1633 : chl 96 {
1634 :     if (MotionFlags & PMV_QUICKSTOP16)
1635 :     goto EPZS16_Terminate_without_Refine;
1636 :     if (MotionFlags & PMV_EARLYSTOP16)
1637 :     goto EPZS16_Terminate_with_Refine;
1638 :     }
1639 :    
1640 :     /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1641 :    
1642 :     // previous frame MV
1643 : chl 141 CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1644 : chl 96
1645 :     // set threshhold based on Min of Prediction and SAD of collocated block
1646 :     // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
1647 :    
1648 :     if ((x==0) && (y==0) )
1649 :     {
1650 :     thresh2 = 512;
1651 :     }
1652 :     else
1653 :     {
1654 :     /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128; [Tourapis, 2002] */
1655 :    
1656 :     thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
1657 :     }
1658 :    
1659 :     // MV=(0,0) is often a good choice
1660 :    
1661 :     CHECK_MV16_ZERO;
1662 :    
1663 :    
1664 :     // left neighbour, if allowed
1665 :     if (x != 0)
1666 :     {
1667 :     if (!(MotionFlags & PMV_HALFPEL16 ))
1668 :     { pmv[1].x = EVEN(pmv[1].x);
1669 :     pmv[1].y = EVEN(pmv[1].y);
1670 :     }
1671 :     CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1672 :     }
1673 :    
1674 :     // top neighbour, if allowed
1675 :     if (y != 0)
1676 :     {
1677 :     if (!(MotionFlags & PMV_HALFPEL16 ))
1678 :     { pmv[2].x = EVEN(pmv[2].x);
1679 :     pmv[2].y = EVEN(pmv[2].y);
1680 :     }
1681 :     CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1682 :    
1683 :     // top right neighbour, if allowed
1684 : chenm001 132 if ((uint32_t)x != (iWcount-1))
1685 : chl 96 {
1686 :     if (!(MotionFlags & PMV_HALFPEL16 ))
1687 :     { pmv[3].x = EVEN(pmv[3].x);
1688 :     pmv[3].y = EVEN(pmv[3].y);
1689 :     }
1690 :     CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
1691 :     }
1692 :     }
1693 :    
1694 :     /* Terminate if MinSAD <= T_2
1695 :     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1696 :     */
1697 :    
1698 :     if ( (iMinSAD <= thresh2)
1699 : chl 141 || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )
1700 : chl 96 {
1701 :     if (MotionFlags & PMV_QUICKSTOP16)
1702 :     goto EPZS16_Terminate_without_Refine;
1703 :     if (MotionFlags & PMV_EARLYSTOP16)
1704 :     goto EPZS16_Terminate_with_Refine;
1705 :     }
1706 :    
1707 :     /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
1708 :    
1709 : chl 141 backupMV = prevMB->mvs[0]; // collocated MV
1710 :     backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x ); // acceleration X
1711 :     backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y ); // acceleration Y
1712 : chl 96
1713 : chl 141 CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);
1714 : chl 96
1715 :     // left neighbour
1716 :     if (x != 0)
1717 : chl 141 CHECK_MV16_CANDIDATE((prevMB-1)->mvs[0].x,(prevMB-1)->mvs[0].y);
1718 : chl 96
1719 :     // top neighbour
1720 :     if (y != 0)
1721 : chl 141 CHECK_MV16_CANDIDATE((prevMB-iWcount)->mvs[0].x,(prevMB-iWcount)->mvs[0].y);
1722 : chl 96
1723 :     // right neighbour, if allowed (this value is not written yet, so take it from pMB->mvs
1724 :    
1725 : chenm001 132 if ((uint32_t)x != iWcount-1)
1726 : chl 141 CHECK_MV16_CANDIDATE((prevMB+1)->mvs[0].x,(prevMB+1)->mvs[0].y);
1727 : chl 96
1728 :     // bottom neighbour, dito
1729 : chenm001 132 if ((uint32_t)y != iHcount-1)
1730 : chl 141 CHECK_MV16_CANDIDATE((prevMB+iWcount)->mvs[0].x,(prevMB+iWcount)->mvs[0].y);
1731 : chl 96
1732 :     /* Terminate if MinSAD <= T_3 (here T_3 = T_2) */
1733 :     if (iMinSAD <= thresh2)
1734 :     {
1735 :     if (MotionFlags & PMV_QUICKSTOP16)
1736 :     goto EPZS16_Terminate_without_Refine;
1737 :     if (MotionFlags & PMV_EARLYSTOP16)
1738 :     goto EPZS16_Terminate_with_Refine;
1739 :     }
1740 :    
1741 :     /************ (if Diamond Search) **************/
1742 :    
1743 :     backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1744 :    
1745 :     /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1746 :    
1747 :     if (MotionFlags & PMV_USESQUARES16)
1748 :     EPZSMainSearchPtr = Square16_MainSearch;
1749 :     else
1750 :     EPZSMainSearchPtr = Diamond16_MainSearch;
1751 :    
1752 :     iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1753 :     x, y,
1754 :     currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1755 :     2, iFcode, iQuant, 0);
1756 :    
1757 :     if (iSAD < iMinSAD)
1758 :     {
1759 :     *currMV = newMV;
1760 :     iMinSAD = iSAD;
1761 :     }
1762 :    
1763 :    
1764 :     if (MotionFlags & PMV_EXTSEARCH16)
1765 :     {
1766 :     /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
1767 :    
1768 :     if (!(MVequal(pmv[0],backupMV)) )
1769 :     {
1770 :     iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1771 :     x, y,
1772 :     pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1773 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
1774 :     }
1775 :    
1776 :     if (iSAD < iMinSAD)
1777 :     {
1778 :     *currMV = newMV;
1779 :     iMinSAD = iSAD;
1780 :     }
1781 :    
1782 :     if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1783 :     {
1784 :     iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1785 :     x, y,
1786 :     0, 0, iMinSAD, &newMV,
1787 : chl 141 pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
1788 : chl 96
1789 :     if (iSAD < iMinSAD)
1790 :     {
1791 :     *currMV = newMV;
1792 :     iMinSAD = iSAD;
1793 :     }
1794 :     }
1795 :     }
1796 :    
1797 :     /*************** Choose best MV found **************/
1798 :    
1799 :     EPZS16_Terminate_with_Refine:
1800 :     if (MotionFlags & PMV_HALFPELREFINE16) // perform final half-pel step
1801 :     iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1802 :     x, y,
1803 :     currMV, iMinSAD,
1804 :     pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1805 :    
1806 :     EPZS16_Terminate_without_Refine:
1807 :    
1808 : chl 141 *oldMB = *prevMB;
1809 : chl 96
1810 :     currPMV->x = currMV->x - pmv[0].x;
1811 :     currPMV->y = currMV->y - pmv[0].y;
1812 :     return iMinSAD;
1813 :     }
1814 :    
1815 :    
1816 :     int32_t EPZSSearch8(
1817 :     const uint8_t * const pRef,
1818 :     const uint8_t * const pRefH,
1819 :     const uint8_t * const pRefV,
1820 :     const uint8_t * const pRefHV,
1821 :     const IMAGE * const pCur,
1822 :     const int x, const int y,
1823 :     const int start_x, const int start_y,
1824 :     const uint32_t MotionFlags,
1825 : suxen_drol 136 const uint32_t iQuant,
1826 :     const uint32_t iFcode,
1827 : chl 96 const MBParam * const pParam,
1828 : suxen_drol 136 const MACROBLOCK * const pMBs,
1829 :     const MACROBLOCK * const prevMBs,
1830 : chl 96 VECTOR * const currMV,
1831 :     VECTOR * const currPMV)
1832 :     {
1833 : chl 141 /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
1834 :    
1835 :     const uint32_t iWcount = pParam->mb_width;
1836 : chl 96 const int32_t iWidth = pParam->width;
1837 :     const int32_t iHeight = pParam->height;
1838 :     const int32_t iEdgedWidth = pParam->edged_width;
1839 :    
1840 :     const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;
1841 :    
1842 :     int32_t iDiamondSize=1;
1843 :    
1844 :     int32_t min_dx;
1845 :     int32_t max_dx;
1846 :     int32_t min_dy;
1847 :     int32_t max_dy;
1848 :    
1849 :     VECTOR newMV;
1850 :     VECTOR backupMV;
1851 :    
1852 :     VECTOR pmv[4];
1853 :     int32_t psad[8];
1854 :    
1855 :     const int32_t iSubBlock = ((y&1)<<1) + (x&1);
1856 :    
1857 : chl 172 // const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1858 : suxen_drol 136 const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1859 : chl 96
1860 :     int32_t bPredEq;
1861 :     int32_t iMinSAD,iSAD=9999;
1862 :    
1863 :     MainSearch8FuncPtr EPZSMainSearchPtr;
1864 :    
1865 :     /* Get maximum range */
1866 :     get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1867 :     x, y, 8, iWidth, iHeight, iFcode);
1868 :    
1869 :     /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1870 :    
1871 :     if (!(MotionFlags & PMV_HALFPEL8 ))
1872 :     { min_dx = EVEN(min_dx);
1873 :     max_dx = EVEN(max_dx);
1874 :     min_dy = EVEN(min_dy);
1875 :     max_dy = EVEN(max_dy);
1876 :     } /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1877 :    
1878 :     bPredEq = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);
1879 :    
1880 :    
1881 :     /* Step 4: Calculate SAD around the Median prediction.
1882 :     MinSAD=SAD
1883 :     If Motion Vector equal to Previous frame motion vector
1884 :     and MinSAD<PrevFrmSAD goto Step 10.
1885 :     If SAD<=256 goto Step 10.
1886 :     */
1887 :    
1888 :     // Prepare for main loop
1889 :    
1890 :    
1891 :     if (!(MotionFlags & PMV_HALFPEL8))
1892 :     {
1893 :     currMV->x = EVEN(currMV->x);
1894 :     currMV->y = EVEN(currMV->y);
1895 :     }
1896 :    
1897 :     if (currMV->x > max_dx)
1898 :     currMV->x=max_dx;
1899 :     if (currMV->x < min_dx)
1900 :     currMV->x=min_dx;
1901 :     if (currMV->y > max_dy)
1902 :     currMV->y=max_dy;
1903 :     if (currMV->y < min_dy)
1904 :     currMV->y=min_dy;
1905 :    
1906 :     /***************** This is predictor SET A: only median prediction ******************/
1907 :    
1908 :    
1909 :     iMinSAD = sad8( cur,
1910 :     get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
1911 :     iEdgedWidth);
1912 : chl 141 iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);
1913 : chl 96
1914 :    
1915 :     // thresh1 is fixed to 256
1916 :     if (iMinSAD < 256/4 )
1917 :     {
1918 :     if (MotionFlags & PMV_QUICKSTOP8)
1919 :     goto EPZS8_Terminate_without_Refine;
1920 :     if (MotionFlags & PMV_EARLYSTOP8)
1921 :     goto EPZS8_Terminate_with_Refine;
1922 :     }
1923 :    
1924 :     /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1925 :    
1926 :    
1927 :     // MV=(0,0) is often a good choice
1928 :     CHECK_MV8_ZERO;
1929 :    
1930 : chl 141 // previous frame MV
1931 :     CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
1932 :    
1933 :     // left neighbour, if allowed
1934 :     if (psad[1] != MV_MAX_ERROR)
1935 :     {
1936 :     if (!(MotionFlags & PMV_HALFPEL8 ))
1937 :     { pmv[1].x = EVEN(pmv[1].x);
1938 :     pmv[1].y = EVEN(pmv[1].y);
1939 :     }
1940 :     CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1941 :     }
1942 :    
1943 :     // top neighbour, if allowed
1944 :     if (psad[2] != MV_MAX_ERROR)
1945 :     {
1946 :     if (!(MotionFlags & PMV_HALFPEL8 ))
1947 :     { pmv[2].x = EVEN(pmv[2].x);
1948 :     pmv[2].y = EVEN(pmv[2].y);
1949 :     }
1950 :     CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1951 :    
1952 :     // top right neighbour, if allowed
1953 :     if (psad[3] != MV_MAX_ERROR)
1954 :     {
1955 :     if (!(MotionFlags & PMV_HALFPEL8 ))
1956 :     { pmv[3].x = EVEN(pmv[3].x);
1957 :     pmv[3].y = EVEN(pmv[3].y);
1958 :     }
1959 :     CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);
1960 :     }
1961 :     }
1962 :    
1963 :     /* // this bias is zero anyway, at the moment!
1964 :    
1965 :     if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
1966 :     iMinSAD -= MV8_00_BIAS;
1967 :    
1968 :     */
1969 :    
1970 : chl 96 /* Terminate if MinSAD <= T_2
1971 :     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1972 :     */
1973 :    
1974 :     if (iMinSAD < 512/4) /* T_2 == 512/4 hardcoded */
1975 :     {
1976 :     if (MotionFlags & PMV_QUICKSTOP8)
1977 :     goto EPZS8_Terminate_without_Refine;
1978 :     if (MotionFlags & PMV_EARLYSTOP8)
1979 :     goto EPZS8_Terminate_with_Refine;
1980 :     }
1981 :    
1982 : chl 141 /************ (Diamond Search) **************/
1983 : chl 96
1984 :     backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1985 :    
1986 :     if (!(MotionFlags & PMV_HALFPELDIAMOND8))
1987 :     iDiamondSize *= 2;
1988 :    
1989 : chl 141 /* default: use best prediction as starting point for one call of EPZS_MainSearch */
1990 : chl 96
1991 : chl 141 /* // there is no EPZS^2 for inter4v at the moment
1992 :    
1993 :     if (MotionFlags & PMV_USESQUARES8)
1994 :     EPZSMainSearchPtr = Square8_MainSearch;
1995 :     else
1996 :     */
1997 :    
1998 :     EPZSMainSearchPtr = Diamond8_MainSearch;
1999 : chl 96
2000 :     iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
2001 :     x, y,
2002 :     currMV->x, currMV->y, iMinSAD, &newMV,
2003 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2004 : chl 141 iDiamondSize, iFcode, iQuant, 0);
2005 : chl 96
2006 : chl 141
2007 : chl 96 if (iSAD < iMinSAD)
2008 :     {
2009 :     *currMV = newMV;
2010 :     iMinSAD = iSAD;
2011 :     }
2012 :    
2013 :     if (MotionFlags & PMV_EXTSEARCH8)
2014 :     {
2015 :     /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2016 :    
2017 :     if (!(MVequal(pmv[0],backupMV)) )
2018 :     {
2019 :     iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
2020 :     x, y,
2021 :     pmv[0].x, pmv[0].y, iMinSAD, &newMV,
2022 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
2023 :    
2024 :     if (iSAD < iMinSAD)
2025 :     {
2026 :     *currMV = newMV;
2027 :     iMinSAD = iSAD;
2028 :     }
2029 :     }
2030 :    
2031 :     if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
2032 :     {
2033 :     iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
2034 :     x, y,
2035 :     0, 0, iMinSAD, &newMV,
2036 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
2037 :    
2038 :     if (iSAD < iMinSAD)
2039 :     {
2040 :     *currMV = newMV;
2041 :     iMinSAD = iSAD;
2042 :     }
2043 :     }
2044 :     }
2045 :    
2046 :     /*************** Choose best MV found **************/
2047 :    
2048 :     EPZS8_Terminate_with_Refine:
2049 :     if (MotionFlags & PMV_HALFPELREFINE8) // perform final half-pel step
2050 :     iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
2051 :     x, y,
2052 :     currMV, iMinSAD,
2053 :     pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
2054 :    
2055 :     EPZS8_Terminate_without_Refine:
2056 :    
2057 :     currPMV->x = currMV->x - pmv[0].x;
2058 :     currPMV->y = currMV->y - pmv[0].y;
2059 :     return iMinSAD;
2060 :     }
2061 :    
2062 : suxen_drol 118
2063 :    
2064 :    
2065 :    
2066 :     /* ***********************************************************
2067 :     bvop motion estimation
2068 :     // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)
2069 :     ***************************************************************/
2070 :    
2071 : suxen_drol 152
2072 : suxen_drol 118 void MotionEstimationBVOP(
2073 :     MBParam * const pParam,
2074 :     FRAMEINFO * const frame,
2075 :    
2076 :     // forward (past) reference
2077 :     const MACROBLOCK * const f_mbs,
2078 :     const IMAGE * const f_ref,
2079 :     const IMAGE * const f_refH,
2080 :     const IMAGE * const f_refV,
2081 :     const IMAGE * const f_refHV,
2082 :     // backward (future) reference
2083 :     const MACROBLOCK * const b_mbs,
2084 :     const IMAGE * const b_ref,
2085 :     const IMAGE * const b_refH,
2086 :     const IMAGE * const b_refV,
2087 :     const IMAGE * const b_refHV)
2088 :     {
2089 :     const uint32_t mb_width = pParam->mb_width;
2090 :     const uint32_t mb_height = pParam->mb_height;
2091 :     const int32_t edged_width = pParam->edged_width;
2092 :    
2093 : suxen_drol 152 uint32_t i,j;
2094 : suxen_drol 118
2095 :     int32_t f_sad16;
2096 :     int32_t b_sad16;
2097 :     int32_t i_sad16;
2098 :     int32_t d_sad16;
2099 :     int32_t best_sad;
2100 :    
2101 :     VECTOR pmv_dontcare;
2102 :    
2103 :     // note: i==horizontal, j==vertical
2104 :     for (j = 0; j < mb_height; j++)
2105 :     {
2106 :     for (i = 0; i < mb_width; i++)
2107 :     {
2108 :     MACROBLOCK *mb = &frame->mbs[i + j*mb_width];
2109 :     const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];
2110 :     const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];
2111 :    
2112 :     if (b_mb->mode == MODE_INTER
2113 :     && b_mb->cbp == 0
2114 :     && b_mb->mvs[0].x == 0
2115 :     && b_mb->mvs[0].y == 0)
2116 :     {
2117 : suxen_drol 152 mb->mode = MODE_NOT_CODED;
2118 : suxen_drol 118 mb->mvs[0].x = 0;
2119 :     mb->mvs[0].y = 0;
2120 :     mb->b_mvs[0].x = 0;
2121 :     mb->b_mvs[0].y = 0;
2122 :     continue;
2123 :     }
2124 :    
2125 :    
2126 :     // forward search
2127 :     f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2128 :     &frame->image,
2129 :     i, j,
2130 :     frame->motion_flags, frame->quant, frame->fcode,
2131 :     pParam,
2132 : suxen_drol 152 f_mbs, f_mbs /* todo */,
2133 : suxen_drol 118 &mb->mvs[0], &pmv_dontcare); // ignore pmv
2134 :    
2135 :     // backward search
2136 :     b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2137 :     &frame->image,
2138 :     i, j,
2139 :     frame->motion_flags, frame->quant, frame->bcode,
2140 :     pParam,
2141 : suxen_drol 152 b_mbs, b_mbs, /* todo */
2142 : suxen_drol 118 &mb->b_mvs[0], &pmv_dontcare); // ignore pmv
2143 :    
2144 :     // interpolate search (simple, but effective)
2145 :     i_sad16 = sad16bi_c(
2146 :     frame->image.y + i*16 + j*16*edged_width,
2147 :     get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2148 :     i, j, 16, mb->mvs[0].x, mb->mvs[0].y, edged_width),
2149 :     get_ref(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2150 :     i, j, 16, mb->b_mvs[0].x, mb->b_mvs[0].x, edged_width),
2151 :     edged_width);
2152 :    
2153 :     // TODO: direct search
2154 :     // predictor + range of [-32,32]
2155 :     d_sad16 = 65535;
2156 :    
2157 :    
2158 :     if (f_sad16 < b_sad16)
2159 :     {
2160 :     best_sad = f_sad16;
2161 : suxen_drol 152 mb->mode = MODE_FORWARD;
2162 : suxen_drol 118 }
2163 :     else
2164 :     {
2165 :     best_sad = b_sad16;
2166 : suxen_drol 152 mb->mode = MODE_BACKWARD;
2167 : suxen_drol 118 }
2168 :    
2169 :     if (i_sad16 < best_sad)
2170 :     {
2171 :     best_sad = i_sad16;
2172 : suxen_drol 152 mb->mode = MODE_INTERPOLATE;
2173 : suxen_drol 118 }
2174 :    
2175 :     if (d_sad16 < best_sad)
2176 :     {
2177 :     best_sad = d_sad16;
2178 : suxen_drol 152 mb->mode = MODE_DIRECT;
2179 : suxen_drol 118 }
2180 :    
2181 :     }
2182 :     }
2183 :     }

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