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

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