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

Diff of /trunk/xvidcore/src/motion/motion_est.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 78, Thu Mar 28 20:57:25 2002 UTC revision 140, Thu Apr 25 21:32:05 2002 UTC
# Line 2  Line 2 
2   *   *
3   *  Modifications:   *  Modifications:
4   *   *
5     *      25.04.2002 partial prevMB conversion
6     *  22.04.2002 remove some compile warning by chenm001 <chenm001@163.com>
7     *  14.04.2002 added MotionEstimationBVOP()
8     *  02.04.2002 add EPZS(^2) as ME algorithm, use PMV_USESQUARES to choose between
9     *             EPZS and EPZS^2
10   *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop   *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop
11   *             PMVFast_Refine to support multiple searches with different start points   *             PMVFast_Refine to support multiple searches with different start points
12   *  07.01.2002 uv-block-based interpolation   *  07.01.2002 uv-block-based interpolation
# Line 31  Line 36 
36    
37  #include <assert.h>  #include <assert.h>
38  #include <stdio.h>  #include <stdio.h>
39    #include <stdlib.h>
40    
41  #include "../encoder.h"  #include "../encoder.h"
42  #include "../utils/mbfunctions.h"  #include "../utils/mbfunctions.h"
43  #include "../prediction/mbprediction.h"  #include "../prediction/mbprediction.h"
44  #include "../global.h"  #include "../global.h"
45  #include "../utils/timer.h"  #include "../utils/timer.h"
46    #include "motion.h"
47  #include "sad.h"  #include "sad.h"
48    
49  // very large value  // very large value
# Line 49  Line 56 
56  /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */  /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */
57  /* nb  = vop pixels * 2^(bpp-8) */  /* nb  = vop pixels * 2^(bpp-8) */
58  #define MV16_00_BIAS    (128+1)  #define MV16_00_BIAS    (128+1)
59    #define MV8_00_BIAS     (0)
60    
61  /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */  /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */
62  #define INTER_BIAS      512  #define INTER_BIAS      512
# Line 65  Line 73 
73  #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)  #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)
74    
75    
76  #define MIN(X, Y) ((X)<(Y)?(X):(Y))  int32_t PMVfastSearch16(
 #define MAX(X, Y) ((X)>(Y)?(X):(Y))  
 #define ABS(X)    (((X)>0)?(X):-(X))  
 #define SIGN(X)   (((X)>0)?1:-1)  
   
   
 int32_t PMVfastSearch8(  
77          const uint8_t * const pRef,          const uint8_t * const pRef,
78          const uint8_t * const pRefH,          const uint8_t * const pRefH,
79          const uint8_t * const pRefV,          const uint8_t * const pRefV,
80          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
81          const IMAGE * const pCur,          const IMAGE * const pCur,
82          const int x, const int y,          const int x, const int y,
83          const int start_x, int start_y,                                          const uint32_t MotionFlags,
84          const uint32_t iQuality,                                          const uint32_t iQuant,
85          MBParam * const pParam,                                          const uint32_t iFcode,
86          MACROBLOCK * const pMBs,                                          const MBParam * const pParam,
87                                            const MACROBLOCK * const pMBs,
88                                            const MACROBLOCK * const prevMBs,
89          VECTOR * const currMV,          VECTOR * const currMV,
90          VECTOR * const currPMV);          VECTOR * const currPMV);
91    
92  int32_t PMVfastSearch16(  int32_t EPZSSearch16(
93          const uint8_t * const pRef,          const uint8_t * const pRef,
94          const uint8_t * const pRefH,          const uint8_t * const pRefH,
95          const uint8_t * const pRefV,          const uint8_t * const pRefV,
96          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
97          const IMAGE * const pCur,          const IMAGE * const pCur,
98          const int x, const int y,          const int x, const int y,
99          const uint32_t iQuality,                                          const uint32_t MotionFlags,
100          MBParam * const pParam,                                          const uint32_t iQuant,
101          MACROBLOCK * const pMBs,                                          const uint32_t iFcode,
102                                            const MBParam * const pParam,
103                                            const MACROBLOCK * const pMBs,
104                                            const MACROBLOCK * const prevMBs,
105          VECTOR * const currMV,          VECTOR * const currMV,
106          VECTOR * const currPMV);          VECTOR * const currPMV);
107    
108    
109    int32_t PMVfastSearch8(
110                                            const uint8_t * const pRef,
111                                            const uint8_t * const pRefH,
112                                            const uint8_t * const pRefV,
113                                            const uint8_t * const pRefHV,
114                                            const IMAGE * const pCur,
115                                            const int x, const int y,
116                                            const int start_x, const int start_y,
117                                            const uint32_t MotionFlags,
118                                            const uint32_t iQuant,
119                                            const uint32_t iFcode,
120                                            const MBParam * const pParam,
121                                            const MACROBLOCK * const pMBs,
122                                            const MACROBLOCK * const prevMBs,
123                                            VECTOR * const currMV,
124                                            VECTOR * const currPMV);
125    
126  /*  int32_t EPZSSearch8(
127   * diamond search stuff                                          const uint8_t * const pRef,
128   * keep the the sequence in circular order (so optimization works)                                          const uint8_t * const pRefH,
129   */                                          const uint8_t * const pRefV,
130                                            const uint8_t * const pRefHV,
131                                            const IMAGE * const pCur,
132                                            const int x, const int y,
133                                            const int start_x, const int start_y,
134                                            const uint32_t MotionFlags,
135                                            const uint32_t iQuant,
136                                            const uint32_t iFcode,
137                                            const MBParam * const pParam,
138                                            const MACROBLOCK * const pMBs,
139                                            const MACROBLOCK * const prevMBs,
140                                            VECTOR * const currMV,
141                                            VECTOR * const currPMV);
142    
 typedef struct  
 {  
         int32_t dx;  
         int32_t dy;  
 }  
 DPOINT;  
143    
144    typedef int32_t (MainSearch16Func)(
145            const uint8_t * const pRef,
146            const uint8_t * const pRefH,
147            const uint8_t * const pRefV,
148            const uint8_t * const pRefHV,
149            const uint8_t * const cur,
150            const int x, const int y,
151            int32_t startx, int32_t starty,
152            int32_t iMinSAD,
153            VECTOR * const currMV,
154            const VECTOR * const pmv,
155            const int32_t min_dx, const int32_t max_dx,
156            const int32_t min_dy, const int32_t max_dy,
157            const int32_t iEdgedWidth,
158            const int32_t iDiamondSize,
159            const int32_t iFcode,
160            const int32_t iQuant,
161            int iFound);
162    
163  static const DPOINT diamond_small[4] =  typedef MainSearch16Func* MainSearch16FuncPtr;
 {  
         {0, 1}, {1, 0}, {0, -1}, {-1, 0}  
 };  
