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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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

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