[cvs] / xvidcore / src / motion / motion_est.c Repository:
ViewVC logotype

Annotation of /xvidcore/src/motion/motion_est.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (view) (download)

1 : Isibaar 1.1 /**************************************************************************
2 :     *
3 :     * Modifications:
4 :     *
5 :     * 08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop
6 :     * PMVFast_Refine to support multiple searches with different start points
7 :     * 07.01.2002 uv-block-based interpolation
8 :     * 06.01.2002 INTER/INTRA-decision is now done before any SEARCH8 (speedup)
9 :     * changed INTER_BIAS to 150 (as suggested by suxen_drol)
10 :     * removed halfpel refinement step in PMVfastSearch8 + quality=5
11 :     * added new quality mode = 6 which performs halfpel refinement
12 :     * filesize difference between quality 5 and 6 is smaller than 1%
13 :     * (Isibaar)
14 :     * 31.12.2001 PMVfastSearch16 and PMVfastSearch8 (gruel)
15 :     * 30.12.2001 get_range/MotionSearchX simplified; blue/green bug fix
16 :     * 22.12.2001 commented best_point==99 check
17 :     * 19.12.2001 modified get_range (purple bug fix)
18 :     * 15.12.2001 moved pmv displacement from mbprediction
19 :     * 02.12.2001 motion estimation/compensation split (Isibaar)
20 :     * 16.11.2001 rewrote/tweaked search algorithms; pross@cs.rmit.edu.au
21 :     * 10.11.2001 support for sad16/sad8 functions
22 :     * 28.08.2001 reactivated MODE_INTER4V for EXT_MODE
23 :     * 24.08.2001 removed MODE_INTER4V_Q, disabled MODE_INTER4V for EXT_MODE
24 :     * 22.08.2001 added MODE_INTER4V_Q
25 :     * 20.08.2001 added pragma to get rid of internal compiler error with VC6
26 :     * idea by Cyril. Thanks.
27 :     *
28 :     * Michael Militzer <isibaar@videocoding.de>
29 :     *
30 :     **************************************************************************/
31 :    
32 :     #include <assert.h>
33 :     #include <stdio.h>
34 :    
35 :     #include "../encoder.h"
36 :     #include "../utils/mbfunctions.h"
37 :     #include "../prediction/mbprediction.h"
38 :     #include "../global.h"
39 :     #include "../utils/timer.h"
40 :     #include "sad.h"
41 :    
42 :     // very large value
43 :     #define MV_MAX_ERROR (4096 * 256)
44 :    
45 :     // stop search if sdelta < THRESHOLD
46 :     #define MV16_THRESHOLD 192
47 :     #define MV8_THRESHOLD 56
48 :    
49 :     /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */
50 :     /* nb = vop pixels * 2^(bpp-8) */
51 :     #define MV16_00_BIAS (128+1)
52 :    
53 :     /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */
54 :     #define INTER_BIAS 512
55 :    
56 :     /* Parameters which control inter/inter4v decision */
57 :     #define IMV16X16 5
58 :    
59 :     /* vector map (vlc delta size) smoother parameters */
60 :     #define NEIGH_TEND_16X16 2
61 :     #define NEIGH_TEND_8X8 2
62 :    
63 :    
64 :     // fast ((A)/2)*2
65 :     #define EVEN(A) (((A)<0?(A)+1:(A)) & ~1)
66 :    
67 :    
68 :     #define MIN(X, Y) ((X)<(Y)?(X):(Y))
69 :     #define MAX(X, Y) ((X)>(Y)?(X):(Y))
70 :     #define ABS(X) (((X)>0)?(X):-(X))
71 :     #define SIGN(X) (((X)>0)?1:-1)
72 :    
73 :    
74 :     int32_t PMVfastSearch8(
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 int start_x, int start_y,
82 :     const uint32_t iQuality,
83 :     MBParam * const pParam,
84 :     MACROBLOCK * const pMBs,
85 :     VECTOR * const currMV,
86 :     VECTOR * const currPMV);
87 :    
88 :     int32_t PMVfastSearch16(
89 :     const uint8_t * const pRef,
90 :     const uint8_t * const pRefH,
91 :     const uint8_t * const pRefV,
92 :     const uint8_t * const pRefHV,
93 :     const IMAGE * const pCur,
94 :     const int x, const int y,
95 :     const uint32_t iQuality,
96 :     MBParam * const pParam,
97 :     MACROBLOCK * const pMBs,
98 :     VECTOR * const currMV,
99 :     VECTOR * const currPMV);
100 :    
101 :    
102 :    
103 :     /* diamond search stuff
104 :     keep the the sequence in circular order (so optimization works)
105 :     */
106 :    
107 :     typedef struct
108 :     {
109 :     int32_t dx;
110 :     int32_t dy;
111 :     }
112 :     DPOINT;
113 :    
114 :    
115 :     static const DPOINT diamond_small[4] =
116 :     {
117 :     {0, 1}, {1, 0}, {0, -1}, {-1, 0}
118 :     };
119 :    
120 :    
121 :     static const DPOINT diamond_large[8] =
122 :     {
123 :     {0, 2}, {1, 1}, {2, 0}, {1, -1}, {0, -2}, {-1, -1}, {-2, 0}, {-1, 1}
124 :     };
125 :    
126 :    
127 :     // mv.length table
128 :     static const uint32_t mvtab[33] = {
129 :     1, 2, 3, 4, 6, 7, 7, 7,
130 :     9, 9, 9, 10, 10, 10, 10, 10,
131 :     10, 10, 10, 10, 10, 10, 10, 10,
132 :     10, 11, 11, 11, 11, 11, 11, 12, 12
133 :     };
134 :    
135 :    
136 :     static __inline uint32_t mv_bits(int32_t component, const uint32_t iFcode)
137 :     {
138 :     if (component == 0)
139 :     return 1;
140 :    
141 :     if (component < 0)
142 :     component = -component;
143 :    
144 :     if (iFcode == 1)
145 :     {
146 :     if (component > 32)
147 :     component = 32;
148 :    
149 :     return mvtab[component] + 1;
150 :     }
151 :    
152 :     component += (1 << (iFcode - 1)) - 1;
153 :     component >>= (iFcode - 1);
154 :    
155 :     if (component > 32)
156 :     component = 32;
157 :    
158 :     return mvtab[component] + 1 + iFcode - 1;
159 :     }
160 :    
161 :    
162 :     static __inline uint32_t calc_delta_16(const int32_t dx, const int32_t dy, const uint32_t iFcode)
163 :     {
164 :     return NEIGH_TEND_16X16 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));
165 :     }
166 :    
167 :     static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode)
168 :    
169 :     {
170 :     return NEIGH_TEND_8X8 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));
171 :     }
172 :    
173 :    
174 :    
175 :    
176 :     /* calculate the min/max range (in halfpixels)
177 :     relative to the _MACROBLOCK_ position
178 :     */
179 :    
180 :     static void __inline get_range(
181 :     int32_t * const min_dx, int32_t * const max_dx,
182 :     int32_t * const min_dy, int32_t * const max_dy,
183 :     const uint32_t x, const uint32_t y,
184 :     const uint32_t block_sz, // block dimension, 8 or 16
185 :     const uint32_t width, const uint32_t height,
186 :     const uint32_t fcode)
187 :     {
188 :     const int search_range = 32 << (fcode - 1);
189 :     const int high = search_range - 1;
190 :     const int low = -search_range;
191 :    
192 :     // convert full-pixel measurements to half pixel
193 :     const int hp_width = 2 * width;
194 :     const int hp_height = 2 * height;
195 :     const int hp_edge = 2 * block_sz;
196 :     const int hp_x = 2 * (x) * block_sz; // we need _right end_ of block, not x-coordinate
197 :     const int hp_y = 2 * (y) * block_sz; // same for _bottom end_
198 :    
199 :     *max_dx = MIN(high, hp_width - hp_x);
200 :     *max_dy = MIN(high, hp_height - hp_y);
201 :     *min_dx = MAX(low, -(hp_edge + hp_x));
202 :     *min_dy = MAX(low, -(hp_edge + hp_y));
203 :     }
204 :    
205 :    
206 :     /* getref: calculate reference image pointer
207 :     the decision to use interpolation h/v/hv or the normal image is
208 :     based on dx & dy.
209 :     */
210 :    
211 :     static __inline const uint8_t * get_ref(
212 :     const uint8_t * const refn,
213 :     const uint8_t * const refh,
214 :     const uint8_t * const refv,
215 :     const uint8_t * const refhv,
216 :     const uint32_t x, const uint32_t y,
217 :     const uint32_t block, // block dimension, 8 or 16
218 :     const int32_t dx, const int32_t dy,
219 :     const uint32_t stride)
220 :     {
221 :     switch ( ((dx&1)<<1) + (dy&1) ) // ((dx%2)?2:0)+((dy%2)?1:0)
222 :     {
223 :     case 0 : return refn + (x*block+dx/2) + (y*block+dy/2)*stride;
224 :     case 1 : return refv + (x*block+dx/2) + (y*block+(dy-1)/2)*stride;
225 :     case 2 : return refh + (x*block+(dx-1)/2) + (y*block+dy/2)*stride;
226 :     default :
227 :     case 3 : return refhv + (x*block+(dx-1)/2) + (y*block+(dy-1)/2)*stride;
228 :     }
229 :     }
230 :    
231 :    
232 :     /* This is somehow a copy of get_ref, but with MV instead of X,Y */
233 :    
234 :     static __inline const uint8_t * get_ref_mv(
235 :     const uint8_t * const refn,
236 :     const uint8_t * const refh,
237 :     const uint8_t * const refv,
238 :     const uint8_t * const refhv,
239 :     const uint32_t x, const uint32_t y,
240 :     const uint32_t block, // block dimension, 8 or 16
241 :     const VECTOR* mv, // measured in half-pel!
242 :     const uint32_t stride)
243 :     {
244 :     switch ( (((mv->x)&1)<<1) + ((mv->y)&1) )
245 :     {
246 :     case 0 : return refn + (x*block+(mv->x)/2) + (y*block+(mv->y)/2)*stride;
247 :     case 1 : return refv + (x*block+(mv->x)/2) + (y*block+((mv->y)-1)/2)*stride;
248 :     case 2 : return refh + (x*block+((mv->x)-1)/2) + (y*block+(mv->y)/2)*stride;
249 :     default :
250 :     case 3 : return refhv + (x*block+((mv->x)-1)/2) + (y*block+((mv->y)-1)/2)*stride;
251 :     }
252 :     }
253 :    
254 :     #ifndef SEARCH16
255 :     #define SEARCH16 PMVfastSearch16
256 :     #endif
257 :    
258 :     #ifndef SEARCH8
259 :     #define SEARCH8 PMVfastSearch8
260 :     #endif
261 :    
262 :     bool MotionEstimation(
263 :     MACROBLOCK * const pMBs,
264 :     MBParam * const pParam,
265 :     const IMAGE * const pRef,
266 :     const IMAGE * const pRefH,
267 :     const IMAGE * const pRefV,
268 :     const IMAGE * const pRefHV,
269 :     IMAGE * const pCurrent,
270 :     const uint32_t iLimit)
271 :    
272 :     {
273 :     const uint32_t iWcount = pParam->mb_width;
274 :     const uint32_t iHcount = pParam->mb_height;
275 :    
276 :     uint32_t i, j, iIntra = 0;
277 :    
278 :     VECTOR mv16;
279 :     VECTOR pmv16;
280 :    
281 :     int32_t sad8 = 0;
282 :     int32_t sad16;
283 :     int32_t deviation;
284 :    
285 :     // note: i==horizontal, j==vertical
286 :     for (i = 0; i < iHcount; i++)
287 :     for (j = 0; j < iWcount; j++)
288 :     {
289 :     MACROBLOCK *pMB = &pMBs[j + i * iWcount];
290 :    
291 :     sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
292 :     j, i, pParam->motion_flags,
293 :     pParam, pMBs, &mv16, &pmv16);
294 :     pMB->sad16=sad16;
295 :    
296 :    
297 :     /* decide: MODE_INTER or MODE_INTRA
298 :     if (dev_intra < sad_inter - 2 * nb) use_intra
299 :     */
300 :    
301 :     deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width);
302 :    
303 :     if (deviation < (sad16 - INTER_BIAS))
304 :     {
305 :     pMB->mode = MODE_INTRA;
306 :     pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;
307 :     pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;
308 :    
309 :     iIntra++;
310 :     if(iIntra >= iLimit)
311 :     return 1;
312 :    
313 :     continue;
314 :     }
315 :    
316 :     if (pParam->global_flags & XVID_INTER4V)
317 :     {
318 :     pMB->sad8[0] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
319 :     2 * j, 2 * i, mv16.x, mv16.y, pParam->motion_flags,
320 :     pParam, pMBs, &pMB->mvs[0], &pMB->pmvs[0]);
321 :    
322 :     pMB->sad8[1] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
323 :     2 * j + 1, 2 * i, mv16.x, mv16.y, pParam->motion_flags,
324 :     pParam, pMBs, &pMB->mvs[1], &pMB->pmvs[1]);
325 :    
326 :     pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
327 :     2 * j, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,
328 :     pParam, pMBs, &pMB->mvs[2], &pMB->pmvs[2]);
329 :    
330 :     pMB->sad8[3] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
331 :     2 * j + 1, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,
332 :     pParam, pMBs, &pMB->mvs[3], &pMB->pmvs[3]);
333 :    
334 :     sad8 = pMB->sad8[0] + pMB->sad8[1] + pMB->sad8[2] + pMB->sad8[3];
335 :     }
336 :    
337 :    
338 :     /* decide: MODE_INTER or MODE_INTER4V
339 :     mpeg4: if (sad8 < sad16 - nb/2+1) use_inter4v
340 :     */
341 :    
342 :     if (pMB->dquant == NO_CHANGE) {
343 :     if (((pParam->global_flags & XVID_INTER4V)==0) ||
344 :     (sad16 < (sad8 + (int32_t)(IMV16X16 * pParam->quant)))) {
345 :    
346 :     sad8 = sad16;
347 :     pMB->mode = MODE_INTER;
348 :     pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;
349 :     pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;
350 :     pMB->pmvs[0].x = pmv16.x;
351 :     pMB->pmvs[0].y = pmv16.y;
352 :     }
353 :     else
354 :     pMB->mode = MODE_INTER4V;
355 :     }
356 :     else
357 :     {
358 :     sad8 = sad16;
359 :     pMB->mode = MODE_INTER;
360 :     pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;
361 :     pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;
362 :     pMB->pmvs[0].x = pmv16.x;
363 :     pMB->pmvs[0].y = pmv16.y;
364 :     }
365 :     }
366 :    
367 :     return 0;
368 :     }
369 :    
370 :     #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )
371 :    
372 :     #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )
373 :    
374 :    
375 :     #define CHECK_MV16_ZERO {\
376 :     if ( (0 <= max_dx) && (0 >= min_dx) \
377 :     && (0 <= max_dy) && (0 >= min_dy) ) \
378 :     { \
379 :     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \
380 :     iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\
381 :     if (iSAD <= iQuant * 96) \
382 :     iSAD -= MV16_00_BIAS; \
383 :     if (iSAD < iMinSAD) \
384 :     { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } } \
385 :     }
386 :    
387 :    
388 :     #define CHECK_MV16_CANDIDATE(X,Y) { \
389 :     if ( ((X) <= max_dx) && ((X) >= min_dx) \
390 :     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
391 :     { \
392 :     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
393 :     iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\
394 :     if (iSAD < iMinSAD) \
395 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
396 :     }
397 :    
398 :     #define CHECK_MV16_CANDIDATE_DIR(X,Y,D) { \
399 :     if ( ((X) <= max_dx) && ((X) >= min_dx) \
400 :     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
401 :     { \
402 :     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
403 :     iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\
404 :     if (iSAD < iMinSAD) \
405 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
406 :     }
407 :    
408 :     #define CHECK_MV16_CANDIDATE_FOUND(X,Y,D) { \
409 :     if ( ((X) <= max_dx) && ((X) >= min_dx) \
410 :     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
411 :     { \
412 :     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
413 :     iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\
414 :     if (iSAD < iMinSAD) \
415 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
416 :     }
417 :    
418 :    
419 :     #define CHECK_MV8_ZERO {\
420 :     iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \
421 :     iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\
422 :     if (iSAD < iMinSAD) \
423 :     { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
424 :     }
425 :    
426 :    
427 :     #define CHECK_MV8_CANDIDATE(X,Y) { \
428 :     if ( ((X) <= max_dx) && ((X) >= min_dx) \
429 :     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
430 :     { \
431 :     iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
432 :     iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\
433 :     if (iSAD < iMinSAD) \
434 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
435 :     }
436 :    
437 :     #define CHECK_MV8_CANDIDATE_DIR(X,Y,D) { \
438 :     if ( ((X) <= max_dx) && ((X) >= min_dx) \
439 :     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
440 :     { \
441 :     iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
442 :     iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\
443 :     if (iSAD < iMinSAD) \
444 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
445 :     }
446 :    
447 :     #define CHECK_MV8_CANDIDATE_FOUND(X,Y,D) { \
448 :     if ( ((X) <= max_dx) && ((X) >= min_dx) \
449 :     && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
450 :     { \
451 :     iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
452 :     iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\
453 :     if (iSAD < iMinSAD) \
454 :     { iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
455 :     }
456 :    
457 :     /* too slow and not fully functional at the moment */
458 :     /*
459 :     int32_t ZeroSearch16(
460 :     const uint8_t * const pRef,
461 :     const uint8_t * const pRefH,
462 :     const uint8_t * const pRefV,
463 :     const uint8_t * const pRefHV,
464 :     const IMAGE * const pCur,
465 :     const int x, const int y,
466 :     const uint32_t MotionFlags,
467 :     MBParam * const pParam,
468 :     MACROBLOCK * const pMBs,
469 :     VECTOR * const currMV,
470 :     VECTOR * const currPMV)
471 :     {
472 :     const int32_t iEdgedWidth = pParam->edged_width;
473 :     const int32_t iQuant = pParam->quant;
474 :     const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
475 :     int32_t iSAD;
476 :     int32_t pred_x,pred_y;
477 :    
478 :     get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);
479 :    
480 :     iSAD = sad16( cur,
481 :     get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),
482 :     iEdgedWidth, MV_MAX_ERROR);
483 :     if (iSAD <= iQuant * 96)
484 :     iSAD -= MV16_00_BIAS;
485 :    
486 :     currMV->x = 0;
487 :     currMV->y = 0;
488 :     currPMV->x = -pred_x;
489 :     currPMV->y = -pred_y;
490 :    
491 :     return iSAD;
492 :    
493 :     }
494 :     */
495 :    
496 :     int32_t PMVfastSearch16_MainSearch(
497 :     const uint8_t * const pRef,
498 :     const uint8_t * const pRefH,
499 :     const uint8_t * const pRefV,
500 :     const uint8_t * const pRefHV,
501 :     const uint8_t * const cur,
502 :     const int x, const int y,
503 :     int32_t startx, int32_t starty,
504 :     int32_t iMinSAD,
505 :     VECTOR * const currMV,
506 :     const VECTOR * const pmv,
507 :     const int32_t min_dx, const int32_t max_dx,
508 :     const int32_t min_dy, const int32_t max_dy,
509 :     const int32_t iEdgedWidth,
510 :     const int32_t iDiamondSize,
511 :     const int32_t iFcode,
512 :     const int32_t iQuant,
513 :     int iFound)
514 :     {
515 :     /* Do a diamond search around given starting point, return SAD of best */
516 :    
517 :     int32_t iDirection=0;
518 :     int32_t iSAD;
519 :     VECTOR backupMV;
520 :     backupMV.x = startx;
521 :     backupMV.y = starty;
522 :    
523 :     /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
524 :    
525 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
526 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
527 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
528 :     CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
529 :    
530 :     if (iDirection)
531 :     while (!iFound)
532 :     {
533 :     iFound = 1;
534 :     backupMV=*currMV;
535 :    
536 :     if ( iDirection != 2)
537 :     CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
538 :     if ( iDirection != 1)
539 :     CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);
540 :     if ( iDirection != 4)
541 :     CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);
542 :     if ( iDirection != 3)
543 :     CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);
544 :     }
545 :     else
546 :     {
547 :     currMV->x = startx;
548 :     currMV->y = starty;
549 :     }
550 :     return iMinSAD;
551 :     }
552 :    
553 :     int32_t PMVfastSearch16_Refine(
554 :     const uint8_t * const pRef,
555 :     const uint8_t * const pRefH,
556 :     const uint8_t * const pRefV,
557 :     const uint8_t * const pRefHV,
558 :     const uint8_t * const cur,
559 :     const int x, const int y,
560 :     VECTOR * const currMV,
561 :     int32_t iMinSAD,
562 :     const VECTOR * const pmv,
563 :     const int32_t min_dx, const int32_t max_dx,
564 :     const int32_t min_dy, const int32_t max_dy,
565 :     const int32_t iFcode,
566 :     const int32_t iQuant,
567 :     const int32_t iEdgedWidth)
568 :     {
569 :     /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
570 :    
571 :     int32_t iSAD;
572 :     VECTOR backupMV = *currMV;
573 :    
574 :     CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y-1);
575 :     CHECK_MV16_CANDIDATE(backupMV.x ,backupMV.y-1);
576 :     CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y-1);
577 :     CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y);
578 :     CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y);
579 :     CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y+1);
580 :     CHECK_MV16_CANDIDATE(backupMV.x ,backupMV.y+1);
581 :     CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y+1);
582 :    
583 :     return iMinSAD;
584 :     }
585 :    
586 :     #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
587 :    
588 :     int32_t PMVfastSearch16(
589 :     const uint8_t * const pRef,
590 :     const uint8_t * const pRefH,
591 :     const uint8_t * const pRefV,
592 :     const uint8_t * const pRefHV,
593 :     const IMAGE * const pCur,
594 :     const int x, const int y,
595 :     const uint32_t MotionFlags,
596 :     MBParam * const pParam,
597 :     MACROBLOCK * const pMBs,
598 :     VECTOR * const currMV,
599 :     VECTOR * const currPMV)
600 :     {
601 :     const uint32_t iWcount = pParam->mb_width;
602 :     const int32_t iFcode = pParam->fixed_code;
603 :     const int32_t iQuant = pParam->quant;
604 :     const int32_t iWidth = pParam->width;
605 :     const int32_t iHeight = pParam->height;
606 :     const int32_t iEdgedWidth = pParam->edged_width;
607 :    
608 :     const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
609 :    
610 :     int32_t iDiamondSize;
611 :    
612 :     int32_t min_dx;
613 :     int32_t max_dx;
614 :     int32_t min_dy;
615 :     int32_t max_dy;
616 :    
617 :     int32_t iFound;
618 :    
619 :     VECTOR newMV;
620 :     VECTOR backupMV; /* just for PMVFAST */
621 :    
622 :     VECTOR pmv[4];
623 :     int32_t psad[4];
624 :    
625 :     MACROBLOCK * const pMB = pMBs + x + y * iWcount;
626 :    
627 :     static int32_t threshA,threshB;
628 :     int32_t bPredEq;
629 :     int32_t iMinSAD,iSAD;
630 :    
631 :     /* Get maximum range */
632 :     get_range(&min_dx, &max_dx, &min_dy, &max_dy,
633 :     x, y, 16, iWidth, iHeight, iFcode);
634 :    
635 :     /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
636 :    
637 :     if (!(MotionFlags & PMV_HALFPEL16 ))
638 :     { min_dx = EVEN(min_dx);
639 :     max_dx = EVEN(max_dx);
640 :     min_dy = EVEN(min_dy);
641 :     max_dy = EVEN(max_dy);
642 :     } /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
643 :    
644 :    
645 :     bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
646 :    
647 :     if ((x==0) && (y==0) )
648 :     {
649 :     threshA = 512;
650 :     threshB = 1024;
651 :    
652 :     }
653 :     else
654 :     {
655 :     threshA = psad[0];
656 :     threshB = threshA+256;
657 :     if (threshA< 512) threshA = 512;
658 :     if (threshA>1024) threshA = 1024;
659 :     if (threshB>1792) threshB = 1792;
660 :     }
661 :    
662 :     iFound=0;
663 :    
664 :     /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
665 :     vector of the median.
666 :     If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
667 :     */
668 :    
669 :     if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[0]) ) )
670 :     iFound=2;
671 :    
672 :     /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
673 :     Otherwise select large Diamond Search.
674 :     */
675 :    
676 :     if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536) || (bPredEq) )
677 :     iDiamondSize=1; // halfpel!
678 :     else
679 :     iDiamondSize=2; // halfpel!
680 :    
681 :     if (!(MotionFlags & PMV_HALFPELDIAMOND16) )
682 :     iDiamondSize*=2;
683 :    
684 :     /* Step 4: Calculate SAD around the Median prediction.
685 :     MinSAD=SAD
686 :     If Motion Vector equal to Previous frame motion vector
687 :     and MinSAD<PrevFrmSAD goto Step 10.
688 :     If SAD<=256 goto Step 10.
689 :     */
690 :    
691 :    
692 :     // Prepare for main loop
693 :    
694 :     *currMV=pmv[0]; /* current best := prediction */
695 :     if (!(MotionFlags & PMV_HALFPEL16 ))
696 :     { /* This should NOT be necessary! */
697 :     currMV->x = EVEN(currMV->x);
698 :     currMV->y = EVEN(currMV->y);
699 :     }
700 :    
701 :     if (currMV->x > max_dx)
702 :     {
703 :     currMV->x=max_dx;
704 :     }
705 :     if (currMV->x < min_dx)
706 :     {
707 :     currMV->x=min_dx;
708 :     }
709 :     if (currMV->y > max_dy)
710 :     {
711 :     currMV->y=max_dy;
712 :     }
713 :     if (currMV->y < min_dy)
714 :     {
715 :     currMV->y=min_dy;
716 :     }
717 :    
718 :     iMinSAD = sad16( cur,
719 :     get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
720 :     iEdgedWidth, MV_MAX_ERROR);
721 :     iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;
722 :    
723 :     if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )
724 :     {
725 :    
726 :     if (MotionFlags & PMV_QUICKSTOP16)
727 :     goto step10b;
728 :     if (MotionFlags & PMV_EARLYSTOP16)
729 :     goto step10;
730 :     }
731 :    
732 :     /*
733 :     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
734 :     Also calculate (0,0) but do not subtract offset.
735 :     Let MinSAD be the smallest SAD up to this point.
736 :     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********
737 :     */
738 :    
739 :     // (0,0) is always possible
740 :    
741 :     CHECK_MV16_ZERO;
742 :    
743 :     // previous frame MV is always possible
744 :     CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);
745 :    
746 :     // left neighbour, if allowed
747 :     if (x != 0)
748 :     {
749 :     if (!(MotionFlags & PMV_HALFPEL16 ))
750 :     { pmv[1].x = EVEN(pmv[1].x);
751 :     pmv[1].y = EVEN(pmv[1].y);
752 :     }
753 :     CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
754 :     }
755 :    
756 :     // top neighbour, if allowed
757 :     if (y != 0)
758 :     {
759 :     if (!(MotionFlags & PMV_HALFPEL16 ))
760 :     { pmv[2].x = EVEN(pmv[2].x);
761 :     pmv[2].y = EVEN(pmv[2].y);
762 :     }
763 :     CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
764 :    
765 :     // top right neighbour, if allowed
766 :     if (x != (iWcount-1))
767 :     {
768 :     if (!(MotionFlags & PMV_HALFPEL16 ))
769 :     { pmv[3].x = EVEN(pmv[3].x);
770 :     pmv[3].y = EVEN(pmv[3].y);
771 :     }
772 :     CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
773 :     }
774 :     }
775 :    
776 :     /* Step 6: If MinSAD <= thresa goto Step 10.
777 :     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
778 :     */
779 :    
780 :     if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )
781 :     {
782 :     if (MotionFlags & PMV_QUICKSTOP16)
783 :     goto step10b;
784 :     if (MotionFlags & PMV_EARLYSTOP16)
785 :     goto step10;
786 :     }
787 :    
788 :    
789 :     /************ (Diamond Search) **************/
790 :     /*
791 :     Step 7: Perform Diamond search, with either the small or large diamond.
792 :     If Found=2 only examine one Diamond pattern, and afterwards goto step 10
793 :     Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
794 :     If center then goto step 10.
795 :     Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
796 :     Refine by using small diamond and goto step 10.
797 :     */
798 :    
799 :     backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
800 :    
801 :     /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
802 :     iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
803 :     x, y,
804 :     currMV->x, currMV->y, iMinSAD, &newMV,
805 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
806 :    
807 :     if (iSAD < iMinSAD)
808 :     {
809 :     *currMV = newMV;
810 :     iMinSAD = iSAD;
811 :     }
812 :    
813 :     if (MotionFlags & PMV_EXTSEARCH16)
814 :     {
815 :     /* extended: search (up to) two more times: orignal prediction and (0,0) */
816 :    
817 :     if (!(MVequal(pmv[0],backupMV)) )
818 :     { iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
819 :     x, y,
820 :     pmv[0].x, pmv[0].y, iMinSAD, &newMV,
821 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
822 :    
823 :     if (iSAD < iMinSAD)
824 :     {
825 :     *currMV = newMV;
826 :     iMinSAD = iSAD;
827 :     }
828 :     }
829 :    
830 :     if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
831 :     { iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
832 :     x, y,
833 :     0, 0, iMinSAD, &newMV,
834 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
835 :    
836 :     if (iSAD < iMinSAD)
837 :     {
838 :     *currMV = newMV;
839 :     iMinSAD = iSAD;
840 :     }
841 :     }
842 :     }
843 :    
844 :     /*
845 :     Step 10: The motion vector is chosen according to the block corresponding to MinSAD.
846 :     */
847 :    
848 :     step10:
849 :     if (MotionFlags & PMV_HALFPELREFINE16) // perform final half-pel step
850 :     iMinSAD = PMVfastSearch16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
851 :     x, y,
852 :     currMV, iMinSAD,
853 :     pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
854 :    
855 :     step10b:
856 :     currPMV->x = currMV->x - pmv[0].x;
857 :     currPMV->y = currMV->y - pmv[0].y;
858 :     return iMinSAD;
859 :     }
860 :    
861 :    
862 :    
863 :    
864 :    
865 :    
866 :     int32_t PMVfastSearch8_MainSearch(
867 :     const uint8_t * const pRef,
868 :     const uint8_t * const pRefH,
869 :     const uint8_t * const pRefV,
870 :     const uint8_t * const pRefHV,
871 :     const uint8_t * const cur,
872 :     const int x, const int y,
873 :     int32_t startx, int32_t starty,
874 :     int32_t iMinSAD,
875 :     VECTOR * const currMV,
876 :     const VECTOR * const pmv,
877 :     const int32_t min_dx, const int32_t max_dx,
878 :     const int32_t min_dy, const int32_t max_dy,
879 :     const int32_t iEdgedWidth,
880 :     const int32_t iDiamondSize,
881 :     const int32_t iFcode,
882 :     const int32_t iQuant,
883 :     int iFound)
884 :     {
885 :     /* Do a diamond search around given starting point, return SAD of best */
886 :    
887 :     int32_t iDirection=0;
888 :     int32_t iSAD;
889 :     VECTOR backupMV;
890 :     backupMV.x = startx;
891 :     backupMV.y = starty;
892 :    
893 :     /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
894 :    
895 :     CHECK_MV8_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
896 :     CHECK_MV8_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
897 :     CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
898 :     CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
899 :    
900 :     if (iDirection)
901 :     while (!iFound)
902 :     {
903 :     iFound = 1;
904 :     backupMV=*currMV; // since iDirection!=0, this is well defined!
905 :    
906 :     if ( iDirection != 2)
907 :     CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
908 :     if ( iDirection != 1)
909 :     CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);
910 :     if ( iDirection != 4)
911 :     CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);
912 :     if ( iDirection != 3)
913 :     CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);
914 :     }
915 :     else
916 :     {
917 :     currMV->x = startx;
918 :     currMV->y = starty;
919 :     }
920 :     return iMinSAD;
921 :     }
922 :    
923 :     int32_t PMVfastSearch8_Refine(
924 :     const uint8_t * const pRef,
925 :     const uint8_t * const pRefH,
926 :     const uint8_t * const pRefV,
927 :     const uint8_t * const pRefHV,
928 :     const uint8_t * const cur,
929 :     const int x, const int y,
930 :     VECTOR * const currMV,
931 :     int32_t iMinSAD,
932 :     const VECTOR * const pmv,
933 :     const int32_t min_dx, const int32_t max_dx,
934 :     const int32_t min_dy, const int32_t max_dy,
935 :     const int32_t iFcode,
936 :     const int32_t iQuant,
937 :     const int32_t iEdgedWidth)
938 :     {
939 :     /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
940 :    
941 :     int32_t iSAD;
942 :     VECTOR backupMV = *currMV;
943 :    
944 :     CHECK_MV8_CANDIDATE(backupMV.x-1,backupMV.y-1);
945 :     CHECK_MV8_CANDIDATE(backupMV.x ,backupMV.y-1);
946 :     CHECK_MV8_CANDIDATE(backupMV.x+1,backupMV.y-1);
947 :     CHECK_MV8_CANDIDATE(backupMV.x-1,backupMV.y);
948 :     CHECK_MV8_CANDIDATE(backupMV.x+1,backupMV.y);
949 :     CHECK_MV8_CANDIDATE(backupMV.x-1,backupMV.y+1);
950 :     CHECK_MV8_CANDIDATE(backupMV.x ,backupMV.y+1);
951 :     CHECK_MV8_CANDIDATE(backupMV.x+1,backupMV.y+1);
952 :    
953 :     return iMinSAD;
954 :     }
955 :    
956 :    
957 :     #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
958 :    
959 :     int32_t PMVfastSearch8(
960 :     const uint8_t * const pRef,
961 :     const uint8_t * const pRefH,
962 :     const uint8_t * const pRefV,
963 :     const uint8_t * const pRefHV,
964 :     const IMAGE * const pCur,
965 :     const int x, const int y,
966 :     const int start_x, int start_y,
967 :     const uint32_t MotionFlags,
968 :     MBParam * const pParam,
969 :     MACROBLOCK * const pMBs,
970 :     VECTOR * const currMV,
971 :     VECTOR * const currPMV)
972 :     {
973 :     const uint32_t iWcount = pParam->mb_width;
974 :    
975 :     const int32_t iFcode = pParam->fixed_code;
976 :     const int32_t iQuant = pParam->quant;
977 :     const int32_t iWidth = pParam->width;
978 :     const int32_t iHeight = pParam->height;
979 :     const int32_t iEdgedWidth = pParam->edged_width;
980 :    
981 :     const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;
982 :    
983 :     int32_t iDiamondSize;
984 :    
985 :     int32_t min_dx;
986 :     int32_t max_dx;
987 :     int32_t min_dy;
988 :     int32_t max_dy;
989 :    
990 :     VECTOR pmv[4];
991 :     int32_t psad[4];
992 :     VECTOR newMV;
993 :     VECTOR backupMV;
994 :    
995 :     MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
996 :    
997 :     static int32_t threshA,threshB;
998 :     int32_t iFound,bPredEq;
999 :     int32_t iMinSAD,iSAD;
1000 :    
1001 :     int32_t iSubBlock = ((y&1)<<1) + (x&1);
1002 :    
1003 :     /* Get maximum range */
1004 :     get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1005 :     x, y, 8, iWidth, iHeight, iFcode);
1006 :    
1007 :     /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */
1008 :    
1009 :     if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))
1010 :     { min_dx = EVEN(min_dx);
1011 :     max_dx = EVEN(max_dx);
1012 :     min_dy = EVEN(min_dy);
1013 :     max_dy = EVEN(max_dy);
1014 :     } /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
1015 :    
1016 :    
1017 :     bPredEq = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);
1018 :    
1019 :     if ((x==0) && (y==0) )
1020 :     {
1021 :     threshA = 512/4;
1022 :     threshB = 1024/4;
1023 :    
1024 :     }
1025 :     else
1026 :     {
1027 :     threshA = psad[0]/4; /* good estimate */
1028 :     threshB = threshA+256/4;
1029 :     if (threshA< 512/4) threshA = 512/4;
1030 :     if (threshA>1024/4) threshA = 1024/4;
1031 :     if (threshB>1792/4) threshB = 1792/4;
1032 :     }
1033 :    
1034 :     iFound=0;
1035 :    
1036 :     /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1037 :     vector of the median.
1038 :     If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1039 :     */
1040 :    
1041 :     if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[iSubBlock]) ) )
1042 :     iFound=2;
1043 :    
1044 :     /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1045 :     Otherwise select large Diamond Search.
1046 :     */
1047 :    
1048 :     if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536/4) || (bPredEq) )
1049 :     iDiamondSize=1; // 1 halfpel!
1050 :     else
1051 :     iDiamondSize=2; // 2 halfpel = 1 full pixel!
1052 :    
1053 :     if (!(MotionFlags & PMV_HALFPELDIAMOND8) )
1054 :     iDiamondSize*=2;
1055 :    
1056 :     /* Step 4: Calculate SAD around the Median prediction.
1057 :     MinSAD=SAD
1058 :     If Motion Vector equal to Previous frame motion vector
1059 :     and MinSAD<PrevFrmSAD goto Step 10.
1060 :     If SAD<=256 goto Step 10.
1061 :     */
1062 :    
1063 :    
1064 :     // Prepare for main loop
1065 :    
1066 :     currMV->x=start_x; /* start with mv16 */
1067 :     currMV->y=start_y;
1068 :    
1069 :     iMinSAD = sad8( cur,
1070 :     get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
1071 :     iEdgedWidth);
1072 :     iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode) * iQuant;
1073 :    
1074 :     if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && (iMinSAD < pMB->sad8[iSubBlock]) ) )
1075 :     {
1076 :     if (MotionFlags & PMV_QUICKSTOP8)
1077 :     goto step10_8b;
1078 :     if (MotionFlags & PMV_EARLYSTOP8)
1079 :     goto step10_8;
1080 :     }
1081 :    
1082 :     /*
1083 :     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
1084 :     Also calculate (0,0) but do not subtract offset.
1085 :     Let MinSAD be the smallest SAD up to this point.
1086 :     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********
1087 :     */
1088 :    
1089 :     // the prediction might be even better than mv16
1090 :     CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);
1091 :    
1092 :     // (0,0) is always possible
1093 :     CHECK_MV8_ZERO;
1094 :    
1095 :     // previous frame MV is always possible
1096 :     CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);
1097 :    
1098 :     // left neighbour, if allowed
1099 :     if (psad[1] != MV_MAX_ERROR)
1100 :     {
1101 :     if (!(MotionFlags & PMV_HALFPEL8 ))
1102 :     { pmv[1].x = EVEN(pmv[1].x);
1103 :     pmv[1].y = EVEN(pmv[1].y);
1104 :     }
1105 :     CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1106 :     }
1107 :    
1108 :     // top neighbour, if allowed
1109 :     if (psad[2] != MV_MAX_ERROR)
1110 :     {
1111 :     if (!(MotionFlags & PMV_HALFPEL8 ))
1112 :     { pmv[2].x = EVEN(pmv[2].x);
1113 :     pmv[2].y = EVEN(pmv[2].y);
1114 :     }
1115 :     CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1116 :    
1117 :     // top right neighbour, if allowed
1118 :     if (psad[3] != MV_MAX_ERROR)
1119 :     {
1120 :     if (!(MotionFlags & PMV_HALFPEL8 ))
1121 :     { pmv[3].x = EVEN(pmv[3].x);
1122 :     pmv[3].y = EVEN(pmv[3].y);
1123 :     }
1124 :     CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);
1125 :     }
1126 :     }
1127 :    
1128 :     /* Step 6: If MinSAD <= thresa goto Step 10.
1129 :     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
1130 :     */
1131 :    
1132 :     if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && (iMinSAD < pMB->sad8[iSubBlock]) ) )
1133 :     {
1134 :     if (MotionFlags & PMV_QUICKSTOP8)
1135 :     goto step10_8b;
1136 :     if (MotionFlags & PMV_EARLYSTOP8)
1137 :     goto step10_8;
1138 :     }
1139 :    
1140 :     /************ (Diamond Search) **************/
1141 :     /*
1142 :     Step 7: Perform Diamond search, with either the small or large diamond.
1143 :     If Found=2 only examine one Diamond pattern, and afterwards goto step 10
1144 :     Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
1145 :     If center then goto step 10.
1146 :     Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
1147 :     Refine by using small diamond and goto step 10.
1148 :     */
1149 :    
1150 :     backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1151 :    
1152 :     /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1153 :     iSAD = PMVfastSearch8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1154 :     x, y,
1155 :     currMV->x, currMV->y, iMinSAD, &newMV,
1156 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
1157 :    
1158 :     if (iSAD < iMinSAD)
1159 :     {
1160 :     *currMV = newMV;
1161 :     iMinSAD = iSAD;
1162 :     }
1163 :    
1164 :     if (MotionFlags & PMV_EXTSEARCH8)
1165 :     {
1166 :     /* extended: search (up to) two more times: orignal prediction and (0,0) */
1167 :    
1168 :     if (!(MVequal(pmv[0],backupMV)) )
1169 :     { iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1170 :     x, y,
1171 :     pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1172 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
1173 :    
1174 :     if (iSAD < iMinSAD)
1175 :     {
1176 :     *currMV = newMV;
1177 :     iMinSAD = iSAD;
1178 :     }
1179 :     }
1180 :    
1181 :     if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1182 :     { iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1183 :     x, y,
1184 :     0, 0, iMinSAD, &newMV,
1185 :     pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
1186 :    
1187 :     if (iSAD < iMinSAD)
1188 :     {
1189 :     *currMV = newMV;
1190 :     iMinSAD = iSAD;
1191 :     }
1192 :     }
1193 :     }
1194 :    
1195 :     /* Step 10: The motion vector is chosen according to the block corresponding to MinSAD.
1196 :     By performing an optional local half-pixel search, we can refine this result even further.
1197 :     */
1198 :    
1199 :     step10_8:
1200 :     if (MotionFlags & PMV_HALFPELREFINE8) // perform final half-pel step
1201 :     iMinSAD = PMVfastSearch8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1202 :     x, y,
1203 :     currMV, iMinSAD,
1204 :     pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1205 :    
1206 :     step10_8b:
1207 :    
1208 :     currPMV->x = currMV->x - pmv[0].x;
1209 :     currPMV->y = currMV->y - pmv[0].y;
1210 :    
1211 :     return iMinSAD;
1212 :     }

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