164    
165    
166  static const DPOINT diamond_large[8] =  typedef int32_t (MainSearch8Func)(
167  {          const uint8_t * const pRef,
168          {0, 2}, {1, 1}, {2, 0}, {1, -1}, {0, -2}, {-1, -1}, {-2, 0}, {-1, 1}          const uint8_t * const pRefH,
169  };          const uint8_t * const pRefV,
170            const uint8_t * const pRefHV,
171            const uint8_t * const cur,
172            const int x, const int y,
173            int32_t startx, int32_t starty,
174            int32_t iMinSAD,
175            VECTOR * const currMV,
176            const VECTOR * const pmv,
177            const int32_t min_dx, const int32_t max_dx,
178            const int32_t min_dy, const int32_t max_dy,
179            const int32_t iEdgedWidth,
180            const int32_t iDiamondSize,
181            const int32_t iFcode,
182            const int32_t iQuant,
183            int iFound);
184    
185    typedef MainSearch8Func* MainSearch8FuncPtr;
186    
187  // mv.length table  // mv.length table
188  static const uint32_t mvtab[33] = {  static const uint32_t mvtab[33] = {
# Line 174  Line 233 
233    
234    
235    
 /* calculate the min/max range (in halfpixels)  
         relative to the _MACROBLOCK_ position  
 */  
   
 static void __inline get_range(  
         int32_t * const min_dx, int32_t * const max_dx,  
         int32_t * const min_dy, int32_t * const max_dy,  
         const uint32_t x, const uint32_t y,  
         const uint32_t block_sz,                                        // block dimension, 8 or 16  
         const uint32_t width, const uint32_t height,  
         const uint32_t fcode)  
 {  
   
         const int search_range = 32 << (fcode - 1);  
         const int high = search_range - 1;  
         const int low = -search_range;  
   
         // convert full-pixel measurements to half pixel  
         const int hp_width = 2 * width;  
         const int hp_height = 2 * height;  
         const int hp_edge = 2 * block_sz;  
         const int hp_x = 2 * (x) * block_sz;            // we need _right end_ of block, not x-coordinate  
         const int hp_y = 2 * (y) * block_sz;            // same for _bottom end_  
   
         *max_dx = MIN(high,     hp_width - hp_x);  
         *max_dy = MIN(high,     hp_height - hp_y);  
         *min_dx = MAX(low,      -(hp_edge + hp_x));  
         *min_dy = MAX(low,      -(hp_edge + hp_y));  
   
 }  
   
   
 /*  
  * getref: calculate reference image pointer  
  * the decision to use interpolation h/v/hv or the normal image is  
  * based on dx & dy.  
  */  
   
 static __inline const uint8_t * get_ref(  
         const uint8_t * const refn,  
         const uint8_t * const refh,  
         const uint8_t * const refv,  
         const uint8_t * const refhv,  
         const uint32_t x, const uint32_t y,  
         const uint32_t block,                                   // block dimension, 8 or 16  
         const int32_t dx, const int32_t dy,  
         const uint32_t stride)  
 {  
   
         switch ( ((dx&1)<<1) + (dy&1) )         // ((dx%2)?2:0)+((dy%2)?1:0)  
         {  
         case 0  : return refn + (x*block+dx/2) + (y*block+dy/2)*stride;  
         case 1  : return refv + (x*block+dx/2) + (y*block+(dy-1)/2)*stride;  
         case 2  : return refh + (x*block+(dx-1)/2) + (y*block+dy/2)*stride;  
         default :  
         case 3  : return refhv + (x*block+(dx-1)/2) + (y*block+(dy-1)/2)*stride;  
         }  
   
 }  
   
   
 /* This is somehow a copy of get_ref, but with MV instead of X,Y */  
   
 static __inline const uint8_t * get_ref_mv(  
         const uint8_t * const refn,  
         const uint8_t * const refh,  
         const uint8_t * const refv,  
         const uint8_t * const refhv,  
         const uint32_t x, const uint32_t y,  
         const uint32_t block,                   // block dimension, 8 or 16  
         const VECTOR* mv,       // measured in half-pel!  
         const uint32_t stride)  
 {  
   
         switch ( (((mv->x)&1)<<1) + ((mv->y)&1) )  
         {  
         case 0  : return refn + (x*block+(mv->x)/2) + (y*block+(mv->y)/2)*stride;  
         case 1  : return refv + (x*block+(mv->x)/2) + (y*block+((mv->y)-1)/2)*stride;  
         case 2  : return refh + (x*block+((mv->x)-1)/2) + (y*block+(mv->y)/2)*stride;  
         default :  
         case 3  : return refhv + (x*block+((mv->x)-1)/2) + (y*block+((mv->y)-1)/2)*stride;  
         }  
   
 }  
236    
237  #ifndef SEARCH16  #ifndef SEARCH16
238  #define SEARCH16        PMVfastSearch16  #define SEARCH16        PMVfastSearch16
239    //#define SEARCH16      FullSearch16
240    //#define SEARCH16      EPZSSearch16
241  #endif  #endif
242    
243  #ifndef SEARCH8  #ifndef SEARCH8
244  #define SEARCH8         PMVfastSearch8  #define SEARCH8         PMVfastSearch8
245    //#define SEARCH8       EPZSSearch8
246  #endif  #endif
247    
248  bool MotionEstimation(  bool MotionEstimation(
         MACROBLOCK * const pMBs,  
249          MBParam * const pParam,          MBParam * const pParam,
250          const IMAGE * const pRef,          FRAMEINFO * const current,
251            FRAMEINFO * const reference,
252          const IMAGE * const pRefH,          const IMAGE * const pRefH,
253          const IMAGE * const pRefV,          const IMAGE * const pRefV,
254          const IMAGE * const pRefHV,          const IMAGE * const pRefHV,
         IMAGE * const pCurrent,  
255          const uint32_t iLimit)          const uint32_t iLimit)
256    
257  {  {
258          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
259          const uint32_t iHcount = pParam->mb_height;          const uint32_t iHcount = pParam->mb_height;
260            MACROBLOCK * pMBs = current->mbs;
261            IMAGE * pCurrent = &current->image;
262    
263            MACROBLOCK * prevMBs = reference->mbs;  // previous frame
264            IMAGE * pRef = &reference->image;
265    
266    
267          uint32_t i, j, iIntra = 0;          uint32_t i, j, iIntra = 0;
268    
# Line 290  Line 273 
273          int32_t sad16;          int32_t sad16;
274          int32_t deviation;          int32_t deviation;
275    
276            if (sadInit)
277                    (*sadInit)();
278    
279    
280            /* eventhough we have a seperate prevMBs,
281               pmvfast/epsz does something "funny" with the previous frames data */
282    
283    /*      for (i = 0; i < iHcount; i++)
284                    for (j = 0; j < iWcount; j++)
285                    {
286                            pMBs[j + i * iWcount].mvs[0] = prevMBs[j + i * iWcount].mvs[0];
287                            pMBs[j + i * iWcount].mvs[1] = prevMBs[j + i * iWcount].mvs[1];
288                            pMBs[j + i * iWcount].mvs[2] = prevMBs[j + i * iWcount].mvs[2];
289                            pMBs[j + i * iWcount].mvs[3] = prevMBs[j + i * iWcount].mvs[3];
290                    }
291    */
292            /*dprintf("*** BEFORE ***");
293            for (i = 0; i < iHcount; i++)
294                    for (j = 0; j < iWcount; j++)
295                    {
296                            dprintf("   [%i,%i] mode=%i dquant=%i mvs=(%i %i %i %i) sad8=(%i %i %i %i) sad16=(%i)", j,i,
297                                    pMBs[j + i * iWcount].mode,
298                                    pMBs[j + i * iWcount].dquant,
299                                    pMBs[j + i * iWcount].mvs[0],
300                                    pMBs[j + i * iWcount].mvs[1],
301                                    pMBs[j + i * iWcount].mvs[2],
302                                    pMBs[j + i * iWcount].mvs[3],
303                                    prevMBs[j + i * iWcount].sad8[0],
304                                    prevMBs[j + i * iWcount].sad8[1],
305                                    prevMBs[j + i * iWcount].sad8[2],
306                                    prevMBs[j + i * iWcount].sad8[3],
307                                    prevMBs[j + i * iWcount].sad16);
308                    }
309            */
310    
311          // note: i==horizontal, j==vertical          // note: i==horizontal, j==vertical
312          for (i = 0; i < iHcount; i++)          for (i = 0; i < iHcount; i++)
313                  for (j = 0; j < iWcount; j++)                  for (j = 0; j < iWcount; j++)
314                  {                  {
315                          MACROBLOCK *pMB = &pMBs[j + i * iWcount];                          MACROBLOCK *pMB = &pMBs[j + i * iWcount];
316                            MACROBLOCK *prevMB = &prevMBs[j + i * iWcount];
317    
318                          sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                          sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
319                                           j, i, pParam->motion_flags,                                           j, i, current->motion_flags, current->quant, current->fcode,
320                                           pParam, pMBs, &mv16, &pmv16);                                           pParam, pMBs, prevMBs, &mv16, &pmv16);
321                          pMB->sad16=sad16;                          pMB->sad16=sad16;
322    
323    
# Line 314  Line 333 
333                                  pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;                                  pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;
334                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;
335    
336                                    pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = 0;
337    
338                                  iIntra++;                                  iIntra++;
339                                  if(iIntra >= iLimit)                                  if(iIntra >= iLimit)
340                                          return 1;                                          return 1;
# Line 321  Line 342 
342                                  continue;                                  continue;
343                          }                          }
344    
345                          if (pParam->global_flags & XVID_INTER4V)                          if (current->global_flags & XVID_INTER4V)
346                          {                          {
347                                  pMB->sad8[0] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                  pMB->sad8[0] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
348                                                         2 * j, 2 * i, mv16.x, mv16.y, pParam->motion_flags,                                                         2 * j, 2 * i, mv16.x, mv16.y,
349                                                         pParam, pMBs, &pMB->mvs[0], &pMB->pmvs[0]);                                                             current->motion_flags, current->quant, current->fcode,
350                                                           pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]);
351    
352                                  pMB->sad8[1] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                  pMB->sad8[1] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
353                                                         2 * j + 1, 2 * i, mv16.x, mv16.y, pParam->motion_flags,                                                         2 * j + 1, 2 * i, mv16.x, mv16.y,
354                                                         pParam, pMBs, &pMB->mvs[1], &pMB->pmvs[1]);                                                             current->motion_flags, current->quant, current->fcode,
355                                                           pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]);
356    
357                                  pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                  pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
358                                                         2 * j, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,                                                         2 * j, 2 * i + 1, mv16.x, mv16.y,
359                                                         pParam, pMBs, &pMB->mvs[2], &pMB->pmvs[2]);                                                             current->motion_flags, current->quant, current->fcode,
360                                                           pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]);
361    
362                                  pMB->sad8[3] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                  pMB->sad8[3] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
363                                                         2 * j + 1, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,                                                         2 * j + 1, 2 * i + 1, mv16.x, mv16.y,
364                                                         pParam, pMBs, &pMB->mvs[3], &pMB->pmvs[3]);                                                             current->motion_flags, current->quant, current->fcode,
365                                                           pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]);
366    
367                                  sad8 = pMB->sad8[0] + pMB->sad8[1] + pMB->sad8[2] + pMB->sad8[3];                                  sad8 = pMB->sad8[0] + pMB->sad8[1] + pMB->sad8[2] + pMB->sad8[3];
368                          }                          }
# Line 347  Line 372 
372                             mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v                             mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v
373                          */                          */
374    
375                          if (pMB->dquant == NO_CHANGE) {                          if (!(current->global_flags & XVID_LUMIMASKING) || pMB->dquant == NO_CHANGE)
376                                  if (((pParam->global_flags & XVID_INTER4V)==0) ||                          {
377                                      (sad16 < (sad8 + (int32_t)(IMV16X16 * pParam->quant)))) {                                  if (((current->global_flags & XVID_INTER4V)==0) ||
378                                        (sad16 < (sad8 + (int32_t)(IMV16X16 * current->quant))))
379                                    {
380    
381                                          sad8 = sad16;                                          sad8 = sad16;
382                                          pMB->mode = MODE_INTER;                                          pMB->mode = MODE_INTER;
# Line 372  Line 399 
399                          }                          }
400                  }                  }
401    
402    /*      dprintf("*** AFTER ***", pMBs[0].b_mvs[0].x);
403            for (i = 0; i < iHcount; i++)
404                    for (j = 0; j < iWcount; j++)
405                    {
406                            dprintf("   [%i,%i] mode=%i dquant=%i mvs=(%i %i %i %i) sad8=(%i %i %i %i) sad16=(%i)", j,i,
407                                    pMBs[j + i * iWcount].mode,
408                                    pMBs[j + i * iWcount].dquant,
409                                    pMBs[j + i * iWcount].mvs[0],
410                                    pMBs[j + i * iWcount].mvs[1],
411                                    pMBs[j + i * iWcount].mvs[2],
412                                    pMBs[j + i * iWcount].mvs[3],
413                                    pMBs[j + i * iWcount].sad8[0],
414                                    pMBs[j + i * iWcount].sad8[1],
415                                    pMBs[j + i * iWcount].sad8[2],
416                                    pMBs[j + i * iWcount].sad8[3],
417                                    pMBs[j + i * iWcount].sad16);
418                    }
419            */
420    
421          return 0;          return 0;
422  }  }
423    
# Line 386  Line 432 
432    { \    { \
433      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \
434      iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\
     if (iSAD <= iQuant * 96)    \  
         iSAD -= MV16_00_BIAS; \  
435      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
436      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
437  }  }
438    
439    #define NOCHECK_MV16_CANDIDATE(X,Y) { \
440        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
441        iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\
442        if (iSAD < iMinSAD) \
443        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
444    }
445    
446  #define CHECK_MV16_CANDIDATE(X,Y) { \  #define CHECK_MV16_CANDIDATE(X,Y) { \
447    if ( ((X) <= max_dx) && ((X) >= min_dx) \    if ( ((X) <= max_dx) && ((X) >= min_dx) \
# Line 431  Line 481 
481    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
482  }  }
483    
484    #define NOCHECK_MV8_CANDIDATE(X,Y) \
485      { \
486        iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
487        iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\
488        if (iSAD < iMinSAD) \
489        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
490    }
491    
492  #define CHECK_MV8_CANDIDATE(X,Y) { \  #define CHECK_MV8_CANDIDATE(X,Y) { \
493    if ( ((X) <= max_dx) && ((X) >= min_dx) \    if ( ((X) <= max_dx) && ((X) >= min_dx) \
# Line 472  Line 529 
529                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
530                                          const int x, const int y,                                          const int x, const int y,
531                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
532                                            const uint32_t iQuant,
533                                            const uint32_t iFcode,
534                                          MBParam * const pParam,                                          MBParam * const pParam,
535                                          MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
536                                            const MACROBLOCK * const prevMBs,
537                                          VECTOR * const currMV,                                          VECTOR * const currMV,
538                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
539  {  {
540          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
         const int32_t iQuant = pParam->quant;  
541          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
542          int32_t iSAD;          int32_t iSAD;
543          int32_t pred_x,pred_y;          int32_t pred_x,pred_y;
# Line 501  Line 560 
560  }  }
561  */  */
562    
563  int32_t PMVfastSearch16_MainSearch(  int32_t Diamond16_MainSearch(
564          const uint8_t * const pRef,          const uint8_t * const pRef,
565          const uint8_t * const pRefH,          const uint8_t * const pRefH,
566          const uint8_t * const pRefV,          const uint8_t * const pRefV,
# Line 558  Line 617 
617          return iMinSAD;          return iMinSAD;
618  }  }
619    
620  int32_t PMVfastSearch16_Refine(  int32_t Square16_MainSearch(
621          const uint8_t * const pRef,          const uint8_t * const pRef,
622          const uint8_t * const pRefH,          const uint8_t * const pRefH,
623          const uint8_t * const pRefV,          const uint8_t * const pRefV,
624          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
625          const uint8_t * const cur,          const uint8_t * const cur,
626          const int x, const int y,          const int x, const int y,
627          VECTOR * const currMV,                                          int32_t startx, int32_t starty,
628          int32_t iMinSAD,          int32_t iMinSAD,
629                                            VECTOR * const currMV,
630          const VECTOR * const pmv,          const VECTOR * const pmv,
631          const int32_t min_dx, const int32_t max_dx,          const int32_t min_dx, const int32_t max_dx,
632          const int32_t min_dy, const int32_t max_dy,          const int32_t min_dy, const int32_t max_dy,
633                                            const int32_t iEdgedWidth,
634                                            const int32_t iDiamondSize,
635          const int32_t iFcode,          const int32_t iFcode,
636          const int32_t iQuant,          const int32_t iQuant,
637          const int32_t iEdgedWidth)                                          int iFound)
638  {  {
639  /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  /* Do a square search around given starting point, return SAD of best */
640    
641            int32_t iDirection=0;
642          int32_t iSAD;          int32_t iSAD;
643          VECTOR backupMV = *currMV;          VECTOR backupMV;
644            backupMV.x = startx;
645          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y-1);          backupMV.y = starty;
         CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y-1);  
         CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y-1);  
         CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y);  
         CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y);  
         CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y+1);  
         CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y+1);  
         CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y+1);  
   
         return iMinSAD;  
 }  
   
 #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  
