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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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

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