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

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

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