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

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

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