646    
647  int32_t PMVfastSearch16(  /* It's one search with full square pattern, and new parts for all following diamonds */
         const uint8_t * const pRef,  
         const uint8_t * const pRefH,  
         const uint8_t * const pRefV,  
         const uint8_t * const pRefHV,  
         const IMAGE * const pCur,  
         const int x, const int y,  
         const uint32_t MotionFlags,  
         MBParam * const pParam,  
         MACROBLOCK * const pMBs,  
         VECTOR * const currMV,  
         VECTOR * const currPMV)  
 {  
         const uint32_t iWcount = pParam->mb_width;  
         const int32_t iFcode = pParam->fixed_code;  
         const int32_t iQuant = pParam->quant;  
         const int32_t iWidth = pParam->width;  
         const int32_t iHeight = pParam->height;  
         const int32_t iEdgedWidth = pParam->edged_width;  
648    
649          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;  /*   new direction are extra, so 1-4 is normal diamond
650          537
651          1*2
652          648
653    */
654    
655          int32_t iDiamondSize;          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
656            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
657            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
658            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
659    
660          int32_t min_dx;          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
661          int32_t max_dx;          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
662          int32_t min_dy;          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
663          int32_t max_dy;          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
664    
         int32_t iFound;  
665    
666          VECTOR newMV;          if (iDirection)
667          VECTOR backupMV;        /* just for PMVFAST */                  while (!iFound)
668                    {
669                            iFound = 1;
670                            backupMV=*currMV;
671    
672          VECTOR pmv[4];                          switch (iDirection)
673          int32_t psad[4];                          {
674                                    case 1:
675                                            CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
676                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
677                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
678                                            break;
679                                    case 2:
680                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
681                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
682                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
683                                            break;
684    
685          MACROBLOCK * const pMB = pMBs + x + y * iWcount;                                  case 3:
686                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
687                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
688                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
689                                            break;
690    
691          static int32_t threshA,threshB;                                  case 4:
692          int32_t bPredEq;                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
693          int32_t iMinSAD,iSAD;                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
694                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
695                                            break;
696    
697  /* Get maximum range */                                  case 5:
698          get_range(&min_dx, &max_dx, &min_dy, &max_dy,                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
699                    x, y, 16, iWidth, iHeight, iFcode);                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
700                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
701                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
702                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
703                                            break;
704    
705  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */                                  case 6:
706                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
707                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
708    
709          if (!(MotionFlags & PMV_HALFPEL16 ))                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
710          { min_dx = EVEN(min_dx);                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
711          max_dx = EVEN(max_dx);                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
         min_dy = EVEN(min_dy);  
         max_dy = EVEN(max_dy);  
         }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */  
712    
713                                            break;
714    
715          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);                                  case 7:
716                                            CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
717                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
718                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
719                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
720                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
721                                            break;
722    
723          if ((x==0) && (y==0) )                                  case 8:
724          {                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
725                  threshA =  512;                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
726                  threshB = 1024;                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
727                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
728                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
729                                            break;
730                            default:
731                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
732                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
733                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
734                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
735    
736                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
737                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
738                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
739                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
740                                            break;
741                            }
742          }          }
743          else          else
744          {          {
745                  threshA = psad[0];                          currMV->x = startx;
746                  threshB = threshA+256;                          currMV->y = starty;
747                  if (threshA< 512) threshA =  512;                  }
748                  if (threshA>1024) threshA = 1024;          return iMinSAD;
                 if (threshB>1792) threshB = 1792;  
749          }          }
750    
         iFound=0;  
   
 /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  
    vector of the median.  
    If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2  
 */  
   
         if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[0]) ) )  
                 iFound=2;  
   
 /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  
    Otherwise select large Diamond Search.  
 */  
   
         if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536) || (bPredEq) )  
                 iDiamondSize=1; // halfpel!  
         else  
                 iDiamondSize=2; // halfpel!  
   
         if (!(MotionFlags & PMV_HALFPELDIAMOND16) )  
                 iDiamondSize*=2;  
