[svn] / branches / dev-api-3 / xvidcore / src / motion / motion_est.c Repository:
ViewVC logotype

Annotation of /branches/dev-api-3/xvidcore/src/motion/motion_est.c

Parent Directory Parent Directory | Revision Log Revision Log


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

1 : Isibaar 3 /**************************************************************************
2 :     *
3 :     * Modifications:
4 :     *
5 : chl 96 * 02.04.2002 add EPZS(^2) as ME algorithm, use PMV_USESQUARES to choose between
6 :     * EPZS and EPZS^2
7 : Isibaar 3 * 08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop
8 :     * PMVFast_Refine to support multiple searches with different start points
9 : edgomez 78 * 07.01.2002 uv-block-based interpolation
10 : Isibaar 3 * 06.01.2002 INTER/INTRA-decision is now done before any SEARCH8 (speedup)
11 : edgomez 78 * changed INTER_BIAS to 150 (as suggested by suxen_drol)
12 :     * removed halfpel refinement step in PMVfastSearch8 + quality=5
13 :     * added new quality mode = 6 which performs halfpel refinement
14 :     * filesize difference between quality 5 and 6 is smaller than 1%
15 : Isibaar 3 * (Isibaar)
16 :     * 31.12.2001 PMVfastSearch16 and PMVfastSearch8 (gruel)
17 : edgomez 78 * 30.12.2001 get_range/MotionSearchX simplified; blue/green bug fix
18 :     * 22.12.2001 commented best_point==99 check
19 :     * 19.12.2001 modified get_range (purple bug fix)
20 : Isibaar 3 * 15.12.2001 moved pmv displacement from mbprediction
21 :     * 02.12.2001 motion estimation/compensation split (Isibaar)
22 : edgomez 78 * 16.11.2001 rewrote/tweaked search algorithms; pross@cs.rmit.edu.au
23 : Isibaar 3 * 10.11.2001 support for sad16/sad8 functions
24 :     * 28.08.2001 reactivated MODE_INTER4V for EXT_MODE
25 :     * 24.08.2001 removed MODE_INTER4V_Q, disabled MODE_INTER4V for EXT_MODE
26 : edgomez 78 * 22.08.2001 added MODE_INTER4V_Q
27 : Isibaar 3 * 20.08.2001 added pragma to get rid of internal compiler error with VC6
28 :     * idea by Cyril. Thanks.
29 :     *
30 :     * Michael Militzer <isibaar@videocoding.de>
31 :     *
32 :     **************************************************************************/
33 :    
34 :     #include <assert.h>
35 :     #include <stdio.h>
36 : chl 96 #include <stdlib.h>
37 : Isibaar 3
38 :     #include "../encoder.h"
39 :     #include "../utils/mbfunctions.h"
40 :     #include "../prediction/mbprediction.h"
41 :     #include "../global.h"
42 :     #include "../utils/timer.h"
43 :     #include "sad.h"
44 :    
45 :     // very large value
46 :     #define MV_MAX_ERROR (4096 * 256)
47 :    
48 :     // stop search if sdelta < THRESHOLD
49 :     #define MV16_THRESHOLD 192
50 :     #define MV8_THRESHOLD 56
51 :    
52 :     /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */
53 :     /* nb = vop pixels * 2^(bpp-8) */
54 :     #define MV16_00_BIAS (128+1)
55 :    
56 :     /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */
57 :     #define INTER_BIAS 512
58 :    
59 :     /* Parameters which control inter/inter4v decision */
60 :     #define IMV16X16 5
61 :    
62 :     /* vector map (vlc delta size) smoother parameters */
63 :     #define NEIGH_TEND_16X16 2
64 :     #define NEIGH_TEND_8X8 2
65 :    
66 :    
67 :     // fast ((A)/2)*2
68 :     #define EVEN(A) (((A)<0?(A)+1:(A)) & ~1)
69 :    
70 :    
71 :     #define MIN(X, Y) ((X)<(Y)?(X):(Y))
72 :     #define MAX(X, Y) ((X)>(Y)?(X):(Y))
73 : edgomez 78 #define ABS(X) (((X)>0)?(X):-(X))
74 :     #define SIGN(X) (((X)>0)?1:-1)
75 : Isibaar 3
76 : chl 96 int32_t PMVfastSearch16(
77 :     const uint8_t * const pRef,
78 :     const uint8_t * const pRefH,
79 :     const uint8_t * const pRefV,
80 :     const uint8_t * const pRefHV,
81 :     const IMAGE * const pCur,
82 :     const int x, const int y,
83 :     const uint32_t MotionFlags,
84 :     const MBParam * const pParam,
85 :     MACROBLOCK * const pMBs,
86 :     VECTOR * const currMV,
87 :     VECTOR * const currPMV);
88 : Isibaar 3
89 : chl 96 int32_t EPZSSearch16(
90 :     const uint8_t * const pRef,
91 :     const uint8_t * const pRefH,
92 :     const uint8_t * const pRefV,
93 :     const uint8_t * const pRefHV,
94 :     const IMAGE * const pCur,
95 :     const int x, const int y,
96 :     const uint32_t MotionFlags,
97 :     const MBParam * const pParam,
98 :     MACROBLOCK * const pMBs,
99 :     VECTOR * const currMV,
100 :     VECTOR * const currPMV);
101 :    
102 :    
103 : Isibaar 3 int32_t PMVfastSearch8(
104 : chl 96 const uint8_t * const pRef,
105 :     const uint8_t * const pRefH,
106 :     const uint8_t * const pRefV,
107 :     const uint8_t * const pRefHV,
108 :     const IMAGE * const pCur,
109 :     const int x, const int y,
110 :     const int start_x, int start_y,
111 :     const uint32_t MotionFlags,
112 :     const MBParam * const pParam,
113 :     MACROBLOCK * const pMBs,
114 :     VECTOR * const currMV,
115 :     VECTOR * const currPMV);
116 :    
117 :     int32_t EPZSSearch8(
118 :     const uint8_t * const pRef,
119 :     const uint8_t * const pRefH,
120 :     const uint8_t * const pRefV,
121 :     const uint8_t * const pRefHV,
122 :     const IMAGE * const pCur,
123 :     const int x, const int y,
124 :     const int start_x, int start_y,
125 :     const uint32_t MotionFlags,
126 :     const MBParam * const pParam,
127 :     MACROBLOCK * const pMBs,
128 :     VECTOR * const currMV,
129 :     VECTOR * const currPMV);
130 :    
131 :    
132 :     typedef int32_t (MainSearch16Func)(
133 : edgomez 78 const uint8_t * const pRef,
134 :     const uint8_t * const pRefH,
135 :     const uint8_t * const pRefV,
136 :     const uint8_t * const pRefHV,
137 : chl 96 const uint8_t * const cur,
138 : edgomez 78 const int x, const int y,
139 : chl 96 int32_t startx, int32_t starty,
140 :     int32_t iMinSAD,
141 : edgomez 78 VECTOR * const currMV,
142 : chl 96 const VECTOR * const pmv,
143 :     const int32_t min_dx, const int32_t max_dx,
144 :     const int32_t min_dy, const int32_t max_dy,
145 :     const int32_t iEdgedWidth,
146 :     const int32_t iDiamondSize,
147 :     const int32_t iFcode,
148 :     const int32_t iQuant,
149 :     int iFound);
150 : Isibaar 3
151 : chl 96 typedef MainSearch16Func* MainSearch16FuncPtr;
152 :    
153 :    
154 :     typedef int32_t (MainSearch8Func)(
155 : edgomez 78 const uint8_t * const pRef,
156 :     const uint8_t * const pRefH,
157 :     const uint8_t * const pRefV,
158 :     const uint8_t * const pRefHV,
159 : chl 96 const uint8_t * const cur,
160 : edgomez 78 const int x, const int y,
161 : chl 96 int32_t startx, int32_t starty,
162 :     int32_t iMinSAD,
163 : edgomez 78 VECTOR * const currMV,
164 : chl 96 const VECTOR * const pmv,
165 :     const int32_t min_dx, const int32_t max_dx,
166 :     const int32_t min_dy, const int32_t max_dy,
167 :     const int32_t iEdgedWidth,
168 :     const int32_t iDiamondSize,
169 :     const int32_t iFcode,
170 :     const int32_t iQuant,
171 :     int iFound);
172 : Isibaar 3
173 : chl 96 typedef MainSearch8Func* MainSearch8FuncPtr;
174 : Isibaar 3
175 :     // mv.length table
176 :     static const uint32_t mvtab[33] = {
177 :     1, 2, 3, 4, 6, 7, 7, 7,
178 :     9, 9, 9, 10, 10, 10, 10, 10,
179 :     10, 10, 10, 10, 10, 10, 10, 10,
180 :     10, 11, 11, 11, 11, 11, 11, 12, 12
181 :     };
182 :    
183 :    
184 :     static __inline uint32_t mv_bits(int32_t component, const uint32_t iFcode)
185 :     {
186 :     if (component == 0)
187 :     return 1;
188 :    
189 :     if (component < 0)
190 :     component = -component;
191 :    
192 :     if (iFcode == 1)
193 :     {
194 :     if (component > 32)
195 :     component = 32;
196 :    
197 :     return mvtab[component] + 1;
198 :     }
199 :    
200 :     component += (1 << (iFcode - 1)) - 1;
201 :     component >>= (iFcode - 1);
202 :    
203 :     if (component > 32)
204 :     component = 32;
205 :    
206 :     return mvtab[component] + 1 + iFcode - 1;
207 :     }
208 :    
209 :    
210 :     static __inline uint32_t calc_delta_16(const int32_t dx, const int32_t dy, const uint32_t iFcode)
211 :     {
212 :     return NEIGH_TEND_16X16 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));
213 :     }
214 :    
215 :     static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode)
216 :    
217 :     {
218 :     return NEIGH_TEND_8X8 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));
219 :     }
220 :    
221 :    
222 :    
223 :    
224 :     /* calculate the min/max range (in halfpixels)
225 :     relative to the _MACROBLOCK_ position
226 :     */
227 :    
228 :     static void __inline get_range(
229 : edgomez 78 int32_t * const min_dx, int32_t * const max_dx,
230 :     int32_t * const min_dy, int32_t * const max_dy,
231 :     const uint32_t x, const uint32_t y,
232 :     const uint32_t block_sz, // block dimension, 8 or 16
233 :     const uint32_t width, const uint32_t height,
234 :     const uint32_t fcode)
235 : Isibaar 3 {
236 : edgomez 78
237 : Isibaar 3 const int search_range = 32 << (fcode - 1);
238 : edgomez 78 const int high = search_range - 1;
239 :     const int low = -search_range;
240 : Isibaar 3
241 :     // convert full-pixel measurements to half pixel
242 :     const int hp_width = 2 * width;
243 :     const int hp_height = 2 * height;
244 :     const int hp_edge = 2 * block_sz;
245 :     const int hp_x = 2 * (x) * block_sz; // we need _right end_ of block, not x-coordinate
246 :     const int hp_y = 2 * (y) * block_sz; // same for _bottom end_
247 :    
248 : edgomez 78 *max_dx = MIN(high, hp_width - hp_x);
249 :     *max_dy = MIN(high, hp_height - hp_y);
250 :     *min_dx = MAX(low, -(hp_edge + hp_x));
251 :     *min_dy = MAX(low, -(hp_edge + hp_y));
252 :    
253 : Isibaar 3 }
254 :    
255 :    
256 : edgomez 78 /*
257 :     * getref: calculate reference image pointer
258 :     * the decision to use interpolation h/v/hv or the normal image is
259 :     * based on dx & dy.
260 :     */
261 : Isibaar 3
262 :     static __inline const uint8_t * get_ref(
263 : edgomez 78 const uint8_t * const refn,
264 :     const uint8_t * const refh,
265 :     const uint8_t * const refv,
266 :     const uint8_t * const refhv,
267 :     const uint32_t x, const uint32_t y,
268 :     const uint32_t block, // block dimension, 8 or 16
269 :     const int32_t dx, const int32_t dy,
270 :     const uint32_t stride)
271 : Isibaar 3 {
272 : edgomez 78
273 : Isibaar 3 switch ( ((dx&1)<<1) + (dy&1) ) // ((dx%2)?2:0)+((dy%2)?1:0)
274 : edgomez 78 {
275 :     case 0 : return refn + (x*block+dx/2) + (y*block+dy/2)*stride;
276 :     case 1 : return refv + (x*block+dx/2) + (y*block+(dy-1)/2)*stride;
277 :     case 2 : return refh + (x*block+(dx-1)/2) + (y*block+dy/2)*stride;
278 : Isibaar 3 default :
279 : edgomez 78 case 3 : return refhv + (x*block+(dx-1)/2) + (y*block+(dy-1)/2)*stride;
280 : Isibaar 3 }
281 : edgomez 78
282 : Isibaar 3 }
283 :    
284 :    
285 :     /* This is somehow a copy of get_ref, but with MV instead of X,Y */
286 :    
287 :     static __inline const uint8_t * get_ref_mv(
288 : edgomez 78 const uint8_t * const refn,
289 :     const uint8_t * const refh,
290 :     const uint8_t * const refv,
291 :     const uint8_t * const refhv,
292 :     const uint32_t x, const uint32_t y,
293 :     const uint32_t block, // block dimension, 8 or 16
294 :     const VECTOR* mv, // measured in half-pel!
295 :     const uint32_t stride)
296 : Isibaar 3 {
297 : edgomez 78
298 : Isibaar 3 switch ( (((mv->x)&1)<<1) + ((mv->y)&1) )
299 : edgomez 78 {
300 :     case 0 : return refn + (x*block+(mv->x)/2) + (y*block+(mv->y)/2)*stride;
301 :     case 1 : return refv + (x*block+(mv->x)/2) + (y*block+((mv->y)-1)/2)*stride;
302 :     case 2 : return refh + (x*block+((mv->x)-1)/2) + (y*block+(mv->y)/2)*stride;
303 : Isibaar 3 default :
304 : edgomez 78 case 3 : return refhv + (x*block+((mv->x)-1)/2) + (y*block+((mv->y)-1)/2)*stride;
305 : Isibaar 3 }
306 : edgomez 78
307 : Isibaar 3 }
308 :    
309 :     #ifndef SEARCH16
310 :     #define SEARCH16 PMVfastSearch16
311 : chl 96 //#define SEARCH16 FullSearch16
312 :     //#define SEARCH16 EPZSSearch16
313 : Isibaar 3 #endif
314 :    
315 :     #ifndef SEARCH8
316 :     #define SEARCH8 PMVfastSearch8
317 : chl 96 //#define SEARCH8 EPZSSearch8
318 : Isibaar 3 #endif
319 :    
320 :     bool MotionEstimation(
321 : edgomez 78 MACROBLOCK * const pMBs,
322 :     MBParam * const pParam,
323 :     const IMAGE * const pRef,
324 :     const IMAGE * const pRefH,
325 :     const IMAGE * const pRefV,
326 :     const IMAGE * const pRefHV,
327 :     IMAGE * const pCurrent,
328 :     const uint32_t iLimit)
329 : Isibaar 3
330 :     {
331 : edgomez 78 const uint32_t iWcount = pParam->mb_width;
332 :     const uint32_t iHcount = pParam->mb_height;
333 : Isibaar 3
334 :     uint32_t i, j, iIntra = 0;
335 :    
336 : edgomez 78 VECTOR mv16;
337 :     VECTOR pmv16;
338 : Isibaar 3
339 : edgomez 78 int32_t sad8 = 0;
340 :     int32_t sad16;
341 :     int32_t deviation;
342 : Isibaar 3
343 : canard 115 if (sadInit);
344 :     (*sadInit)();
345 :    
346 : Isibaar 3 // note: i==horizontal, j==vertical
347 : edgomez 78 for (i = 0; i < iHcount; i++)
348 : Isibaar 3 for (j = 0; j < iWcount; j++)
349 :     {
350 :     MACROBLOCK *pMB = &pMBs[j + i * iWcount];
351 :    
352 :     sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
353 : edgomez 78 j, i, pParam->motion_flags,
354 :     pParam, pMBs, &mv16, &pmv16);
355 : Isibaar 3 pMB->sad16=sad16;
356 :    
357 :    
358 : edgomez 78 /* decide: MODE_INTER or MODE_INTRA
359 :     if (dev_intra < sad_inter - 2 * nb) use_intra
360 :     */
361 : Isibaar 3
362 : edgomez 78 deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width);
363 : Isibaar 3
364 : edgomez 78 if (deviation < (sad16 - INTER_BIAS))
365 :     {
366 :     pMB->mode = MODE_INTRA;
367 :     pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;
368 :     pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;
369 : Isibaar 3
370 : edgomez 78 iIntra++;
371 :     if(iIntra >= iLimit)
372 :     return 1;
373 : Isibaar 3
374 : edgomez 78 continue;
375 :     }
376 : Isibaar 3
377 : edgomez 78 if (pParam->global_flags & XVID_INTER4V)
378 :     {
379 :     pMB->sad8[0] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
380 :     2 * j, 2 * i, mv16.x, mv16.y, pParam->motion_flags,
381 :     pParam, pMBs, &pMB->mvs[0], &pMB->pmvs[0]);
382 : Isibaar 3
383 : edgomez 78 pMB->sad8[1] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
384 :     2 * j + 1, 2 * i, mv16.x, mv16.y, pParam->motion_flags,
385 :     pParam, pMBs, &pMB->mvs[1], &pMB->pmvs[1]);
386 : Isibaar 3
387 : edgomez 78 pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
388 :     2 * j, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,
389 :     pParam, pMBs, &pMB->mvs[2], &pMB->pmvs[2]);
390 : Isibaar 3
391 : edgomez 78 pMB->sad8[3] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
392 :     2 * j + 1, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,
393 :     pParam, pMBs, &pMB->mvs[3], &pMB->pmvs[3]);
394 : Isibaar 3
395 : edgomez 78 sad8 = pMB->sad8[0] + pMB->sad8[1] + pMB->sad8[2] + pMB->sad8[3];
396 :     }
397 : Isibaar 3
398 :    
399 : edgomez 78 /* decide: MODE_INTER or MODE_INTER4V
400 :     mpeg4: if (sad8 < sad16 - nb/2+1) use_inter4v
401 :     */
402 : Isibaar 3
403 : edgomez 78 if (pMB->dquant == NO_CHANGE) {
404 :     if (((pParam->global_flags & XVID_INTER4V)==0) ||
405 :     (sad16 < (sad8 + (int32_t)(IMV16X16 * pParam->quant)))) {
406 : Isibaar 3
407 : edgomez 78 sad8 = sad16;
408 :     pMB->mode = MODE_INTER;
409 :     pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;
410 :     pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;
411 :     pMB->pmvs[0].x = pmv16.x;
412 :     pMB->pmvs[0].y = pmv16.y;
413 :     }
414 :     else
415 :     pMB->mode = MODE_INTER4V;
416 :     }
417 :     else
418 :     {
419 : Isibaar 3 sad8 = sad16;
420 :     pMB->mode = MODE_INTER;
421 :     pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;
422 :     pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;
423 :     pMB->pmvs[0].x = pmv16.x;
424 :     pMB->pmvs[0].y = pmv16.y;
425 :     }
426 :     }
427 :    
428 :     return 0;
429 :     }
430 :    
431 :     #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )
432 :    
433 :     #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )
434 :    
435 :    
436 :     #define CHECK_MV16_ZERO {\
437 :     if ( (0 <= max_dx) && (0 >= min_dx) \
438 :     && (0 <= max_dy) && (0 >= min_dy) ) \
439 :     { \
440 :     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \
441 :     iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\
442 :     if (iSAD <= iQuant * 96) \
443 :     iSAD -= MV16_00_BIAS; \
444 :     if (iSAD < iMinSAD) \
445 :     { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } } \
446 :     }
447 :    
448 : chl 96 #define NOCHECK_MV16_CANDIDATE(X,Y) { \
449 :     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
450 :     iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\
451 :     if (iSAD < iMinSAD) \
452 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
453 :     }
454 : Isibaar 3
455 :     #define CHECK_MV16_CANDIDATE(X,Y) { \
456 :     if ( ((X) <= max_dx) && ((X) >= min_dx) \
457 :     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
458 :     { \
459 :     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
460 :     iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\
461 :     if (iSAD < iMinSAD) \
462 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
463 :     }
464 :    
465 :     #define CHECK_MV16_CANDIDATE_DIR(X,Y,D) { \
466 :     if ( ((X) <= max_dx) && ((X) >= min_dx) \
467 :     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
468 :     { \
469 :     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
470 :     iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\
471 :     if (iSAD < iMinSAD) \
472 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
473 :     }
474 :    
475 :     #define CHECK_MV16_CANDIDATE_FOUND(X,Y,D) { \
476 :     if ( ((X) <= max_dx) && ((X) >= min_dx) \
477 :     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
478 :     { \
479 :     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
480 :     iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\
481 :     if (iSAD < iMinSAD) \
482 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
483 :     }
484 :    
485 :    
486 :     #define CHECK_MV8_ZERO {\
487 :     iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \
488 :     iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\
489 :     if (iSAD < iMinSAD) \
490 :     { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
491 :     }
492 :    
493 : chl 96 #define NOCHECK_MV8_CANDIDATE(X,Y) \
494 :     { \
495 :     iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
496 :     iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\
497 :     if (iSAD < iMinSAD) \
498 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
499 :     }
500 : Isibaar 3
501 :     #define CHECK_MV8_CANDIDATE(X,Y) { \
502 :     if ( ((X) <= max_dx) && ((X) >= min_dx) \
503 :     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
504 :     { \
505 :     iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
506 :     iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\
507 :     if (iSAD < iMinSAD) \
508 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
509 :     }
510 :    
511 :     #define CHECK_MV8_CANDIDATE_DIR(X,Y,D) { \
512 :     if ( ((X) <= max_dx) && ((X) >= min_dx) \
513 :     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
514 :     { \
515 :     iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
516 :     iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\
517 :     if (iSAD < iMinSAD) \
518 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
519 :     }
520 :    
521 :     #define CHECK_MV8_CANDIDATE_FOUND(X,Y,D) { \
522 :     if ( ((X) <= max_dx) && ((X) >= min_dx) \
523 :     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
524 :     { \
525 :     iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
526 :     iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\
527 :     if (iSAD < iMinSAD) \
528 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
529 :     }
530 :    
531 :     /* too slow and not fully functional at the moment */
532 :     /*
533 :     int32_t ZeroSearch16(
534 :     const uint8_t * const pRef,
535 :     const uint8_t * const pRefH,
536 :     const uint8_t * const pRefV,
537 :     const uint8_t * const pRefHV,
538 :     const IMAGE * const pCur,
539 :     const int x, const int y,
540 :     const uint32_t MotionFlags,
541 :     MBParam * const pParam,
542 :     MACROBLOCK * const pMBs,
543 :     VECTOR * const currMV,
544 :     VECTOR * const currPMV)
545 :     {
546 :     const int32_t iEdgedWidth = pParam->edged_width;
547 :     const int32_t iQuant = pParam->quant;
548 :     const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
549 :     int32_t iSAD;
550 :     int32_t pred_x,pred_y;
551 :    
552 :     get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);
553 :    
554 :     iSAD = sad16( cur,
555 :     get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),
556 :     iEdgedWidth, MV_MAX_ERROR);
557 :     if (iSAD <= iQuant * 96)
558 :     iSAD -= MV16_00_BIAS;
559 :    
560 :     currMV->x = 0;
561 :     currMV->y = 0;
562 :     currPMV->x = -pred_x;
563 :     currPMV->y = -pred_y;
564 :    
565 :     return iSAD;
566 :    
567 :     }
568 :     */
569 :    
570 : chl 96 int32_t Diamond16_MainSearch(
571 : edgomez 78 const uint8_t * const pRef,
572 :     const uint8_t * const pRefH,
573 :     const uint8_t * const pRefV,
574 :     const uint8_t * const pRefHV,
575 :     const uint8_t * const cur,
576 :     const int x, const int y,
577 :     int32_t startx, int32_t starty,
578 :     int32_t iMinSAD,
579 :     VECTOR * const currMV,
580 :     const VECTOR * const pmv,
581 :     const int32_t min_dx, const int32_t max_dx,
582 :     const int32_t min_dy, const int32_t max_dy,
583 :     const int32_t iEdgedWidth,
584 :     const int32_t iDiamondSize,
585 :     const int32_t iFcode,
586 :     const int32_t iQuant,
587 :     int iFound)
588 : Isibaar 3 {
589 :     /* Do a diamond search around given starting point, return SAD of best */
590 :    
591 :     int32_t iDirection=0;
592 :     int32_t iSAD;
593 :     VECTOR backupMV;
594 :     backupMV.x = startx;
595 :     backupMV.y = starty;
596 :    
597 :     /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
598 :    
599 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
600 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
601 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
602 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
603 :    
604 :     if (iDirection)
605 :     while (!iFound)
606 :     {
607 :     iFound = 1;
608 :     backupMV=*currMV;
609 :    
610 :     if ( iDirection != 2)
611 :     CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
612 :     if ( iDirection != 1)
613 :     CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);
614 :     if ( iDirection != 4)
615 :     CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);
616 :     if ( iDirection != 3)
617 :     CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);
618 :     }
619 :     else
620 : edgomez 78 {
621 :     currMV->x = startx;
622 :     currMV->y = starty;
623 :     }
624 : Isibaar 3 return iMinSAD;
625 :     }
626 :    
627 : chl 96 int32_t Square16_MainSearch(
628 :     const uint8_t * const pRef,
629 :     const uint8_t * const pRefH,
630 :     const uint8_t * const pRefV,
631 :     const uint8_t * const pRefHV,
632 :     const uint8_t * const cur,
633 :     const int x, const int y,
634 :     int32_t startx, int32_t starty,
635 :     int32_t iMinSAD,
636 :     VECTOR * const currMV,
637 :     const VECTOR * const pmv,
638 :     const int32_t min_dx, const int32_t max_dx,
639 :     const int32_t min_dy, const int32_t max_dy,
640 :     const int32_t iEdgedWidth,
641 :     const int32_t iDiamondSize,
642 :     const int32_t iFcode,
643 :     const int32_t iQuant,
644 :     int iFound)
645 :     {
646 :     /* Do a square search around given starting point, return SAD of best */
647 :    
648 :     int32_t iDirection=0;
649 :     int32_t iSAD;
650 :     VECTOR backupMV;
651 :     backupMV.x = startx;
652 :     backupMV.y = starty;
653 :    
654 :     /* It's one search with full square pattern, and new parts for all following diamonds */
655 :    
656 :     /* new direction are extra, so 1-4 is normal diamond
657 :     537
658 :     1*2
659 :     648
660 :     */
661 :    
662 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
663 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
664 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
665 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
666 :    
667 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
668 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
669 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
670 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
671 :    
672 :    
673 :     if (iDirection)
674 :     while (!iFound)
675 :     {
676 :     iFound = 1;
677 :     backupMV=*currMV;
678 :    
679 :     switch (iDirection)
680 :     {
681 :     case 1:
682 :     CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
683 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
684 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
685 :     break;
686 :     case 2:
687 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
688 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
689 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
690 :     break;
691 :    
692 :     case 3:
693 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
694 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
695 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
696 :     break;
697 :    
698 :     case 4:
699 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
700 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
701 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
702 :     break;
703 :    
704 :     case 5:
705 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
706 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
707 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
708 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
709 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
710 :     break;
711 :    
712 :     case 6:
713 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
714 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
715 :    
716 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
717 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
718 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
719 :    
720 :     break;
721 :    
722 :     case 7:
723 :     CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
724 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
725 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
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 :     case 8:
731 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
732 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
733 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
734 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
735 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
736 :     break;
737 :     default:
738 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
739 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
740 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
741 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
742 :    
743 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
744 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
745 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
746 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
747 :     break;
748 :     }
749 :     }
750 :     else
751 :     {
752 :     currMV->x = startx;
753 :     currMV->y = starty;
754 :     }
755 :     return iMinSAD;
756 :     }
757 :    
758 :    
759 :     int32_t Full16_MainSearch(
760 :     const uint8_t * const pRef,
761 :     const uint8_t * const pRefH,
762 :     const uint8_t * const pRefV,
763 :     const uint8_t * const pRefHV,
764 :     const uint8_t * const cur,
765 :     const int x, const int y,
766 :     int32_t startx, int32_t starty,
767 :     int32_t iMinSAD,
768 :     VECTOR * const currMV,
769 :     const VECTOR * const pmv,
770 :     const int32_t min_dx, const int32_t max_dx,
771 :     const int32_t min_dy, const int32_t max_dy,
772 :     const int32_t iEdgedWidth,
773 :     const int32_t iDiamondSize,
774 :     const int32_t iFcode,
775 :     const int32_t iQuant,
776 :     int iFound)
777 :     {
778 :     int32_t iSAD;
779 :     int32_t dx,dy;
780 :     VECTOR backupMV;
781 :     backupMV.x = startx;
782 :     backupMV.y = starty;
783 :    
784 :     for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
785 :     for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
786 :     NOCHECK_MV16_CANDIDATE(dx,dy);
787 :    
788 :     return iMinSAD;
789 :     }
790 :    
791 :     int32_t Full8_MainSearch(
792 :     const uint8_t * const pRef,
793 :     const uint8_t * const pRefH,
794 :     const uint8_t * const pRefV,
795 :     const uint8_t * const pRefHV,
796 :     const uint8_t * const cur,
797 :     const int x, const int y,
798 :     int32_t startx, int32_t starty,
799 :     int32_t iMinSAD,
800 :     VECTOR * const currMV,
801 :     const VECTOR * const pmv,
802 :     const int32_t min_dx, const int32_t max_dx,
803 :     const int32_t min_dy, const int32_t max_dy,
804 :     const int32_t iEdgedWidth,
805 :     const int32_t iDiamondSize,
806 :     const int32_t iFcode,
807 :     const int32_t iQuant,
808 :     int iFound)
809 :     {
810 :     int32_t iSAD;
811 :     int32_t dx,dy;
812 :     VECTOR backupMV;
813 :     backupMV.x = startx;
814 :     backupMV.y = starty;
815 :    
816 :     for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
817 :     for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
818 :     NOCHECK_MV8_CANDIDATE(dx,dy);
819 :    
820 :     return iMinSAD;
821 :     }
822 :    
823 :    
824 :    
825 :     int32_t Halfpel16_Refine(
826 : edgomez 78 const uint8_t * const pRef,
827 :     const uint8_t * const pRefH,
828 :     const uint8_t * const pRefV,
829 :     const uint8_t * const pRefHV,
830 :     const uint8_t * const cur,
831 :     const int x, const int y,
832 :     VECTOR * const currMV,
833 :     int32_t iMinSAD,
834 :     const VECTOR * const pmv,
835 :     const int32_t min_dx, const int32_t max_dx,
836 :     const int32_t min_dy, const int32_t max_dy,
837 :     const int32_t iFcode,
838 :     const int32_t iQuant,
839 :     const int32_t iEdgedWidth)
840 : Isibaar 3 {
841 :     /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
842 :    
843 :     int32_t iSAD;
844 :     VECTOR backupMV = *currMV;
845 :    
846 :     CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y-1);
847 :     CHECK_MV16_CANDIDATE(backupMV.x ,backupMV.y-1);
848 :     CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y-1);
849 :     CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y);
850 :     CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y);
851 :     CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y+1);
852 :     CHECK_MV16_CANDIDATE(backupMV.x ,backupMV.y+1);
853 :     CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y+1);
854 :    
855 :     return iMinSAD;
856 :     }
857 :    
858 :     #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
859 :    
860 : chl 96
861 : Isibaar 3 int32_t PMVfastSearch16(
862 : chl 96 const uint8_t * const pRef,
863 :     const uint8_t * const pRefH,
864 :     const uint8_t * const pRefV,
865 :     const uint8_t * const pRefHV,
866 :     const IMAGE * const pCur,
867 :     const int x, const int y,
868 :     const uint32_t MotionFlags,
869 :     const MBParam * const pParam,
870 :     MACROBLOCK * const pMBs,
871 :     VECTOR * const currMV,
872 :     VECTOR * const currPMV)
873 : Isibaar 3 {
874 :     const uint32_t iWcount = pParam->mb_width;
875 :     const int32_t iFcode = pParam->fixed_code;
876 :     const int32_t iQuant = pParam->quant;
877 :     const int32_t iWidth = pParam->width;
878 :     const int32_t iHeight = pParam->height;
879 :     const int32_t iEdgedWidth = pParam->edged_width;
880 :    
881 :     const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
882 :    
883 :     int32_t iDiamondSize;
884 :    
885 :     int32_t min_dx;
886 :     int32_t max_dx;
887 :     int32_t min_dy;
888 :     int32_t max_dy;
889 :    
890 :     int32_t iFound;
891 :    
892 :     VECTOR newMV;
893 :     VECTOR backupMV; /* just for PMVFAST */
894 :    
895 :     VECTOR pmv[4];
896 :     int32_t psad[4];
897 :    
898 :     MACROBLOCK * const pMB = pMBs + x + y * iWcount;
899 :    
900 :     static int32_t threshA,threshB;
901 :     int32_t bPredEq;
902 :     int32_t iMinSAD,iSAD;
903 :    
904 :     /* Get maximum range */
905 :     get_range(&min_dx, &max_dx, &min_dy, &max_dy,
906 : edgomez 78 x, y, 16, iWidth, iHeight, iFcode);
907 : Isibaar 3
908 :     /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
909 :    
910 :     if (!(MotionFlags & PMV_HALFPEL16 ))
911 :     { min_dx = EVEN(min_dx);
912 : edgomez 78 max_dx = EVEN(max_dx);
913 :     min_dy = EVEN(min_dy);
914 :     max_dy = EVEN(max_dy);
915 : Isibaar 3 } /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
916 :    
917 :    
918 :     bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
919 :    
920 :     if ((x==0) && (y==0) )
921 :     {
922 :     threshA = 512;
923 :     threshB = 1024;
924 :    
925 :     }
926 :     else
927 :     {
928 :     threshA = psad[0];
929 :     threshB = threshA+256;
930 :     if (threshA< 512) threshA = 512;
931 :     if (threshA>1024) threshA = 1024;
932 :     if (threshB>1792) threshB = 1792;
933 :     }
934 :    
935 :     iFound=0;
936 :    
937 :     /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
938 : edgomez 78 vector of the median.
939 :     If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
940 : Isibaar 3 */
941 :    
942 :     if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[0]) ) )
943 :     iFound=2;
944 :    
945 :     /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
946 : edgomez 78 Otherwise select large Diamond Search.
947 : Isibaar 3 */
948 :    
949 :     if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536) || (bPredEq) )
950 :     iDiamondSize=1; // halfpel!
951 :     else
952 :     iDiamondSize=2; // halfpel!
953 :    
954 :     if (!(MotionFlags & PMV_HALFPELDIAMOND16) )
955 :     iDiamondSize*=2;
956 :    
957 :     /* Step 4: Calculate SAD around the Median prediction.
958 : edgomez 78 MinSAD=SAD
959 :     If Motion Vector equal to Previous frame motion vector
960 :     and MinSAD<PrevFrmSAD goto Step 10.
961 :     If SAD<=256 goto Step 10.
962 : Isibaar 3 */
963 :    
964 :    
965 :     // Prepare for main loop
966 :    
967 :     *currMV=pmv[0]; /* current best := prediction */
968 :     if (!(MotionFlags & PMV_HALFPEL16 ))
969 :     { /* This should NOT be necessary! */
970 :     currMV->x = EVEN(currMV->x);
971 :     currMV->y = EVEN(currMV->y);
972 :     }
973 :    
974 :     if (currMV->x > max_dx)
975 : edgomez 78 {
976 :     currMV->x=max_dx;
977 :     }
978 : Isibaar 3 if (currMV->x < min_dx)
979 : edgomez 78 {
980 :     currMV->x=min_dx;
981 :     }
982 : Isibaar 3 if (currMV->y > max_dy)
983 : edgomez 78 {
984 :     currMV->y=max_dy;
985 :     }
986 : Isibaar 3 if (currMV->y < min_dy)
987 : edgomez 78 {
988 :     currMV->y=min_dy;
989 :     }
990 : Isibaar 3
991 :     iMinSAD = sad16( cur,
992 : edgomez 78 get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
993 :     iEdgedWidth, MV_MAX_ERROR);
994 : Isibaar 3 iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;
995 :    
996 :     if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )
997 : edgomez 78 {
998 : Isibaar 3
999 : edgomez 78 if (MotionFlags & PMV_QUICKSTOP16)
1000 : chl 96 goto PMVfast16_Terminate_without_Refine;
1001 :     if (MotionFlags & PMV_EARLYSTOP16)
1002 :     goto PMVfast16_Terminate_with_Refine;
1003 : edgomez 78 }
1004 : Isibaar 3
1005 :     /*
1006 : edgomez 78 Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
1007 :     Also calculate (0,0) but do not subtract offset.
1008 :     Let MinSAD be the smallest SAD up to this point.
1009 :     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********
1010 : Isibaar 3 */
1011 :    
1012 :     // (0,0) is always possible
1013 :    
1014 :     CHECK_MV16_ZERO;
1015 :    
1016 :     // previous frame MV is always possible
1017 :     CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);
1018 :    
1019 :     // left neighbour, if allowed
1020 :     if (x != 0)
1021 :     {
1022 :     if (!(MotionFlags & PMV_HALFPEL16 ))
1023 :     { pmv[1].x = EVEN(pmv[1].x);
1024 : edgomez 78 pmv[1].y = EVEN(pmv[1].y);
1025 : Isibaar 3 }
1026 :     CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1027 :     }
1028 :    
1029 :     // top neighbour, if allowed
1030 :     if (y != 0)
1031 :     {
1032 :     if (!(MotionFlags & PMV_HALFPEL16 ))
1033 :     { pmv[2].x = EVEN(pmv[2].x);
1034 : edgomez 78 pmv[2].y = EVEN(pmv[2].y);
1035 : Isibaar 3 }
1036 :     CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1037 :    
1038 :     // top right neighbour, if allowed
1039 :     if (x != (iWcount-1))
1040 :     {
1041 :     if (!(MotionFlags & PMV_HALFPEL16 ))
1042 :     { pmv[3].x = EVEN(pmv[3].x);
1043 : edgomez 78 pmv[3].y = EVEN(pmv[3].y);
1044 : Isibaar 3 }
1045 :     CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
1046 :     }
1047 :     }
1048 :    
1049 :     /* Step 6: If MinSAD <= thresa goto Step 10.
1050 :     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
1051 :     */
1052 :    
1053 :     if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )
1054 : edgomez 78 {
1055 :     if (MotionFlags & PMV_QUICKSTOP16)
1056 : chl 96 goto PMVfast16_Terminate_without_Refine;
1057 :     if (MotionFlags & PMV_EARLYSTOP16)
1058 :     goto PMVfast16_Terminate_with_Refine;
1059 : edgomez 78 }
1060 : Isibaar 3
1061 :    
1062 :     /************ (Diamond Search) **************/
1063 :     /*
1064 : edgomez 78 Step 7: Perform Diamond search, with either the small or large diamond.
1065 :     If Found=2 only examine one Diamond pattern, and afterwards goto step 10
1066 :     Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
1067 :     If center then goto step 10.
1068 :     Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
1069 :     Refine by using small diamond and goto step 10.
1070 : Isibaar 3 */
1071 :    
1072 :     backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1073 :    
1074 :     /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1075 : chl 96 iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1076 : edgomez 78 x, y,
1077 :     currMV->x, currMV->y, iMinSAD, &newMV,
1078 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
1079 : Isibaar 3
1080 :     if (iSAD < iMinSAD)
1081 :     {
1082 :     *currMV = newMV;
1083 :     iMinSAD = iSAD;
1084 :     }
1085 :    
1086 :     if (MotionFlags & PMV_EXTSEARCH16)
1087 :     {
1088 :     /* extended: search (up to) two more times: orignal prediction and (0,0) */
1089 :    
1090 :     if (!(MVequal(pmv[0],backupMV)) )
1091 : chl 96 { iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1092 : edgomez 78 x, y,
1093 :     pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1094 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
1095 : Isibaar 3
1096 : edgomez 78 if (iSAD < iMinSAD)
1097 :     {
1098 :     *currMV = newMV;
1099 :     iMinSAD = iSAD;
1100 : Isibaar 3 }
1101 : edgomez 78 }
1102 : Isibaar 3
1103 :     if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1104 : chl 96 { iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1105 : edgomez 78 x, y,
1106 :     0, 0, iMinSAD, &newMV,
1107 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
1108 : Isibaar 3
1109 : edgomez 78 if (iSAD < iMinSAD)
1110 :     {
1111 :     *currMV = newMV;
1112 :     iMinSAD = iSAD;
1113 : Isibaar 3 }
1114 : edgomez 78 }
1115 : Isibaar 3 }
1116 :    
1117 :     /*
1118 : edgomez 78 Step 10: The motion vector is chosen according to the block corresponding to MinSAD.
1119 : Isibaar 3 */
1120 :    
1121 : chl 96 PMVfast16_Terminate_with_Refine:
1122 : Isibaar 3 if (MotionFlags & PMV_HALFPELREFINE16) // perform final half-pel step
1123 : chl 96 iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1124 :     x, y,
1125 :     currMV, iMinSAD,
1126 :     pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1127 : Isibaar 3
1128 : chl 96 PMVfast16_Terminate_without_Refine:
1129 : Isibaar 3 currPMV->x = currMV->x - pmv[0].x;
1130 :     currPMV->y = currMV->y - pmv[0].y;
1131 :     return iMinSAD;
1132 :     }
1133 :    
1134 :    
1135 :    
1136 :    
1137 :    
1138 :    
1139 : chl 96 int32_t Diamond8_MainSearch(
1140 : edgomez 78 const uint8_t * const pRef,
1141 :     const uint8_t * const pRefH,
1142 :     const uint8_t * const pRefV,
1143 :     const uint8_t * const pRefHV,
1144 :     const uint8_t * const cur,
1145 :     const int x, const int y,
1146 :     int32_t startx, int32_t starty,
1147 :     int32_t iMinSAD,
1148 :     VECTOR * const currMV,
1149 :     const VECTOR * const pmv,
1150 :     const int32_t min_dx, const int32_t max_dx,
1151 :     const int32_t min_dy, const int32_t max_dy,
1152 :     const int32_t iEdgedWidth,
1153 :     const int32_t iDiamondSize,
1154 :     const int32_t iFcode,
1155 :     const int32_t iQuant,
1156 :     int iFound)
1157 : Isibaar 3 {
1158 :     /* Do a diamond search around given starting point, return SAD of best */
1159 :    
1160 :     int32_t iDirection=0;
1161 :     int32_t iSAD;
1162 :     VECTOR backupMV;
1163 :     backupMV.x = startx;
1164 :     backupMV.y = starty;
1165 :    
1166 :     /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1167 :    
1168 :     CHECK_MV8_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
1169 :     CHECK_MV8_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
1170 :     CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
1171 :     CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1172 :    
1173 :     if (iDirection)
1174 :     while (!iFound)
1175 :     {
1176 :     iFound = 1;
1177 :     backupMV=*currMV; // since iDirection!=0, this is well defined!
1178 :    
1179 :     if ( iDirection != 2)
1180 :     CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
1181 :     if ( iDirection != 1)
1182 :     CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);
1183 :     if ( iDirection != 4)
1184 :     CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);
1185 :     if ( iDirection != 3)
1186 :     CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);
1187 :     }
1188 :     else
1189 : edgomez 78 {
1190 :     currMV->x = startx;
1191 :     currMV->y = starty;
1192 :     }
1193 : Isibaar 3 return iMinSAD;
1194 :     }
1195 :    
1196 : chl 96 int32_t Halfpel8_Refine(
1197 : edgomez 78 const uint8_t * const pRef,
1198 :     const uint8_t * const pRefH,
1199 :     const uint8_t * const pRefV,
1200 :     const uint8_t * const pRefHV,
1201 :     const uint8_t * const cur,
1202 :     const int x, const int y,
1203 :     VECTOR * const currMV,
1204 :     int32_t iMinSAD,
1205 :     const VECTOR * const pmv,
1206 :     const int32_t min_dx, const int32_t max_dx,
1207 :     const int32_t min_dy, const int32_t max_dy,
1208 :     const int32_t iFcode,
1209 :     const int32_t iQuant,
1210 :     const int32_t iEdgedWidth)
1211 : Isibaar 3 {
1212 :     /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
1213 :    
1214 :     int32_t iSAD;
1215 :     VECTOR backupMV = *currMV;
1216 :    
1217 :     CHECK_MV8_CANDIDATE(backupMV.x-1,backupMV.y-1);
1218 :     CHECK_MV8_CANDIDATE(backupMV.x ,backupMV.y-1);
1219 :     CHECK_MV8_CANDIDATE(backupMV.x+1,backupMV.y-1);
1220 :     CHECK_MV8_CANDIDATE(backupMV.x-1,backupMV.y);
1221 :     CHECK_MV8_CANDIDATE(backupMV.x+1,backupMV.y);
1222 :     CHECK_MV8_CANDIDATE(backupMV.x-1,backupMV.y+1);
1223 :     CHECK_MV8_CANDIDATE(backupMV.x ,backupMV.y+1);
1224 :     CHECK_MV8_CANDIDATE(backupMV.x+1,backupMV.y+1);
1225 :    
1226 :     return iMinSAD;
1227 :     }
1228 :    
1229 :    
1230 :     #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1231 :    
1232 :     int32_t PMVfastSearch8(
1233 : chl 96 const uint8_t * const pRef,
1234 :     const uint8_t * const pRefH,
1235 :     const uint8_t * const pRefV,
1236 :     const uint8_t * const pRefHV,
1237 :     const IMAGE * const pCur,
1238 :     const int x, const int y,
1239 :     const int start_x, int start_y,
1240 :     const uint32_t MotionFlags,
1241 :     const MBParam * const pParam,
1242 :     MACROBLOCK * const pMBs,
1243 :     VECTOR * const currMV,
1244 :     VECTOR * const currPMV)
1245 : Isibaar 3 {
1246 :     const uint32_t iWcount = pParam->mb_width;
1247 :    
1248 :     const int32_t iFcode = pParam->fixed_code;
1249 :     const int32_t iQuant = pParam->quant;
1250 :     const int32_t iWidth = pParam->width;
1251 :     const int32_t iHeight = pParam->height;
1252 :     const int32_t iEdgedWidth = pParam->edged_width;
1253 :    
1254 :     const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;
1255 :    
1256 :     int32_t iDiamondSize;
1257 :    
1258 :     int32_t min_dx;
1259 :     int32_t max_dx;
1260 :     int32_t min_dy;
1261 :     int32_t max_dy;
1262 :    
1263 :     VECTOR pmv[4];
1264 :     int32_t psad[4];
1265 :     VECTOR newMV;
1266 :     VECTOR backupMV;
1267 :    
1268 :     MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1269 :    
1270 :     static int32_t threshA,threshB;
1271 :     int32_t iFound,bPredEq;
1272 :     int32_t iMinSAD,iSAD;
1273 :    
1274 :     int32_t iSubBlock = ((y&1)<<1) + (x&1);
1275 :    
1276 :     /* Get maximum range */
1277 : edgomez 78 get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1278 :     x, y, 8, iWidth, iHeight, iFcode);
1279 : Isibaar 3
1280 :     /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */
1281 :    
1282 :     if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))
1283 :     { min_dx = EVEN(min_dx);
1284 : edgomez 78 max_dx = EVEN(max_dx);
1285 :     min_dy = EVEN(min_dy);
1286 :     max_dy = EVEN(max_dy);
1287 : Isibaar 3 } /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
1288 :    
1289 :    
1290 :     bPredEq = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);
1291 :    
1292 :     if ((x==0) && (y==0) )
1293 :     {
1294 :     threshA = 512/4;
1295 :     threshB = 1024/4;
1296 :    
1297 :     }
1298 :     else
1299 :     {
1300 :     threshA = psad[0]/4; /* good estimate */
1301 :     threshB = threshA+256/4;
1302 :     if (threshA< 512/4) threshA = 512/4;
1303 :     if (threshA>1024/4) threshA = 1024/4;
1304 :     if (threshB>1792/4) threshB = 1792/4;
1305 :     }
1306 :    
1307 :     iFound=0;
1308 :    
1309 :     /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1310 : edgomez 78 vector of the median.
1311 :     If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1312 : Isibaar 3 */
1313 :    
1314 :     if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[iSubBlock]) ) )
1315 :     iFound=2;
1316 :    
1317 :     /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1318 : edgomez 78 Otherwise select large Diamond Search.
1319 : Isibaar 3 */
1320 :    
1321 :     if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536/4) || (bPredEq) )
1322 :     iDiamondSize=1; // 1 halfpel!
1323 :     else
1324 :     iDiamondSize=2; // 2 halfpel = 1 full pixel!
1325 :    
1326 :     if (!(MotionFlags & PMV_HALFPELDIAMOND8) )
1327 :     iDiamondSize*=2;
1328 :    
1329 :     /* Step 4: Calculate SAD around the Median prediction.
1330 : edgomez 78 MinSAD=SAD
1331 :     If Motion Vector equal to Previous frame motion vector
1332 :     and MinSAD<PrevFrmSAD goto Step 10.
1333 :     If SAD<=256 goto Step 10.
1334 : Isibaar 3 */
1335 :    
1336 :    
1337 :     // Prepare for main loop
1338 :    
1339 :     currMV->x=start_x; /* start with mv16 */
1340 :     currMV->y=start_y;
1341 :    
1342 :     iMinSAD = sad8( cur,
1343 : edgomez 78 get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
1344 :     iEdgedWidth);
1345 : Isibaar 3 iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode) * iQuant;
1346 :    
1347 :     if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && (iMinSAD < pMB->sad8[iSubBlock]) ) )
1348 : edgomez 78 {
1349 : chl 96 if (MotionFlags & PMV_QUICKSTOP16)
1350 :     goto PMVfast8_Terminate_without_Refine;
1351 :     if (MotionFlags & PMV_EARLYSTOP16)
1352 :     goto PMVfast8_Terminate_with_Refine;
1353 : edgomez 78 }
1354 : Isibaar 3
1355 : chl 96
1356 : Isibaar 3 /*
1357 : edgomez 78 Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
1358 :     Also calculate (0,0) but do not subtract offset.
1359 :     Let MinSAD be the smallest SAD up to this point.
1360 :     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********
1361 : Isibaar 3 */
1362 :    
1363 :     // the prediction might be even better than mv16
1364 :     CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);
1365 :    
1366 :     // (0,0) is always possible
1367 :     CHECK_MV8_ZERO;
1368 :    
1369 :     // previous frame MV is always possible
1370 :     CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);
1371 :    
1372 :     // left neighbour, if allowed
1373 :     if (psad[1] != MV_MAX_ERROR)
1374 :     {
1375 :     if (!(MotionFlags & PMV_HALFPEL8 ))
1376 :     { pmv[1].x = EVEN(pmv[1].x);
1377 : edgomez 78 pmv[1].y = EVEN(pmv[1].y);
1378 : Isibaar 3 }
1379 :     CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1380 :     }
1381 :    
1382 :     // top neighbour, if allowed
1383 :     if (psad[2] != MV_MAX_ERROR)
1384 :     {
1385 :     if (!(MotionFlags & PMV_HALFPEL8 ))
1386 :     { pmv[2].x = EVEN(pmv[2].x);
1387 : edgomez 78 pmv[2].y = EVEN(pmv[2].y);
1388 : Isibaar 3 }
1389 :     CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1390 :    
1391 :     // top right neighbour, if allowed
1392 :     if (psad[3] != MV_MAX_ERROR)
1393 :     {
1394 : edgomez 78 if (!(MotionFlags & PMV_HALFPEL8 ))
1395 :     { pmv[3].x = EVEN(pmv[3].x);
1396 : Isibaar 3 pmv[3].y = EVEN(pmv[3].y);
1397 : edgomez 78 }
1398 : Isibaar 3 CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);
1399 :     }
1400 :     }
1401 :    
1402 :     /* Step 6: If MinSAD <= thresa goto Step 10.
1403 :     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
1404 :     */
1405 :    
1406 :     if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && (iMinSAD < pMB->sad8[iSubBlock]) ) )
1407 : edgomez 78 {
1408 : chl 96 if (MotionFlags & PMV_QUICKSTOP16)
1409 :     goto PMVfast8_Terminate_without_Refine;
1410 :     if (MotionFlags & PMV_EARLYSTOP16)
1411 :     goto PMVfast8_Terminate_with_Refine;
1412 : edgomez 78 }
1413 : Isibaar 3
1414 :     /************ (Diamond Search) **************/
1415 :     /*
1416 : edgomez 78 Step 7: Perform Diamond search, with either the small or large diamond.
1417 :     If Found=2 only examine one Diamond pattern, and afterwards goto step 10
1418 :     Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
1419 :     If center then goto step 10.
1420 :     Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
1421 :     Refine by using small diamond and goto step 10.
1422 : Isibaar 3 */
1423 :    
1424 :     backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1425 :    
1426 :     /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1427 : chl 96 iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1428 : edgomez 78 x, y,
1429 :     currMV->x, currMV->y, iMinSAD, &newMV,
1430 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
1431 : Isibaar 3
1432 :     if (iSAD < iMinSAD)
1433 :     {
1434 :     *currMV = newMV;
1435 :     iMinSAD = iSAD;
1436 :     }
1437 :    
1438 :     if (MotionFlags & PMV_EXTSEARCH8)
1439 :     {
1440 :     /* extended: search (up to) two more times: orignal prediction and (0,0) */
1441 :    
1442 :     if (!(MVequal(pmv[0],backupMV)) )
1443 : chl 96 { iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1444 : edgomez 78 x, y,
1445 :     pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1446 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
1447 : Isibaar 3
1448 : edgomez 78 if (iSAD < iMinSAD)
1449 :     {
1450 :     *currMV = newMV;
1451 :     iMinSAD = iSAD;
1452 : Isibaar 3 }
1453 : edgomez 78 }
1454 : Isibaar 3
1455 :     if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1456 : chl 96 { iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1457 : edgomez 78 x, y,
1458 :     0, 0, iMinSAD, &newMV,
1459 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
1460 : Isibaar 3
1461 : edgomez 78 if (iSAD < iMinSAD)
1462 :     {
1463 :     *currMV = newMV;
1464 :     iMinSAD = iSAD;
1465 : Isibaar 3 }
1466 : edgomez 78 }
1467 : Isibaar 3 }
1468 :    
1469 :     /* Step 10: The motion vector is chosen according to the block corresponding to MinSAD.
1470 : edgomez 78 By performing an optional local half-pixel search, we can refine this result even further.
1471 : Isibaar 3 */
1472 :    
1473 : chl 96 PMVfast8_Terminate_with_Refine:
1474 : Isibaar 3 if (MotionFlags & PMV_HALFPELREFINE8) // perform final half-pel step
1475 : chl 96 iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1476 : edgomez 78 x, y,
1477 :     currMV, iMinSAD,
1478 :     pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1479 : Isibaar 3
1480 :    
1481 : chl 96 PMVfast8_Terminate_without_Refine:
1482 : Isibaar 3 currPMV->x = currMV->x - pmv[0].x;
1483 :     currPMV->y = currMV->y - pmv[0].y;
1484 :    
1485 :     return iMinSAD;
1486 :     }
1487 : chl 96
1488 :     int32_t EPZSSearch16(
1489 :     const uint8_t * const pRef,
1490 :     const uint8_t * const pRefH,
1491 :     const uint8_t * const pRefV,
1492 :     const uint8_t * const pRefHV,
1493 :     const IMAGE * const pCur,
1494 :     const int x, const int y,
1495 :     const uint32_t MotionFlags,
1496 :     const MBParam * const pParam,
1497 :     MACROBLOCK * const pMBs,
1498 :     VECTOR * const currMV,
1499 :     VECTOR * const currPMV)
1500 :     {
1501 :     const uint32_t iWcount = pParam->mb_width;
1502 :     const uint32_t iHcount = pParam->mb_height;
1503 :     const int32_t iFcode = pParam->fixed_code;
1504 :     const int32_t iQuant = pParam->quant;
1505 :    
1506 :     const int32_t iWidth = pParam->width;
1507 :     const int32_t iHeight = pParam->height;
1508 :     const int32_t iEdgedWidth = pParam->edged_width;
1509 :    
1510 :     const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
1511 :    
1512 :     int32_t min_dx;
1513 :     int32_t max_dx;
1514 :     int32_t min_dy;
1515 :     int32_t max_dy;
1516 :    
1517 :     VECTOR newMV;
1518 :     VECTOR backupMV;
1519 :    
1520 :     VECTOR pmv[4];
1521 :     int32_t psad[8];
1522 :    
1523 :     static MACROBLOCK * oldMBs = NULL;
1524 :     MACROBLOCK * const pMB = pMBs + x + y * iWcount;
1525 :     MACROBLOCK * oldMB = NULL;
1526 :    
1527 :     static int32_t thresh2;
1528 :     int32_t bPredEq;
1529 :     int32_t iMinSAD,iSAD=9999;
1530 :    
1531 :     MainSearch16FuncPtr EPZSMainSearchPtr;
1532 :    
1533 :     if (oldMBs == NULL)
1534 :     { oldMBs = (MACROBLOCK*) calloc(1,iWcount*iHcount*sizeof(MACROBLOCK));
1535 :     fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
1536 :     }
1537 :     oldMB = oldMBs + x + y * iWcount;
1538 :    
1539 :     /* Get maximum range */
1540 :     get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1541 :     x, y, 16, iWidth, iHeight, iFcode);
1542 :    
1543 :     /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1544 :    
1545 :     if (!(MotionFlags & PMV_HALFPEL16 ))
1546 :     { min_dx = EVEN(min_dx);
1547 :     max_dx = EVEN(max_dx);
1548 :     min_dy = EVEN(min_dy);
1549 :     max_dy = EVEN(max_dy);
1550 :     } /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1551 :    
1552 :     bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1553 :    
1554 :     /* Step 4: Calculate SAD around the Median prediction.
1555 :     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 :     */
1560 :    
1561 :     // Prepare for main loop
1562 :    
1563 :     *currMV=pmv[0]; /* current best := median prediction */
1564 :     if (!(MotionFlags & PMV_HALFPEL16))
1565 :     {
1566 :     currMV->x = EVEN(currMV->x);
1567 :     currMV->y = EVEN(currMV->y);
1568 :     }
1569 :    
1570 :     if (currMV->x > max_dx)
1571 :     currMV->x=max_dx;
1572 :     if (currMV->x < min_dx)
1573 :     currMV->x=min_dx;
1574 :     if (currMV->y > max_dy)
1575 :     currMV->y=max_dy;
1576 :     if (currMV->y < min_dy)
1577 :     currMV->y=min_dy;
1578 :    
1579 :     /***************** This is predictor SET A: only median prediction ******************/
1580 :    
1581 :     iMinSAD = sad16( cur,
1582 :     get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
1583 :     iEdgedWidth, MV_MAX_ERROR);
1584 :     iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;
1585 :    
1586 :     // thresh1 is fixed to 256
1587 :     if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )
1588 :     {
1589 :     if (MotionFlags & PMV_QUICKSTOP16)
1590 :     goto EPZS16_Terminate_without_Refine;
1591 :     if (MotionFlags & PMV_EARLYSTOP16)
1592 :     goto EPZS16_Terminate_with_Refine;
1593 :     }
1594 :    
1595 :     /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1596 :    
1597 :     // previous frame MV
1598 :     CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);
1599 :    
1600 :     // set threshhold based on Min of Prediction and SAD of collocated block
1601 :     // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
1602 :    
1603 :     if ((x==0) && (y==0) )
1604 :     {
1605 :     thresh2 = 512;
1606 :     }
1607 :     else
1608 :     {
1609 :     /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128; [Tourapis, 2002] */
1610 :    
1611 :     thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
1612 :     }
1613 :    
1614 :     // MV=(0,0) is often a good choice
1615 :    
1616 :     CHECK_MV16_ZERO;
1617 :    
1618 :    
1619 :     // left neighbour, if allowed
1620 :     if (x != 0)
1621 :     {
1622 :     if (!(MotionFlags & PMV_HALFPEL16 ))
1623 :     { pmv[1].x = EVEN(pmv[1].x);
1624 :     pmv[1].y = EVEN(pmv[1].y);
1625 :     }
1626 :     CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1627 :     }
1628 :    
1629 :     // top neighbour, if allowed
1630 :     if (y != 0)
1631 :     {
1632 :     if (!(MotionFlags & PMV_HALFPEL16 ))
1633 :     { pmv[2].x = EVEN(pmv[2].x);
1634 :     pmv[2].y = EVEN(pmv[2].y);
1635 :     }
1636 :     CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1637 :    
1638 :     // top right neighbour, if allowed
1639 :     if (x != (iWcount-1))
1640 :     {
1641 :     if (!(MotionFlags & PMV_HALFPEL16 ))
1642 :     { pmv[3].x = EVEN(pmv[3].x);
1643 :     pmv[3].y = EVEN(pmv[3].y);
1644 :     }
1645 :     CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
1646 :     }
1647 :     }
1648 :    
1649 :     /* Terminate if MinSAD <= T_2
1650 :     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1651 :     */
1652 :    
1653 :     if ( (iMinSAD <= thresh2)
1654 :     || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD <= pMB->sad16) ) )
1655 :     {
1656 :     if (MotionFlags & PMV_QUICKSTOP16)
1657 :     goto EPZS16_Terminate_without_Refine;
1658 :     if (MotionFlags & PMV_EARLYSTOP16)
1659 :     goto EPZS16_Terminate_with_Refine;
1660 :     }
1661 :    
1662 :     /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
1663 :    
1664 :     backupMV = pMB->mvs[0]; // last MV
1665 :     backupMV.x += (pMB->mvs[0].x - oldMB->mvs[0].x ); // acceleration X
1666 :     backupMV.y += (pMB->mvs[0].y - oldMB->mvs[0].y ); // acceleration Y
1667 :    
1668 :     CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);
1669 :    
1670 :     // left neighbour
1671 :     if (x != 0)
1672 :     CHECK_MV16_CANDIDATE((oldMB-1)->mvs[0].x,oldMB->mvs[0].y);
1673 :    
1674 :     // top neighbour
1675 :     if (y != 0)
1676 :     CHECK_MV16_CANDIDATE((oldMB-iWcount)->mvs[0].x,oldMB->mvs[0].y);
1677 :    
1678 :     // right neighbour, if allowed (this value is not written yet, so take it from pMB->mvs
1679 :    
1680 :     if (x != iWcount-1)
1681 :     CHECK_MV16_CANDIDATE((pMB+1)->mvs[0].x,oldMB->mvs[0].y);
1682 :    
1683 :     // bottom neighbour, dito
1684 :     if (y != iHcount-1)
1685 :     CHECK_MV16_CANDIDATE((pMB+iWcount)->mvs[0].x,oldMB->mvs[0].y);
1686 :    
1687 :     /* Terminate if MinSAD <= T_3 (here T_3 = T_2) */
1688 :     if (iMinSAD <= thresh2)
1689 :     {
1690 :     if (MotionFlags & PMV_QUICKSTOP16)
1691 :     goto EPZS16_Terminate_without_Refine;
1692 :     if (MotionFlags & PMV_EARLYSTOP16)
1693 :     goto EPZS16_Terminate_with_Refine;
1694 :     }
1695 :    
1696 :     /************ (if Diamond Search) **************/
1697 :    
1698 :     backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1699 :    
1700 :     /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1701 :    
1702 :     if (MotionFlags & PMV_USESQUARES16)
1703 :     EPZSMainSearchPtr = Square16_MainSearch;
1704 :     else
1705 :     EPZSMainSearchPtr = Diamond16_MainSearch;
1706 :    
1707 :     iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1708 :     x, y,
1709 :     currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1710 :     2, iFcode, iQuant, 0);
1711 :    
1712 :     if (iSAD < iMinSAD)
1713 :     {
1714 :     *currMV = newMV;
1715 :     iMinSAD = iSAD;
1716 :     }
1717 :    
1718 :    
1719 :     if (MotionFlags & PMV_EXTSEARCH16)
1720 :     {
1721 :     /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
1722 :    
1723 :     if (!(MVequal(pmv[0],backupMV)) )
1724 :     {
1725 :     iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1726 :     x, y,
1727 :     pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1728 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
1729 :     }
1730 :    
1731 :     if (iSAD < iMinSAD)
1732 :     {
1733 :     *currMV = newMV;
1734 :     iMinSAD = iSAD;
1735 :     }
1736 :    
1737 :     if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1738 :     {
1739 :     iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1740 :     x, y,
1741 :     0, 0, iMinSAD, &newMV,
1742 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, /*iDiamondSize*/ 2, iFcode, iQuant, 0);
1743 :    
1744 :     if (iSAD < iMinSAD)
1745 :     {
1746 :     *currMV = newMV;
1747 :     iMinSAD = iSAD;
1748 :     }
1749 :     }
1750 :     }
1751 :    
1752 :     /*************** Choose best MV found **************/
1753 :    
1754 :     EPZS16_Terminate_with_Refine:
1755 :     if (MotionFlags & PMV_HALFPELREFINE16) // perform final half-pel step
1756 :     iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1757 :     x, y,
1758 :     currMV, iMinSAD,
1759 :     pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1760 :    
1761 :     EPZS16_Terminate_without_Refine:
1762 :    
1763 :     *oldMB = *pMB;
1764 :    
1765 :     currPMV->x = currMV->x - pmv[0].x;
1766 :     currPMV->y = currMV->y - pmv[0].y;
1767 :     return iMinSAD;
1768 :     }
1769 :    
1770 :    
1771 :     int32_t EPZSSearch8(
1772 :     const uint8_t * const pRef,
1773 :     const uint8_t * const pRefH,
1774 :     const uint8_t * const pRefV,
1775 :     const uint8_t * const pRefHV,
1776 :     const IMAGE * const pCur,
1777 :     const int x, const int y,
1778 :     const int start_x, const int start_y,
1779 :     const uint32_t MotionFlags,
1780 :     const MBParam * const pParam,
1781 :     MACROBLOCK * const pMBs,
1782 :     VECTOR * const currMV,
1783 :     VECTOR * const currPMV)
1784 :     {
1785 :     const uint32_t iWcount = pParam->mb_width;
1786 :     const int32_t iFcode = pParam->fixed_code;
1787 :     const int32_t iQuant = pParam->quant;
1788 :    
1789 :     const int32_t iWidth = pParam->width;
1790 :     const int32_t iHeight = pParam->height;
1791 :     const int32_t iEdgedWidth = pParam->edged_width;
1792 :    
1793 :     const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;
1794 :    
1795 :     int32_t iDiamondSize=1;
1796 :    
1797 :     int32_t min_dx;
1798 :     int32_t max_dx;
1799 :     int32_t min_dy;
1800 :     int32_t max_dy;
1801 :    
1802 :     VECTOR newMV;
1803 :     VECTOR backupMV;
1804 :    
1805 :     VECTOR pmv[4];
1806 :     int32_t psad[8];
1807 :    
1808 :     const int32_t iSubBlock = ((y&1)<<1) + (x&1);
1809 :    
1810 :     MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1811 :    
1812 :     int32_t bPredEq;
1813 :     int32_t iMinSAD,iSAD=9999;
1814 :    
1815 :     MainSearch8FuncPtr EPZSMainSearchPtr;
1816 :    
1817 :     /* Get maximum range */
1818 :     get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1819 :     x, y, 8, iWidth, iHeight, iFcode);
1820 :    
1821 :     /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1822 :    
1823 :     if (!(MotionFlags & PMV_HALFPEL8 ))
1824 :     { min_dx = EVEN(min_dx);
1825 :     max_dx = EVEN(max_dx);
1826 :     min_dy = EVEN(min_dy);
1827 :     max_dy = EVEN(max_dy);
1828 :     } /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1829 :    
1830 :     bPredEq = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);
1831 :    
1832 :    
1833 :     /* Step 4: Calculate SAD around the Median prediction.
1834 :     MinSAD=SAD
1835 :     If Motion Vector equal to Previous frame motion vector
1836 :     and MinSAD<PrevFrmSAD goto Step 10.
1837 :     If SAD<=256 goto Step 10.
1838 :     */
1839 :    
1840 :     // Prepare for main loop
1841 :    
1842 :    
1843 :     if (!(MotionFlags & PMV_HALFPEL8))
1844 :     {
1845 :     currMV->x = EVEN(currMV->x);
1846 :     currMV->y = EVEN(currMV->y);
1847 :     }
1848 :    
1849 :     if (currMV->x > max_dx)
1850 :     currMV->x=max_dx;
1851 :     if (currMV->x < min_dx)
1852 :     currMV->x=min_dx;
1853 :     if (currMV->y > max_dy)
1854 :     currMV->y=max_dy;
1855 :     if (currMV->y < min_dy)
1856 :     currMV->y=min_dy;
1857 :    
1858 :     /***************** This is predictor SET A: only median prediction ******************/
1859 :    
1860 :    
1861 :     iMinSAD = sad8( cur,
1862 :     get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
1863 :     iEdgedWidth);
1864 :     iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;
1865 :    
1866 :    
1867 :     // thresh1 is fixed to 256
1868 :     if (iMinSAD < 256/4 )
1869 :     {
1870 :     if (MotionFlags & PMV_QUICKSTOP8)
1871 :     goto EPZS8_Terminate_without_Refine;
1872 :     if (MotionFlags & PMV_EARLYSTOP8)
1873 :     goto EPZS8_Terminate_with_Refine;
1874 :     }
1875 :    
1876 :     /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1877 :    
1878 :     // previous frame MV
1879 :     CHECK_MV8_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);
1880 :    
1881 :     // MV=(0,0) is often a good choice
1882 :    
1883 :     CHECK_MV8_ZERO;
1884 :    
1885 :     /* Terminate if MinSAD <= T_2
1886 :     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1887 :     */
1888 :    
1889 :     if (iMinSAD < 512/4) /* T_2 == 512/4 hardcoded */
1890 :     {
1891 :     if (MotionFlags & PMV_QUICKSTOP8)
1892 :     goto EPZS8_Terminate_without_Refine;
1893 :     if (MotionFlags & PMV_EARLYSTOP8)
1894 :     goto EPZS8_Terminate_with_Refine;
1895 :     }
1896 :    
1897 :     /************ (if Diamond Search) **************/
1898 :    
1899 :     backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1900 :    
1901 :     if (!(MotionFlags & PMV_HALFPELDIAMOND8))
1902 :     iDiamondSize *= 2;
1903 :    
1904 :     /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1905 :    
1906 :     // if (MotionFlags & PMV_USESQUARES8)
1907 :     // EPZSMainSearchPtr = Square8_MainSearch;
1908 :     // else
1909 :     EPZSMainSearchPtr = Diamond8_MainSearch;
1910 :    
1911 :     iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1912 :     x, y,
1913 :     currMV->x, currMV->y, iMinSAD, &newMV,
1914 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1915 :     iDiamondSize, iFcode, iQuant, 00);
1916 :    
1917 :    
1918 :     if (iSAD < iMinSAD)
1919 :     {
1920 :     *currMV = newMV;
1921 :     iMinSAD = iSAD;
1922 :     }
1923 :    
1924 :     if (MotionFlags & PMV_EXTSEARCH8)
1925 :     {
1926 :     /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
1927 :    
1928 :     if (!(MVequal(pmv[0],backupMV)) )
1929 :     {
1930 :     iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1931 :     x, y,
1932 :     pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1933 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
1934 :    
1935 :     if (iSAD < iMinSAD)
1936 :     {
1937 :     *currMV = newMV;
1938 :     iMinSAD = iSAD;
1939 :     }
1940 :     }
1941 :    
1942 :     if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1943 :     {
1944 :     iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1945 :     x, y,
1946 :     0, 0, iMinSAD, &newMV,
1947 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
1948 :    
1949 :     if (iSAD < iMinSAD)
1950 :     {
1951 :     *currMV = newMV;
1952 :     iMinSAD = iSAD;
1953 :     }
1954 :     }
1955 :     }
1956 :    
1957 :     /*************** Choose best MV found **************/
1958 :    
1959 :     EPZS8_Terminate_with_Refine:
1960 :     if (MotionFlags & PMV_HALFPELREFINE8) // perform final half-pel step
1961 :     iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1962 :     x, y,
1963 :     currMV, iMinSAD,
1964 :     pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1965 :    
1966 :     EPZS8_Terminate_without_Refine:
1967 :    
1968 :     currPMV->x = currMV->x - pmv[0].x;
1969 :     currPMV->y = currMV->y - pmv[0].y;
1970 :     return iMinSAD;
1971 :     }
1972 :    

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