[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 140 - (view) (download)

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

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