751    
752  /* Step 4: Calculate SAD around the Median prediction.  int32_t Full16_MainSearch(
753     MinSAD=SAD                                          const uint8_t * const pRef,
754     If Motion Vector equal to Previous frame motion vector                                          const uint8_t * const pRefH,
755     and MinSAD<PrevFrmSAD goto Step 10.                                          const uint8_t * const pRefV,
756                                            const uint8_t * const pRefHV,
757                                            const uint8_t * const cur,
758                                            const int x, const int y,
759                                            int32_t startx, int32_t starty,
760                                            int32_t iMinSAD,
761                                            VECTOR * const currMV,
762                                            const VECTOR * const pmv,
763                                            const int32_t min_dx, const int32_t max_dx,
764                                            const int32_t min_dy, const int32_t max_dy,
765                                            const int32_t iEdgedWidth,
766                                            const int32_t iDiamondSize,
767                                            const int32_t iFcode,
768                                            const int32_t iQuant,
769                                            int iFound)
770    {
771            int32_t iSAD;
772            int32_t dx,dy;
773            VECTOR backupMV;
774            backupMV.x = startx;
775            backupMV.y = starty;
776    
777            for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
778                    for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
779                            NOCHECK_MV16_CANDIDATE(dx,dy);
780    
781            return iMinSAD;
782    }
783    
784    int32_t Full8_MainSearch(
785                                            const uint8_t * const pRef,
786                                            const uint8_t * const pRefH,
787                                            const uint8_t * const pRefV,
788                                            const uint8_t * const pRefHV,
789                                            const uint8_t * const cur,
790                                            const int x, const int y,
791                                            int32_t startx, int32_t starty,
792                                            int32_t iMinSAD,
793                                            VECTOR * const currMV,
794                                            const VECTOR * const pmv,
795                                            const int32_t min_dx, const int32_t max_dx,
796                                            const int32_t min_dy, const int32_t max_dy,
797                                            const int32_t iEdgedWidth,
798                                            const int32_t iDiamondSize,
799                                            const int32_t iFcode,
800                                            const int32_t iQuant,
801                                            int iFound)
802    {
803            int32_t iSAD;
804            int32_t dx,dy;
805            VECTOR backupMV;
806            backupMV.x = startx;
807            backupMV.y = starty;
808    
809            for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
810                    for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
811                            NOCHECK_MV8_CANDIDATE(dx,dy);
812    
813            return iMinSAD;
814    }
815    
816    
817    
818    int32_t Halfpel16_Refine(
819            const uint8_t * const pRef,
820            const uint8_t * const pRefH,
821            const uint8_t * const pRefV,
822            const uint8_t * const pRefHV,
823            const uint8_t * const cur,
824            const int x, const int y,
825            VECTOR * const currMV,
826            int32_t iMinSAD,
827            const VECTOR * const pmv,
828            const int32_t min_dx, const int32_t max_dx,
829            const int32_t min_dy, const int32_t max_dy,
830            const int32_t iFcode,
831            const int32_t iQuant,
832            const int32_t iEdgedWidth)
833    {
834    /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
835    
836            int32_t iSAD;
837            VECTOR backupMV = *currMV;
838    
839            CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y-1);
840            CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y-1);
841            CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y-1);
842            CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y);
843            CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y);
844            CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y+1);
845            CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y+1);
846            CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y+1);
847    
848            return iMinSAD;
849    }
850    
851    #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
852    
853    
854    int32_t PMVfastSearch16(
855                                            const uint8_t * const pRef,
856                                            const uint8_t * const pRefH,
857                                            const uint8_t * const pRefV,
858                                            const uint8_t * const pRefHV,
859                                            const IMAGE * const pCur,
860                                            const int x, const int y,
861                                            const uint32_t MotionFlags,
862                                            const uint32_t iQuant,
863                                            const uint32_t iFcode,
864                                            const MBParam * const pParam,
865                                            const MACROBLOCK * const pMBs,
866                                            const MACROBLOCK * const prevMBs,
867                                            VECTOR * const currMV,
868                                            VECTOR * const currPMV)
869    {
870        const uint32_t iWcount = pParam->mb_width;
871            const int32_t iWidth = pParam->width;
872            const int32_t iHeight = pParam->height;
873            const int32_t iEdgedWidth = pParam->edged_width;
874    
875            const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
876    
877            int32_t iDiamondSize;
878    
879            int32_t min_dx;
880            int32_t max_dx;
881            int32_t min_dy;
882            int32_t max_dy;
883    
884            int32_t iFound;
885    
886            VECTOR newMV;
887            VECTOR backupMV;        /* just for PMVFAST */
888    
889            VECTOR pmv[4];
890            int32_t psad[4];
891    
892            const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
893            const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
894    
895            static int32_t threshA,threshB;
896            int32_t bPredEq;
897            int32_t iMinSAD,iSAD;
898    
899    /* Get maximum range */
900            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
901                      x, y, 16, iWidth, iHeight, iFcode);
902    
903    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
904    
905            if (!(MotionFlags & PMV_HALFPEL16 ))
906            { min_dx = EVEN(min_dx);
907            max_dx = EVEN(max_dx);
908            min_dy = EVEN(min_dy);
909            max_dy = EVEN(max_dy);
910            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
911    
912    
913            bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
914    
915            if ((x==0) && (y==0) )
916            {
917                    threshA =  512;
918                    threshB = 1024;
919    
920            }
921            else
922            {
923                    threshA = psad[0];
924                    threshB = threshA+256;
925                    if (threshA< 512) threshA =  512;
926                    if (threshA>1024) threshA = 1024;
927                    if (threshB>1792) threshB = 1792;
928            }
929    
930            iFound=0;
931    
932    /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
933       vector of the median.
934       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
935    */
936    
937            if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[0]) ) )
938                    iFound=2;
939    
940    /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
941       Otherwise select large Diamond Search.
942    */
943    
944            if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536) || (bPredEq) )
945                    iDiamondSize=1; // halfpel!
946            else
947                    iDiamondSize=2; // halfpel!
948    
949            if (!(MotionFlags & PMV_HALFPELDIAMOND16) )
950                    iDiamondSize*=2;
951    
952    /* Step 4: Calculate SAD around the Median prediction.
953       MinSAD=SAD
954       If Motion Vector equal to Previous frame motion vector
955       and MinSAD<PrevFrmSAD goto Step 10.
956     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
957  */  */
958    
# Line 728  Line 988 
988                           iEdgedWidth, MV_MAX_ERROR);                           iEdgedWidth, MV_MAX_ERROR);
989          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;
990    
991          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
992          {          {
993    
994                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
995                          goto step10b;                          goto PMVfast16_Terminate_without_Refine;
996                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
997                          goto step10;                          goto PMVfast16_Terminate_with_Refine;
998          }          }
999    
1000  /*  /*
1001     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
1002     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1003     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1004     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1005  */  */
1006    
1007  // (0,0) is always possible  // (0,0) is always possible
# Line 749  Line 1009 
1009          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1010    
1011  // previous frame MV is always possible  // previous frame MV is always possible
1012          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1013    
1014  // left neighbour, if allowed  // left neighbour, if allowed
1015          if (x != 0)          if (x != 0)
# Line 771  Line 1031 
1031                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1032    
1033  // top right neighbour, if allowed  // top right neighbour, if allowed
1034                  if (x != (iWcount-1))                  if ((uint32_t)x != (iWcount-1))
1035                  {                  {
1036                          if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!(MotionFlags & PMV_HALFPEL16 ))
1037                          {       pmv[3].x = EVEN(pmv[3].x);                          {       pmv[3].x = EVEN(pmv[3].x);
# Line 781  Line 1041 
1041                  }                  }
1042          }          }
1043    
1044            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) && (iSAD <= iQuant * 96) )
1045                    iMinSAD -= MV16_00_BIAS;
1046    
1047    
1048  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1049     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
1050  */  */
1051    
1052          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
1053          {          {
1054                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1055                          goto step10b;                          goto PMVfast16_Terminate_without_Refine;
1056                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
1057                          goto step10;                          goto PMVfast16_Terminate_with_Refine;
1058          }          }
1059    
1060    
# Line 807  Line 1071 
1071          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1072    
1073  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1074          iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1075                                            x, y,                                            x, y,
1076                                            currMV->x, currMV->y, iMinSAD, &newMV,                                            currMV->x, currMV->y, iMinSAD, &newMV,
1077                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 823  Line 1087 
1087  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1088    
1089                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0],backupMV)) )
1090                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1091                                                            x, y,                                                            x, y,
1092                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1093                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 836  Line 1100 
1100                  }                  }
1101    
1102                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1103                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1104                                                            x, y,                                                            x, y,
1105                                                            0, 0, iMinSAD, &newMV,                                                            0, 0, iMinSAD, &newMV,
1106                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 853  Line 1117 
1117     Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.     Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.
1118  */  */
1119    
1120   step10:  PMVfast16_Terminate_with_Refine:
1121          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1122                  iMinSAD = PMVfastSearch16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1123                                                    x, y,                                                    x, y,
1124                                                    currMV, iMinSAD,                                                    currMV, iMinSAD,
1125                                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1126    
1127   step10b:  PMVfast16_Terminate_without_Refine:
1128          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1129          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
1130          return iMinSAD;          return iMinSAD;
# Line 871  Line 1135 
1135    
1136    
1137    
1138  int32_t PMVfastSearch8_MainSearch(  int32_t Diamond8_MainSearch(
1139          const uint8_t * const pRef,          const uint8_t * const pRef,
1140          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1141          const uint8_t * const pRefV,          const uint8_t * const pRefV,
# Line 928  Line 1192 
1192          return iMinSAD;          return iMinSAD;
1193  }  }
1194    
1195  int32_t PMVfastSearch8_Refine(  int32_t Halfpel8_Refine(
1196          const uint8_t * const pRef,          const uint8_t * const pRef,
1197          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1198          const uint8_t * const pRefV,          const uint8_t * const pRefV,
# Line 971  Line 1235 
1235          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1236          const IMAGE * const pCur,          const IMAGE * const pCur,
1237          const int x, const int y,          const int x, const int y,
1238          const int start_x, int start_y,                                          const int start_x, const int start_y,
1239          const uint32_t MotionFlags,          const uint32_t MotionFlags,
1240          MBParam * const pParam,                                          const uint32_t iQuant,
1241          MACROBLOCK * const pMBs,                                          const uint32_t iFcode,
1242                                            const MBParam * const pParam,
1243                                            const MACROBLOCK * const pMBs,
1244                                            const MACROBLOCK * const prevMBs,
1245          VECTOR * const currMV,          VECTOR * const currMV,
1246          VECTOR * const currPMV)          VECTOR * const currPMV)
1247  {  {
1248          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
   
         const int32_t iFcode = pParam->fixed_code;  
         const int32_t iQuant = pParam->quant;  
1249          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1250          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
1251          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 1000  Line 1264 
1264          VECTOR newMV;          VECTOR newMV;
1265          VECTOR backupMV;          VECTOR backupMV;
1266    
1267          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1268            const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1269    
1270          static int32_t threshA,threshB;          static int32_t threshA,threshB;
1271          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
# Line 1012  Line 1277 
1277          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1278                    x, y, 8, iWidth, iHeight, iFcode);                    x, y, 8, iWidth, iHeight, iFcode);
1279    
 /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */  
   
