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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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

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