[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 141 - (view) (download)
Original Path: trunk/xvidcore/src/motion/motion_est.c

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

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