1280          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))
1281          { min_dx = EVEN(min_dx);          { min_dx = EVEN(min_dx);
1282          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
# Line 1046  Line 1309 
1309     If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2     If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1310  */  */
1311    
1312          if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[iSubBlock]) ) )          if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[iSubBlock]) ) )
1313                  iFound=2;                  iFound=2;
1314    
1315  /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
# Line 1079  Line 1342 
1342                          iEdgedWidth);                          iEdgedWidth);
1343          iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode) * iQuant;          iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode) * iQuant;
1344    
1345          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock])) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1346          {          {
1347                  if (MotionFlags & PMV_QUICKSTOP8)                  if (MotionFlags & PMV_QUICKSTOP16)
1348                          goto step10_8b;                          goto PMVfast8_Terminate_without_Refine;
1349                  if (MotionFlags & PMV_EARLYSTOP8)                  if (MotionFlags & PMV_EARLYSTOP16)
1350                          goto step10_8;                          goto PMVfast8_Terminate_with_Refine;
1351          }          }
1352    
1353    
1354  /*  /*
1355     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
1356     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1357     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1358     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1359  */  */
1360    
1361  // the prediction might be even better than mv16  // the prediction might be even better than mv16
# Line 1101  Line 1365 
1365          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
1366    
1367  // previous frame MV is always possible  // previous frame MV is always possible
1368          CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
1369    
1370  // left neighbour, if allowed  // left neighbour, if allowed
1371          if (psad[1] != MV_MAX_ERROR)          if (psad[1] != MV_MAX_ERROR)
# Line 1133  Line 1397 
1397                  }                  }
1398          }          }
1399    
1400            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) && (iSAD <= iQuant * 96) )
1401                    iMinSAD -= MV8_00_BIAS;
1402    
1403    
1404  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1405     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
1406  */  */
1407    
1408          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1409          {          {
1410                  if (MotionFlags & PMV_QUICKSTOP8)                  if (MotionFlags & PMV_QUICKSTOP16)
1411                          goto step10_8b;                          goto PMVfast8_Terminate_without_Refine;
1412                  if (MotionFlags & PMV_EARLYSTOP8)                  if (MotionFlags & PMV_EARLYSTOP16)
1413                          goto step10_8;                          goto PMVfast8_Terminate_with_Refine;
1414          }          }
1415    
1416  /************ (Diamond Search)  **************/  /************ (Diamond Search)  **************/
# Line 1158  Line 1426 
1426          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1427    
1428  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1429          iSAD = PMVfastSearch8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1430                                           x, y,                                           x, y,
1431                                           currMV->x, currMV->y, iMinSAD, &newMV,                                           currMV->x, currMV->y, iMinSAD, &newMV,
1432                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 1174  Line 1442 
1442  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1443    
1444                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0],backupMV)) )
1445                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1446                                                            x, y,                                                            x, y,
1447                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1448                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 1187  Line 1455 
1455                  }                  }
1456    
1457                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1458                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1459                                                            x, y,                                                            x, y,
1460                                                            0, 0, iMinSAD, &newMV,                                                            0, 0, iMinSAD, &newMV,
1461                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 1204  Line 1472 
1472     By performing an optional local half-pixel search, we can refine this result even further.     By performing an optional local half-pixel search, we can refine this result even further.
1473  */  */
1474    
1475   step10_8:  PMVfast8_Terminate_with_Refine:
1476          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
1477                  iMinSAD = PMVfastSearch8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1478                                                   x, y,                                                   x, y,
1479                                                   currMV, iMinSAD,                                                   currMV, iMinSAD,
1480                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1481    
  step10_8b:  
