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

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

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