1482    
1483    PMVfast8_Terminate_without_Refine:
1484          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1485          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
1486    
1487          return iMinSAD;          return iMinSAD;
1488  }  }
1489    
1490    int32_t EPZSSearch16(
1491                                            const uint8_t * const pRef,
1492                                            const uint8_t * const pRefH,
1493                                            const uint8_t * const pRefV,
1494                                            const uint8_t * const pRefHV,
1495                                            const IMAGE * const pCur,
1496                                            const int x, const int y,
1497                                            const uint32_t MotionFlags,
1498                                            const uint32_t iQuant,
1499                                            const uint32_t iFcode,
1500                                            const MBParam * const pParam,
1501                                            const MACROBLOCK * const pMBs,
1502                                            const MACROBLOCK * const prevMBs,
1503                                            VECTOR * const currMV,
1504                                            VECTOR * const currPMV)
1505    {
1506        const uint32_t iWcount = pParam->mb_width;
1507        const uint32_t iHcount = pParam->mb_height;
1508    
1509            const int32_t iWidth = pParam->width;
1510            const int32_t iHeight = pParam->height;
1511            const int32_t iEdgedWidth = pParam->edged_width;
1512    
1513            const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
1514    
1515            int32_t min_dx;
1516            int32_t max_dx;
1517            int32_t min_dy;
1518            int32_t max_dy;
1519    
1520            VECTOR newMV;
1521            VECTOR backupMV;
1522    
1523            VECTOR pmv[4];
1524            int32_t psad[8];
1525    
1526            static MACROBLOCK * oldMBs = NULL;
1527            const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
1528            const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1529            MACROBLOCK * oldMB = NULL;
1530    
1531            static int32_t thresh2;
1532            int32_t bPredEq;
1533            int32_t iMinSAD,iSAD=9999;
1534    
1535            MainSearch16FuncPtr EPZSMainSearchPtr;
1536    
1537            if (oldMBs == NULL)
1538            {       oldMBs = (MACROBLOCK*) calloc(1,iWcount*iHcount*sizeof(MACROBLOCK));
1539    //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
1540            }
1541            oldMB = oldMBs + x + y * iWcount;
1542    
1543    /* Get maximum range */
1544            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1545                            x, y, 16, iWidth, iHeight, iFcode);
1546    
1547            if (!(MotionFlags & PMV_HALFPEL16 ))
1548            { min_dx = EVEN(min_dx);
1549              max_dx = EVEN(max_dx);
1550              min_dy = EVEN(min_dy);
1551              max_dy = EVEN(max_dy);
1552            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1553    
1554            bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1555    
1556    /* Step 4: Calculate SAD around the Median prediction.
1557            MinSAD=SAD
1558            If Motion Vector equal to Previous frame motion vector
1559                    and MinSAD<PrevFrmSAD goto Step 10.
1560            If SAD<=256 goto Step 10.
1561    */
1562    
1563    // Prepare for main loop
1564    
1565            *currMV=pmv[0];         /* current best := median prediction */
1566            if (!(MotionFlags & PMV_HALFPEL16))
1567            {
1568                    currMV->x = EVEN(currMV->x);
1569                    currMV->y = EVEN(currMV->y);
1570            }
1571    
1572            if (currMV->x > max_dx)
1573                    currMV->x=max_dx;
1574            if (currMV->x < min_dx)
1575                    currMV->x=min_dx;
1576            if (currMV->y > max_dy)
1577                    currMV->y=max_dy;
1578            if (currMV->y < min_dy)
1579                    currMV->y=min_dy;
1580    
1581    /***************** This is predictor SET A: only median prediction ******************/
1582    
1583            iMinSAD = sad16( cur,
1584                    get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
1585                    iEdgedWidth, MV_MAX_ERROR);
1586            iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;
1587    
1588    // thresh1 is fixed to 256
1589            if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
1590                    {
1591                            if (MotionFlags & PMV_QUICKSTOP16)
1592                                    goto EPZS16_Terminate_without_Refine;
1593                            if (MotionFlags & PMV_EARLYSTOP16)
1594                                    goto EPZS16_Terminate_with_Refine;
1595                    }
1596    
1597    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1598    
1599    // previous frame MV
1600            CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);
1601    
1602    // set threshhold based on Min of Prediction and SAD of collocated block
1603    // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
1604    
1605            if ((x==0) && (y==0) )
1606            {
1607                    thresh2 =  512;
1608            }
1609            else
1610            {
1611    /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */
1612    
1613                    thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
1614            }
1615    
1616    // MV=(0,0) is often a good choice
1617    
1618            CHECK_MV16_ZERO;
1619    
1620    
1621    // left neighbour, if allowed
1622            if (x != 0)
1623            {
1624                    if (!(MotionFlags & PMV_HALFPEL16 ))
1625                    {       pmv[1].x = EVEN(pmv[1].x);
1626                            pmv[1].y = EVEN(pmv[1].y);
1627                    }
1628                    CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1629            }
1630    
1631    // top neighbour, if allowed
1632            if (y != 0)
1633            {
1634                    if (!(MotionFlags & PMV_HALFPEL16 ))
1635                    {       pmv[2].x = EVEN(pmv[2].x);
1636                            pmv[2].y = EVEN(pmv[2].y);
1637                    }
1638                    CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1639    
1640    // top right neighbour, if allowed
1641                    if ((uint32_t)x != (iWcount-1))
1642                    {
1643                            if (!(MotionFlags & PMV_HALFPEL16 ))
1644                            {       pmv[3].x = EVEN(pmv[3].x);
1645                                    pmv[3].y = EVEN(pmv[3].y);
1646                            }
1647                            CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
1648                    }
1649            }
1650    
1651    /* Terminate if MinSAD <= T_2
1652       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1653    */
1654    
1655            if ( (iMinSAD <= thresh2)
1656                    || ( MVequal(*currMV,pMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )
1657                    {
1658                            if (MotionFlags & PMV_QUICKSTOP16)
1659                                    goto EPZS16_Terminate_without_Refine;
1660                            if (MotionFlags & PMV_EARLYSTOP16)
1661                                    goto EPZS16_Terminate_with_Refine;
1662                    }
1663    
1664    /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
1665    
1666            backupMV = pMB->mvs[0];                 // last MV
1667            backupMV.x += (pMB->mvs[0].x - oldMB->mvs[0].x );       // acceleration X
1668            backupMV.y += (pMB->mvs[0].y - oldMB->mvs[0].y );       // acceleration Y
1669    
1670            CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);
1671    
1672    // left neighbour
1673            if (x != 0)
1674                    CHECK_MV16_CANDIDATE((oldMB-1)->mvs[0].x,oldMB->mvs[0].y);
1675    
1676    // top neighbour
1677            if (y != 0)
1678                    CHECK_MV16_CANDIDATE((oldMB-iWcount)->mvs[0].x,oldMB->mvs[0].y);
1679    
1680    // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
1681    
1682            if ((uint32_t)x != iWcount-1)
1683                    CHECK_MV16_CANDIDATE((pMB+1)->mvs[0].x,oldMB->mvs[0].y);
1684    
1685    // bottom neighbour, dito
1686            if ((uint32_t)y != iHcount-1)
1687                    CHECK_MV16_CANDIDATE((pMB+iWcount)->mvs[0].x,oldMB->mvs[0].y);
1688    
1689    /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
1690            if (iMinSAD <= thresh2)
1691                    {
1692                            if (MotionFlags & PMV_QUICKSTOP16)
1693                                    goto EPZS16_Terminate_without_Refine;
1694                            if (MotionFlags & PMV_EARLYSTOP16)
1695                                    goto EPZS16_Terminate_with_Refine;
1696                    }
1697    
1698    /************ (if Diamond Search)  **************/
1699    
1700            backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1701    
1702    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1703    
1704            if (MotionFlags & PMV_USESQUARES16)
1705                    EPZSMainSearchPtr = Square16_MainSearch;
1706            else
1707                    EPZSMainSearchPtr = Diamond16_MainSearch;
1708    
1709            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1710                            x, y,
1711                            currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1712                            2, iFcode, iQuant, 0);
1713    
1714            if (iSAD < iMinSAD)
1715            {
1716                    *currMV = newMV;
1717                    iMinSAD = iSAD;
1718            }
1719    
1720    
1721            if (MotionFlags & PMV_EXTSEARCH16)
1722            {
1723    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
1724    
1725                    if (!(MVequal(pmv[0],backupMV)) )
1726                    {
1727                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1728                                    x, y,
1729                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1730                                    pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
1731                    }
1732    
1733                    if (iSAD < iMinSAD)
1734                    {
1735                            *currMV = newMV;
1736                            iMinSAD = iSAD;
1737                    }
1738    
1739                    if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1740                    {
1741                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1742                                    x, y,
1743                            0, 0, iMinSAD, &newMV,
1744                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, /*iDiamondSize*/ 2, iFcode, iQuant, 0);
1745    
1746                            if (iSAD < iMinSAD)
1747                            {
1748                                    *currMV = newMV;
1749                                    iMinSAD = iSAD;
1750                            }
1751                    }
1752            }
1753    
1754    /***************        Choose best MV found     **************/
1755    
1756    EPZS16_Terminate_with_Refine:
1757            if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1758                    iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1759                                    x, y,
1760                                    currMV, iMinSAD,
1761                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1762    
1763    EPZS16_Terminate_without_Refine:
1764    
1765            *oldMB = *pMB;
1766    
1767            currPMV->x = currMV->x - pmv[0].x;
1768            currPMV->y = currMV->y - pmv[0].y;
1769            return iMinSAD;
1770    }
1771    
1772    
1773    int32_t EPZSSearch8(
1774                                            const uint8_t * const pRef,
1775                                            const uint8_t * const pRefH,
1776                                            const uint8_t * const pRefV,
1777                                            const uint8_t * const pRefHV,
1778                                            const IMAGE * const pCur,
1779                                            const int x, const int y,
1780                                            const int start_x, const int start_y,
1781                                            const uint32_t MotionFlags,
1782                                            const uint32_t iQuant,
1783                                            const uint32_t iFcode,
1784                                            const MBParam * const pParam,
1785                                            const MACROBLOCK * const pMBs,
1786                                            const MACROBLOCK * const prevMBs,
1787                                            VECTOR * const currMV,
1788                                            VECTOR * const currPMV)
1789    {
1790        const uint32_t iWcount = pParam->mb_width;
1791            const int32_t iWidth = pParam->width;
1792            const int32_t iHeight = pParam->height;
1793            const int32_t iEdgedWidth = pParam->edged_width;
1794    
1795            const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;
1796    
1797            int32_t iDiamondSize=1;
1798    
1799            int32_t min_dx;
1800            int32_t max_dx;
1801            int32_t min_dy;
1802            int32_t max_dy;
1803    
1804            VECTOR newMV;
1805            VECTOR backupMV;
1806    
1807            VECTOR pmv[4];
1808            int32_t psad[8];
1809    
1810            const   int32_t iSubBlock = ((y&1)<<1) + (x&1);
1811    
1812            const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1813            const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1814    
1815            int32_t bPredEq;
1816            int32_t iMinSAD,iSAD=9999;
1817    
1818            MainSearch8FuncPtr EPZSMainSearchPtr;
1819    
1820    /* Get maximum range */
1821            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1822                            x, y, 8, iWidth, iHeight, iFcode);
1823    
1824    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1825    
1826            if (!(MotionFlags & PMV_HALFPEL8 ))
1827            { min_dx = EVEN(min_dx);
1828              max_dx = EVEN(max_dx);
1829              min_dy = EVEN(min_dy);
1830              max_dy = EVEN(max_dy);
1831            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1832    
1833            bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);
1834    
1835    
1836    /* Step 4: Calculate SAD around the Median prediction.
1837            MinSAD=SAD
1838            If Motion Vector equal to Previous frame motion vector
1839                    and MinSAD<PrevFrmSAD goto Step 10.
1840            If SAD<=256 goto Step 10.
1841    */
1842    
1843    // Prepare for main loop
1844    
1845    
1846            if (!(MotionFlags & PMV_HALFPEL8))
1847            {
1848                    currMV->x = EVEN(currMV->x);
1849                    currMV->y = EVEN(currMV->y);
1850            }
1851    
1852            if (currMV->x > max_dx)
1853                    currMV->x=max_dx;
1854            if (currMV->x < min_dx)
1855                    currMV->x=min_dx;
1856            if (currMV->y > max_dy)
1857                    currMV->y=max_dy;
1858            if (currMV->y < min_dy)
1859                    currMV->y=min_dy;
1860    
1861    /***************** This is predictor SET A: only median prediction ******************/
1862    
1863    
1864            iMinSAD = sad8( cur,
1865                    get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
1866                    iEdgedWidth);
1867            iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;
1868    
1869    
1870    // thresh1 is fixed to 256
1871            if (iMinSAD < 256/4 )
1872                    {
1873                            if (MotionFlags & PMV_QUICKSTOP8)
1874                                    goto EPZS8_Terminate_without_Refine;
1875                            if (MotionFlags & PMV_EARLYSTOP8)
1876                                    goto EPZS8_Terminate_with_Refine;
1877                    }
1878    
1879    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1880    
1881    // previous frame MV
1882            CHECK_MV8_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);
1883    
1884    // MV=(0,0) is often a good choice
1885    
1886            CHECK_MV8_ZERO;
1887    
1888    /* Terminate if MinSAD <= T_2
1889       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1890    */
1891    
1892            if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */
1893                    {
1894                            if (MotionFlags & PMV_QUICKSTOP8)
1895                                    goto EPZS8_Terminate_without_Refine;
1896                            if (MotionFlags & PMV_EARLYSTOP8)
1897                                    goto EPZS8_Terminate_with_Refine;
1898                    }
1899    
1900    /************ (if Diamond Search)  **************/
1901    
1902            backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1903    
1904            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
1905                    iDiamondSize *= 2;
1906    
1907    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1908    
1909    //      if (MotionFlags & PMV_USESQUARES8)
1910    //              EPZSMainSearchPtr = Square8_MainSearch;
1911    //      else
1912                    EPZSMainSearchPtr = Diamond8_MainSearch;
1913    
1914            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1915                    x, y,
1916                    currMV->x, currMV->y, iMinSAD, &newMV,
1917                    pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1918                    iDiamondSize, iFcode, iQuant, 00);
1919    
1920    
1921            if (iSAD < iMinSAD)
1922            {
1923                    *currMV = newMV;
1924                    iMinSAD = iSAD;
1925            }
1926    
1927            if (MotionFlags & PMV_EXTSEARCH8)
1928            {
1929    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
1930    
1931                    if (!(MVequal(pmv[0],backupMV)) )
1932                    {
1933                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1934                                    x, y,
1935                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1936                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
1937    
1938                            if (iSAD < iMinSAD)
1939                            {
1940                                    *currMV = newMV;
1941                                    iMinSAD = iSAD;
1942                            }
1943                    }
1944    
1945                    if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1946                    {
1947                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1948                                    x, y,
1949                            0, 0, iMinSAD, &newMV,
1950                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
1951    
1952                            if (iSAD < iMinSAD)
1953                            {
1954                                    *currMV = newMV;
1955                                    iMinSAD = iSAD;
1956                            }
1957                    }
1958            }
1959    
1960    /***************        Choose best MV found     **************/
1961    
1962    EPZS8_Terminate_with_Refine:
1963            if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
1964                    iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1965                                    x, y,
1966                                    currMV, iMinSAD,
1967                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1968    
1969    EPZS8_Terminate_without_Refine:
1970    
1971            currPMV->x = currMV->x - pmv[0].x;
1972            currPMV->y = currMV->y - pmv[0].y;
1973            return iMinSAD;
1974    }
1975    
1976    
1977    
1978    
1979    
1980    /* ***********************************************************
1981            bvop motion estimation
1982    // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)
1983    ***************************************************************/
1984    
1985    /*
1986    void MotionEstimationBVOP(
1987                            MBParam * const pParam,
1988                            FRAMEINFO * const frame,
1989    
1990                            // forward (past) reference
1991                            const MACROBLOCK * const f_mbs,
1992                        const IMAGE * const f_ref,
1993                            const IMAGE * const f_refH,
1994                        const IMAGE * const f_refV,
1995                            const IMAGE * const f_refHV,
1996                            // backward (future) reference
1997                            const MACROBLOCK * const b_mbs,
1998                        const IMAGE * const b_ref,
1999                            const IMAGE * const b_refH,
2000                        const IMAGE * const b_refV,
2001                            const IMAGE * const b_refHV)
2002    {
2003        const uint32_t mb_width = pParam->mb_width;
2004        const uint32_t mb_height = pParam->mb_height;
2005            const int32_t edged_width = pParam->edged_width;
2006    
2007            int32_t i,j;
2008    
2009            int32_t f_sad16;
2010            int32_t b_sad16;
2011            int32_t i_sad16;
2012            int32_t d_sad16;
2013            int32_t best_sad;
2014    
2015            VECTOR pmv_dontcare;
2016    
2017            // note: i==horizontal, j==vertical
2018        for (j = 0; j < mb_height; j++)
2019            {
2020                    for (i = 0; i < mb_width; i++)
2021                    {
2022                            MACROBLOCK *mb = &frame->mbs[i + j*mb_width];
2023                            const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];
2024                            const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];
2025    
2026                            if (b_mb->mode == MODE_INTER
2027                                    && b_mb->cbp == 0
2028                                    && b_mb->mvs[0].x == 0
2029                                    && b_mb->mvs[0].y == 0)
2030                            {
2031                                    mb->mode = MB_IGNORE;
2032                                    mb->mvs[0].x = 0;
2033                                    mb->mvs[0].y = 0;
2034                                    mb->b_mvs[0].x = 0;
2035                                    mb->b_mvs[0].y = 0;
2036                                    continue;
2037                            }
2038    
2039    
2040                            // forward search
2041                            f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2042                                                    &frame->image,
2043                                                    i, j,
2044                                                    frame->motion_flags,  frame->quant, frame->fcode,
2045                                                    pParam,
2046                                                    f_mbs,
2047                                                    &mb->mvs[0], &pmv_dontcare);    // ignore pmv
2048    
2049                            // backward search
2050                            b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2051                                                    &frame->image,
2052                                                    i, j,
2053                                                    frame->motion_flags,  frame->quant, frame->bcode,
2054                                                    pParam,
2055                                                    b_mbs,
2056                                                    &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv
2057    
2058                            // interpolate search (simple, but effective)
2059                            i_sad16 = sad16bi_c(
2060                                            frame->image.y + i*16 + j*16*edged_width,
2061                                            get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2062                                                    i, j, 16, mb->mvs[0].x, mb->mvs[0].y, edged_width),
2063                                            get_ref(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2064                                                    i, j, 16, mb->b_mvs[0].x, mb->b_mvs[0].x, edged_width),
2065                                            edged_width);
2066    
2067                            // TODO: direct search
2068                            // predictor + range of [-32,32]
2069                            d_sad16 = 65535;
2070    
2071    
2072                            if (f_sad16 < b_sad16)
2073                            {
2074                                    best_sad = f_sad16;
2075                                    mb->mode = MB_FORWARD;
2076                            }
2077                            else
2078                            {
2079                                    best_sad = b_sad16;
2080                                    mb->mode = MB_BACKWARD;
2081                            }
2082    
2083                            if (i_sad16 < best_sad)
2084                            {
2085                                    best_sad = i_sad16;
2086                                    mb->mode = MB_INTERPOLATE;
2087                            }
2088    
2089                            if (d_sad16 < best_sad)
2090                            {
2091                                    best_sad = d_sad16;
2092                                    mb->mode = MB_DIRECT;
2093                            }
2094    
2095                    }
2096            }
2097    }
2098    
2099    */

Legend:
Removed from v.78  
changed lines
  Added in v.140

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