[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 3, Fri Mar 8 02:46:11 2002 UTC revision 169, Thu May 9 00:42:35 2002 UTC
# Line 2  Line 2 
2   *   *
3   *  Modifications:   *  Modifications:
4   *   *
5     *      01.05.2002      updated MotionEstimationBVOP
6     *      25.04.2002 partial prevMB conversion
7     *  22.04.2002 remove some compile warning by chenm001 <chenm001@163.com>
8     *  14.04.2002 added MotionEstimationBVOP()
9     *  02.04.2002 add EPZS(^2) as ME algorithm, use PMV_USESQUARES to choose between
10     *             EPZS and EPZS^2
11   *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop   *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop
12   *             PMVFast_Refine to support multiple searches with different start points   *             PMVFast_Refine to support multiple searches with different start points
13   *      07.01.2002 uv-block-based interpolation   *      07.01.2002 uv-block-based interpolation
# Line 31  Line 37 
37    
38  #include <assert.h>  #include <assert.h>
39  #include <stdio.h>  #include <stdio.h>
40    #include <stdlib.h>
41    
42  #include "../encoder.h"  #include "../encoder.h"
43  #include "../utils/mbfunctions.h"  #include "../utils/mbfunctions.h"
44  #include "../prediction/mbprediction.h"  #include "../prediction/mbprediction.h"
45  #include "../global.h"  #include "../global.h"
46  #include "../utils/timer.h"  #include "../utils/timer.h"
47    #include "motion.h"
48  #include "sad.h"  #include "sad.h"
49    
50  // very large value  // very large value
# Line 49  Line 57 
57  /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */  /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */
58  /* nb  = vop pixels * 2^(bpp-8) */  /* nb  = vop pixels * 2^(bpp-8) */
59  #define MV16_00_BIAS    (128+1)  #define MV16_00_BIAS    (128+1)
60    #define MV8_00_BIAS     (0)
61    
62  /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */  /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */
63  #define INTER_BIAS      512  #define INTER_BIAS      512
# Line 65  Line 74 
74  #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)  #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)
75    
76    
77  #define MIN(X, Y) ((X)<(Y)?(X):(Y))  int32_t PMVfastSearch16(
78  #define MAX(X, Y) ((X)>(Y)?(X):(Y))                                          const uint8_t * const pRef,
79  #define ABS(X) (((X)>0)?(X):-(X))                                          const uint8_t * const pRefH,
80  #define SIGN(X) (((X)>0)?1:-1)                                          const uint8_t * const pRefV,
81                                            const uint8_t * const pRefHV,
82                                            const IMAGE * const pCur,
83                                            const int x, const int y,
84                                            const uint32_t MotionFlags,
85                                            const uint32_t iQuant,
86                                            const uint32_t iFcode,
87                                            const MBParam * const pParam,
88                                            const MACROBLOCK * const pMBs,
89                                            const MACROBLOCK * const prevMBs,
90                                            VECTOR * const currMV,
91                                            VECTOR * const currPMV);
92    
93    int32_t EPZSSearch16(
94                                            const uint8_t * const pRef,
95                                            const uint8_t * const pRefH,
96                                            const uint8_t * const pRefV,
97                                            const uint8_t * const pRefHV,
98                                            const IMAGE * const pCur,
99                                            const int x, const int y,
100                                            const uint32_t MotionFlags,
101                                            const uint32_t iQuant,
102                                            const uint32_t iFcode,
103                                            const MBParam * const pParam,
104                                            const MACROBLOCK * const pMBs,
105                                            const MACROBLOCK * const prevMBs,
106                                            VECTOR * const currMV,
107                                            VECTOR * const currPMV);
108    
109    
110  int32_t PMVfastSearch8(  int32_t PMVfastSearch8(
# Line 78  Line 114 
114                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
115                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
116                                          const int x, const int y,                                          const int x, const int y,
117                                          const int start_x, int start_y,                                          const int start_x, const int start_y,
118                                          const uint32_t iQuality,                                          const uint32_t MotionFlags,
119                                          MBParam * const pParam,                                          const uint32_t iQuant,
120                                          MACROBLOCK * const pMBs,                                          const uint32_t iFcode,
121                                            const MBParam * const pParam,
122                                            const MACROBLOCK * const pMBs,
123                                            const MACROBLOCK * const prevMBs,
124                                          VECTOR * const currMV,                                          VECTOR * const currMV,
125                                          VECTOR * const currPMV);                                          VECTOR * const currPMV);
126    
127  int32_t PMVfastSearch16(  int32_t EPZSSearch8(
128                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
129                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
130                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
131                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
132                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
133                                          const int x, const int y,                                          const int x, const int y,
134                                          const uint32_t iQuality,                                          const int start_x, const int start_y,
135                                          MBParam * const pParam,                                          const uint32_t MotionFlags,
136                                          MACROBLOCK * const pMBs,                                          const uint32_t iQuant,
137                                            const uint32_t iFcode,
138                                            const MBParam * const pParam,
139                                            const MACROBLOCK * const pMBs,
140                                            const MACROBLOCK * const prevMBs,
141                                          VECTOR * const currMV,                                          VECTOR * const currMV,
142                                          VECTOR * const currPMV);                                          VECTOR * const currPMV);
143    
144    
145    typedef int32_t (MainSearch16Func)(
146            const uint8_t * const pRef,
147            const uint8_t * const pRefH,
148            const uint8_t * const pRefV,
149            const uint8_t * const pRefHV,
150            const uint8_t * const cur,
151            const int x, const int y,
152            int32_t startx, int32_t starty,
153            int32_t iMinSAD,
154            VECTOR * const currMV,
155            const VECTOR * const pmv,
156            const int32_t min_dx, const int32_t max_dx,
157            const int32_t min_dy, const int32_t max_dy,
158            const int32_t iEdgedWidth,
159            const int32_t iDiamondSize,
160            const int32_t iFcode,
161            const int32_t iQuant,
162            int iFound);
163    
164  /* diamond search stuff  typedef MainSearch16Func* MainSearch16FuncPtr;
    keep the the sequence in circular order (so optimization works)  
 */  
165    
 typedef struct  
 {  
         int32_t dx;  
         int32_t dy;  
 }  
 DPOINT;  
166    
167    typedef int32_t (MainSearch8Func)(
168            const uint8_t * const pRef,
169            const uint8_t * const pRefH,
170            const uint8_t * const pRefV,
171            const uint8_t * const pRefHV,
172            const uint8_t * const cur,
173            const int x, const int y,
174            int32_t startx, int32_t starty,
175            int32_t iMinSAD,
176            VECTOR * const currMV,
177            const VECTOR * const pmv,
178            const int32_t min_dx, const int32_t max_dx,
179            const int32_t min_dy, const int32_t max_dy,
180            const int32_t iEdgedWidth,
181            const int32_t iDiamondSize,
182            const int32_t iFcode,
183            const int32_t iQuant,
184            int iFound);
185    
186  static const DPOINT diamond_small[4] =  typedef MainSearch8Func* MainSearch8FuncPtr;
 {  
         {0, 1}, {1, 0}, {0, -1}, {-1, 0}  
 };  
187    
188    static int32_t lambda_vec16[32] =  /* rounded values for lambda param for weight of motion bits as in modified H.26L */
189            {     0    ,(int)(1.00235+0.5), (int)(1.15582+0.5), (int)(1.31976+0.5), (int)(1.49591+0.5), (int)(1.68601+0.5),
190            (int)(1.89187+0.5), (int)(2.11542+0.5), (int)(2.35878+0.5), (int)(2.62429+0.5), (int)(2.91455+0.5),
191            (int)(3.23253+0.5), (int)(3.58158+0.5), (int)(3.96555+0.5), (int)(4.38887+0.5), (int)(4.85673+0.5),
192            (int)(5.37519+0.5), (int)(5.95144+0.5), (int)(6.59408+0.5), (int)(7.31349+0.5), (int)(8.12242+0.5),
193            (int)(9.03669+0.5), (int)(10.0763+0.5), (int)(11.2669+0.5), (int)(12.6426+0.5), (int)(14.2493+0.5),
194            (int)(16.1512+0.5), (int)(18.442+0.5),  (int)(21.2656+0.5), (int)(24.8580+0.5), (int)(29.6436+0.5),
195            (int)(36.4949+0.5)      };
196    
197    static int32_t *lambda_vec8 = lambda_vec16;     /* same table for INTER and INTER4V for now*/
198    
 static const DPOINT diamond_large[8] =  
 {  
         {0, 2}, {1, 1}, {2, 0}, {1, -1}, {0, -2}, {-1, -1}, {-2, 0}, {-1, 1}  
 };  
199    
200    
201  // mv.length table  // mv.length table
# Line 159  Line 233 
233  }  }
234    
235    
236  static __inline uint32_t calc_delta_16(const int32_t dx, const int32_t dy, const uint32_t iFcode)  static __inline uint32_t calc_delta_16(const int32_t dx, const int32_t dy, const uint32_t iFcode, const uint32_t iQuant)
 {  
         return NEIGH_TEND_16X16 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));  
 }  
   
 static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode)  
   
237  {  {
238      return NEIGH_TEND_8X8 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));          return NEIGH_TEND_16X16 * lambda_vec16[iQuant] * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));
239  }  }
240    
241    static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode, const uint32_t iQuant)
242    
   
   
 /* 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)  
243  {  {
244          const int search_range = 32 << (fcode - 1);      return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));
     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));  
245  }  }
246    
247    
 /* 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;  
         }  
 }  
   
248    
 /* This is somehow a copy of get_ref, but with MV instead of X,Y */  
249    
 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;  
         }  
 }  
250    
251  #ifndef SEARCH16  #ifndef SEARCH16
252  #define SEARCH16        PMVfastSearch16  #define SEARCH16        PMVfastSearch16
253    //#define SEARCH16      FullSearch16
254    //#define SEARCH16      EPZSSearch16
255  #endif  #endif
256    
257  #ifndef SEARCH8  #ifndef SEARCH8
258  #define SEARCH8         PMVfastSearch8  #define SEARCH8         PMVfastSearch8
259    //#define SEARCH8       EPZSSearch8
260  #endif  #endif
261    
262  bool MotionEstimation(  bool MotionEstimation(
                         MACROBLOCK * const pMBs,  
263                          MBParam * const pParam,                          MBParam * const pParam,
264                      const IMAGE * const pRef,          FRAMEINFO * const current,
265            FRAMEINFO * const reference,
266                          const IMAGE * const pRefH,                          const IMAGE * const pRefH,
267                      const IMAGE * const pRefV,                      const IMAGE * const pRefV,
268                          const IMAGE * const pRefHV,                          const IMAGE * const pRefHV,
                     IMAGE * const pCurrent,  
269                          const uint32_t iLimit)                          const uint32_t iLimit)
270    
271  {  {
272      const uint32_t iWcount = pParam->mb_width;      const uint32_t iWcount = pParam->mb_width;
273      const uint32_t iHcount = pParam->mb_height;      const uint32_t iHcount = pParam->mb_height;
274            MACROBLOCK * pMBs = current->mbs;
275            IMAGE * pCurrent = &current->image;
276    
277            MACROBLOCK * prevMBs = reference->mbs;  // previous frame
278            IMAGE * pRef = &reference->image;
279    
280    
281          uint32_t i, j, iIntra = 0;          uint32_t i, j, iIntra = 0;
282    
# Line 282  Line 287 
287      int32_t sad16;      int32_t sad16;
288      int32_t deviation;      int32_t deviation;
289    
290            if (sadInit)
291                    (*sadInit)();
292    
293          // note: i==horizontal, j==vertical          // note: i==horizontal, j==vertical
294      for (i = 0; i < iHcount; i++)      for (i = 0; i < iHcount; i++)
295                  for (j = 0; j < iWcount; j++)                  for (j = 0; j < iWcount; j++)
296                  {                  {
297                          MACROBLOCK *pMB = &pMBs[j + i * iWcount];                          MACROBLOCK *pMB = &pMBs[j + i * iWcount];
298                            MACROBLOCK *prevMB = &prevMBs[j + i * iWcount];
299    
300                          sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                          sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
301                                            j, i, pParam->motion_flags,                                           j, i, current->motion_flags, current->quant, current->fcode,
302                                            pParam, pMBs, &mv16, &pmv16);                                           pParam, pMBs, prevMBs, &mv16, &pmv16);
303                          pMB->sad16=sad16;                          pMB->sad16=sad16;
304    
305    
# Line 306  Line 315 
315                          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;
316                          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;
317    
318                                    pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = 0;
319    
320                          iIntra++;                          iIntra++;
321                          if(iIntra >= iLimit)                          if(iIntra >= iLimit)
322                                  return 1;                                  return 1;
# Line 313  Line 324 
324                          continue;                          continue;
325                  }                  }
326    
327                  if (pParam->global_flags & XVID_INTER4V)                          if (current->global_flags & XVID_INTER4V)
328                  {                  {
329                          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,
330                                          2 * j, 2 * i, mv16.x, mv16.y, pParam->motion_flags,                                                         2 * j, 2 * i, mv16.x, mv16.y,
331                                          pParam, pMBs, &pMB->mvs[0], &pMB->pmvs[0]);                                                             current->motion_flags, current->quant, current->fcode,
332                                                           pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]);
333    
334                          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,
335                                          2 * j + 1, 2 * i, mv16.x, mv16.y, pParam->motion_flags,                                                         2 * j + 1, 2 * i, mv16.x, mv16.y,
336                                          pParam, pMBs, &pMB->mvs[1], &pMB->pmvs[1]);                                                             current->motion_flags, current->quant, current->fcode,
337                                                           pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]);
338    
339                          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,
340                                          2 * j, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,                                                         2 * j, 2 * i + 1, mv16.x, mv16.y,
341                                          pParam, pMBs, &pMB->mvs[2], &pMB->pmvs[2]);                                                             current->motion_flags, current->quant, current->fcode,
342                                                           pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]);
343    
344                          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,
345                                          2 * j + 1, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,                                                         2 * j + 1, 2 * i + 1, mv16.x, mv16.y,
346                                          pParam, pMBs, &pMB->mvs[3], &pMB->pmvs[3]);                                                             current->motion_flags, current->quant, current->fcode,
347                                                           pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]);
348    
349                          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];
350                  }                  }
# Line 339  Line 354 
354                          mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v                          mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v
355                  */                  */
356    
357                  if (pMB->dquant == NO_CHANGE) {                          if (!(current->global_flags & XVID_LUMIMASKING) || pMB->dquant == NO_CHANGE)
358                          if (((pParam->global_flags & XVID_INTER4V)==0) ||                          {
359                                  (sad16 < (sad8 + (int32_t)(IMV16X16 * pParam->quant)))) {                                  if (((current->global_flags & XVID_INTER4V)==0) ||
360                                        (sad16 < (sad8 + (int32_t)(IMV16X16 * current->quant))))
361                                    {
362    
363                                  sad8 = sad16;                                  sad8 = sad16;
364                                  pMB->mode = MODE_INTER;                                  pMB->mode = MODE_INTER;
365                                  pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;                                  pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;
366                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;
367                                            pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = sad16;
368                                  pMB->pmvs[0].x = pmv16.x;                                  pMB->pmvs[0].x = pmv16.x;
369                                  pMB->pmvs[0].y = pmv16.y;                                  pMB->pmvs[0].y = pmv16.y;
370                          }                          }
371                          else                          else
372                                    {
373                                  pMB->mode = MODE_INTER4V;                                  pMB->mode = MODE_INTER4V;
374                                            pMB->sad8[0] *= 4;
375                                            pMB->sad8[1] *= 4;
376                                            pMB->sad8[2] *= 4;
377                                            pMB->sad8[3] *= 4;
378                                    }
379                  }                  }
380                  else                  else
381                  {                  {
# Line 359  Line 383 
383                          pMB->mode = MODE_INTER;                          pMB->mode = MODE_INTER;
384                          pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;                          pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;
385                          pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;                          pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;
386                                    pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = sad16;
387    
388                          pMB->pmvs[0].x = pmv16.x;                          pMB->pmvs[0].x = pmv16.x;
389                          pMB->pmvs[0].y = pmv16.y;                          pMB->pmvs[0].y = pmv16.y;
390                  }                  }
# Line 377  Line 403 
403      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
404    { \    { \
405      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); \
406      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; \  
407      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
408      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
409  }  }
410    
411    #define NOCHECK_MV16_CANDIDATE(X,Y) { \
412        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
413        iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
414        if (iSAD < iMinSAD) \
415        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
416    }
417    
418  #define CHECK_MV16_CANDIDATE(X,Y) { \  #define CHECK_MV16_CANDIDATE(X,Y) { \
419    if ( ((X) <= max_dx) && ((X) >= min_dx) \    if ( ((X) <= max_dx) && ((X) >= min_dx) \
420      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
421    { \    { \
422      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
423      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
424      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
425      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
426  }  }
# Line 400  Line 430 
430      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
431    { \    { \
432      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
433      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
434      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
435      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
436  }  }
# Line 410  Line 440 
440      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
441    { \    { \
442      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
443      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
444      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
445      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
446  }  }
# Line 418  Line 448 
448    
449  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
450    iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \    iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \
451    iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\    iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\
452    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
453    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
454  }  }
455    
456    #define NOCHECK_MV8_CANDIDATE(X,Y) \
457      { \
458        iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
459        iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
460        if (iSAD < iMinSAD) \
461        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
462    }
463    
464  #define CHECK_MV8_CANDIDATE(X,Y) { \  #define CHECK_MV8_CANDIDATE(X,Y) { \
465    if ( ((X) <= max_dx) && ((X) >= min_dx) \    if ( ((X) <= max_dx) && ((X) >= min_dx) \
466      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
467    { \    { \
468      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
469      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
470      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
471      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
472  }  }
# Line 439  Line 476 
476      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
477    { \    { \
478      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
479      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
480      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
481      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
482  }  }
# Line 449  Line 486 
486      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
487    { \    { \
488      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
489      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
490      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
491      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
492  }  }
# Line 464  Line 501 
501                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
502                                          const int x, const int y,                                          const int x, const int y,
503                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
504                                            const uint32_t iQuant,
505                                            const uint32_t iFcode,
506                                          MBParam * const pParam,                                          MBParam * const pParam,
507                                          MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
508                                            const MACROBLOCK * const prevMBs,
509                                          VECTOR * const currMV,                                          VECTOR * const currMV,
510                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
511  {  {
512          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
         const int32_t iQuant = pParam->quant;  
513          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
514          int32_t iSAD;          int32_t iSAD;
515          int32_t pred_x,pred_y;          int32_t pred_x,pred_y;
# Line 493  Line 532 
532  }  }
533  */  */
534    
535  int32_t PMVfastSearch16_MainSearch(  int32_t Diamond16_MainSearch(
536                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
537                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
538                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
# Line 550  Line 589 
589          return iMinSAD;          return iMinSAD;
590  }  }
591    
592  int32_t PMVfastSearch16_Refine(  int32_t Square16_MainSearch(
593                                            const uint8_t * const pRef,
594                                            const uint8_t * const pRefH,
595                                            const uint8_t * const pRefV,
596                                            const uint8_t * const pRefHV,
597                                            const uint8_t * const cur,
598                                            const int x, const int y,
599                                            int32_t startx, int32_t starty,
600                                            int32_t iMinSAD,
601                                            VECTOR * const currMV,
602                                            const VECTOR * const pmv,
603                                            const int32_t min_dx, const int32_t max_dx,
604                                            const int32_t min_dy, const int32_t max_dy,
605                                            const int32_t iEdgedWidth,
606                                            const int32_t iDiamondSize,
607                                            const int32_t iFcode,
608                                            const int32_t iQuant,
609                                            int iFound)
610    {
611    /* Do a square search around given starting point, return SAD of best */
612    
613            int32_t iDirection=0;
614            int32_t iSAD;
615            VECTOR backupMV;
616            backupMV.x = startx;
617            backupMV.y = starty;
618    
619    /* It's one search with full square pattern, and new parts for all following diamonds */
620    
621    /*   new direction are extra, so 1-4 is normal diamond
622          537
623          1*2
624          648
625    */
626    
627            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
628            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
629            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
630            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
631    
632            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
633            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
634            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
635            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
636    
637    
638            if (iDirection)
639                    while (!iFound)
640                    {
641                            iFound = 1;
642                            backupMV=*currMV;
643    
644                            switch (iDirection)
645                            {
646                                    case 1:
647                                            CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
648                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
649                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
650                                            break;
651                                    case 2:
652                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
653                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
654                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
655                                            break;
656    
657                                    case 3:
658                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
659                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
660                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
661                                            break;
662    
663                                    case 4:
664                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
665                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
666                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
667                                            break;
668    
669                                    case 5:
670                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
671                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
672                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
673                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
674                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
675                                            break;
676    
677                                    case 6:
678                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
679                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
680    
681                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
682                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
683                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
684    
685                                            break;
686    
687                                    case 7:
688                                            CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
689                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
690                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
691                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
692                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
693                                            break;
694    
695                                    case 8:
696                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
697                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
698                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
699                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
700                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
701                                            break;
702                            default:
703                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
704                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
705                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
706                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
707    
708                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
709                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
710                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
711                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
712                                            break;
713                            }
714                    }
715            else
716                    {
717                            currMV->x = startx;
718                            currMV->y = starty;
719                    }
720            return iMinSAD;
721    }
722    
723    
724    int32_t Full16_MainSearch(
725                                            const uint8_t * const pRef,
726                                            const uint8_t * const pRefH,
727                                            const uint8_t * const pRefV,
728                                            const uint8_t * const pRefHV,
729                                            const uint8_t * const cur,
730                                            const int x, const int y,
731                                            int32_t startx, int32_t starty,
732                                            int32_t iMinSAD,
733                                            VECTOR * const currMV,
734                                            const VECTOR * const pmv,
735                                            const int32_t min_dx, const int32_t max_dx,
736                                            const int32_t min_dy, const int32_t max_dy,
737                                            const int32_t iEdgedWidth,
738                                            const int32_t iDiamondSize,
739                                            const int32_t iFcode,
740                                            const int32_t iQuant,
741                                            int iFound)
742    {
743            int32_t iSAD;
744            int32_t dx,dy;
745            VECTOR backupMV;
746            backupMV.x = startx;
747            backupMV.y = starty;
748    
749            for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
750                    for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
751                            NOCHECK_MV16_CANDIDATE(dx,dy);
752    
753            return iMinSAD;
754    }
755    
756    int32_t Full8_MainSearch(
757                                            const uint8_t * const pRef,
758                                            const uint8_t * const pRefH,
759                                            const uint8_t * const pRefV,
760                                            const uint8_t * const pRefHV,
761                                            const uint8_t * const cur,
762                                            const int x, const int y,
763                                            int32_t startx, int32_t starty,
764                                            int32_t iMinSAD,
765                                            VECTOR * const currMV,
766                                            const VECTOR * const pmv,
767                                            const int32_t min_dx, const int32_t max_dx,
768                                            const int32_t min_dy, const int32_t max_dy,
769                                            const int32_t iEdgedWidth,
770                                            const int32_t iDiamondSize,
771                                            const int32_t iFcode,
772                                            const int32_t iQuant,
773                                            int iFound)
774    {
775            int32_t iSAD;
776            int32_t dx,dy;
777            VECTOR backupMV;
778            backupMV.x = startx;
779            backupMV.y = starty;
780    
781            for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
782                    for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
783                            NOCHECK_MV8_CANDIDATE(dx,dy);
784    
785            return iMinSAD;
786    }
787    
788    
789    
790    int32_t Halfpel16_Refine(
791                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
792                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
793                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
# Line 585  Line 822 
822    
823  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
824    
825    
826  int32_t PMVfastSearch16(  int32_t PMVfastSearch16(
827                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
828                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
# Line 593  Line 831 
831                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
832                                          const int x, const int y,                                          const int x, const int y,
833                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
834                                          MBParam * const pParam,                                          const uint32_t iQuant,
835                                          MACROBLOCK * const pMBs,                                          const uint32_t iFcode,
836                                            const MBParam * const pParam,
837                                            const MACROBLOCK * const pMBs,
838                                            const MACROBLOCK * const prevMBs,
839                                          VECTOR * const currMV,                                          VECTOR * const currMV,
840                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
841  {  {
842          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;  
843          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
844          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
845          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 622  Line 861 
861          VECTOR pmv[4];          VECTOR pmv[4];
862          int32_t psad[4];          int32_t psad[4];
863    
864          MACROBLOCK * const pMB = pMBs + x + y * iWcount;          const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
865            const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
866    
867          static int32_t threshA,threshB;          static int32_t threshA,threshB;
868          int32_t bPredEq;          int32_t bPredEq;
# Line 661  Line 901 
901    
902          iFound=0;          iFound=0;
903    
904  /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  /* Step 4: Calculate SAD around the Median prediction.
905          vector of the median.     MinSAD=SAD
906          If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2     If Motion Vector equal to Previous frame motion vector
907       and MinSAD<PrevFrmSAD goto Step 10.
908       If SAD<=256 goto Step 10.
909  */  */
910    
911          if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[0]) ) )          *currMV=pmv[0];         /* current best := prediction */
912                  iFound=2;          if (!(MotionFlags & PMV_HALFPEL16 ))
913            {       /* This should NOT be necessary! */
914  /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.                  currMV->x = EVEN(currMV->x);
915          Otherwise select large Diamond Search.                  currMV->y = EVEN(currMV->y);
916  */          }
   
         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;  
   
 /* Step 4: Calculate SAD around the Median prediction.  
         MinSAD=SAD  
         If Motion Vector equal to Previous frame motion vector  
                 and MinSAD<PrevFrmSAD goto Step 10.  
         If SAD<=256 goto Step 10.  
 */  
   
   
 // Prepare for main loop  
   
         *currMV=pmv[0];         /* current best := prediction */  
         if (!(MotionFlags & PMV_HALFPEL16 ))  
         {       /* This should NOT be necessary! */  
                 currMV->x = EVEN(currMV->x);  
                 currMV->y = EVEN(currMV->y);  
         }  
917    
918          if (currMV->x > max_dx)          if (currMV->x > max_dx)
919                  {                  {
# Line 718  Line 935 
935          iMinSAD = sad16( cur,          iMinSAD = sad16( cur,
936                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
937                  iEdgedWidth, MV_MAX_ERROR);                  iEdgedWidth, MV_MAX_ERROR);
938          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);
939    
940          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
941            {
942                    if (iMinSAD < 2*iQuant) // high chances for SKIP-mode
943                    {
944                            if (!MVzero(*currMV))
945                  {                  {
946                                    iMinSAD += MV16_00_BIAS;
947                                    CHECK_MV16_ZERO;                // (0,0) saves space for letterboxed pictures
948                                    iMinSAD -= MV16_00_BIAS;
949                            }
950                    }
951    
952                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
953                                  goto step10b;                          goto PMVfast16_Terminate_without_Refine;
954                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
955                                  goto step10;                          goto PMVfast16_Terminate_with_Refine;
956                  }                  }
957    
958    
959    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
960       vector of the median.
961       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
962    */
963    
964            if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[0]) ) )
965                    iFound=2;
966    
967    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
968       Otherwise select large Diamond Search.
969    */
970    
971            if ( (!MVzero(pmv[0])) || (threshB<1536) || (bPredEq) )
972                    iDiamondSize=1; // halfpel!
973            else
974                    iDiamondSize=2; // halfpel!
975    
976            if (!(MotionFlags & PMV_HALFPELDIAMOND16) )
977                    iDiamondSize*=2;
978    
979  /*  /*
980  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.
981          Also calculate (0,0) but do not subtract offset.          Also calculate (0,0) but do not subtract offset.
982          Let MinSAD be the smallest SAD up to this point.          Let MinSAD be the smallest SAD up to this point.
983          If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
984  */  */
985    
986  // (0,0) is always possible  // (0,0) is always possible
987    
988            if (!MVzero(pmv[0]))
989          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
990    
991  // previous frame MV is always possible  // previous frame MV is always possible
992          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);  
993            if (!MVzero(prevMB->mvs[0]))
994            if (!MVequal(prevMB->mvs[0],pmv[0]))
995                    CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
996    
997  // left neighbour, if allowed  // left neighbour, if allowed
998          if (x != 0)  
999            if (!MVzero(pmv[1]))
1000            if (!MVequal(pmv[1],prevMB->mvs[0]))
1001            if (!MVequal(pmv[1],pmv[0]))
1002          {          {
1003                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!(MotionFlags & PMV_HALFPEL16 ))
1004                  {       pmv[1].x = EVEN(pmv[1].x);                  {       pmv[1].x = EVEN(pmv[1].x);
1005                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
1006                  }                  }
1007    
1008                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1009          }          }
1010    
1011  // top neighbour, if allowed  // top neighbour, if allowed
1012          if (y != 0)          if (!MVzero(pmv[2]))
1013            if (!MVequal(pmv[2],prevMB->mvs[0]))
1014            if (!MVequal(pmv[2],pmv[0]))
1015            if (!MVequal(pmv[2],pmv[1]))
1016          {          {
1017                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!(MotionFlags & PMV_HALFPEL16 ))
1018                  {       pmv[2].x = EVEN(pmv[2].x);                  {       pmv[2].x = EVEN(pmv[2].x);
# Line 763  Line 1021 
1021                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1022    
1023  // top right neighbour, if allowed  // top right neighbour, if allowed
1024                  if (x != (iWcount-1))                  if (!MVzero(pmv[3]))
1025                    if (!MVequal(pmv[3],prevMB->mvs[0]))
1026                    if (!MVequal(pmv[3],pmv[0]))
1027                    if (!MVequal(pmv[3],pmv[1]))
1028                    if (!MVequal(pmv[3],pmv[2]))
1029                  {                  {
1030                          if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!(MotionFlags & PMV_HALFPEL16 ))
1031                          {       pmv[3].x = EVEN(pmv[3].x);                          {       pmv[3].x = EVEN(pmv[3].x);
# Line 773  Line 1035 
1035                  }                  }
1036          }          }
1037    
1038            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96)*/ )
1039                    iMinSAD -= MV16_00_BIAS;
1040    
1041    
1042  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1043     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.
1044  */  */
1045    
1046          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
1047                  {                  {
1048                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
1049                                  goto step10b;                          goto PMVfast16_Terminate_without_Refine;
1050                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
1051                                  goto step10;                          goto PMVfast16_Terminate_with_Refine;
1052                  }                  }
1053    
1054    
# Line 799  Line 1065 
1065          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1066    
1067  /* 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 */
1068          iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1069                  x, y,                  x, y,
1070                  currMV->x, currMV->y, iMinSAD, &newMV,                  currMV->x, currMV->y, iMinSAD, &newMV,
1071                  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 815  Line 1081 
1081  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1082    
1083                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0],backupMV)) )
1084                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1085                                  x, y,                                  x, y,
1086                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1087                          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 828  Line 1094 
1094                  }                  }
1095    
1096                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1097                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1098                                  x, y,                                  x, y,
1099                          0, 0, iMinSAD, &newMV,                          0, 0, iMinSAD, &newMV,
1100                          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 845  Line 1111 
1111          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.
1112  */  */
1113    
1114  step10:  PMVfast16_Terminate_with_Refine:
1115          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1116                  iMinSAD = PMVfastSearch16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1117                                  x, y,                                  x, y,
1118                                  currMV, iMinSAD,                                  currMV, iMinSAD,
1119                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1120    
1121  step10b:  PMVfast16_Terminate_without_Refine:
1122          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1123          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
1124          return iMinSAD;          return iMinSAD;
# Line 863  Line 1129 
1129    
1130    
1131    
1132  int32_t PMVfastSearch8_MainSearch(  int32_t Diamond8_MainSearch(
1133                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
1134                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1135                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
# Line 920  Line 1186 
1186          return iMinSAD;          return iMinSAD;
1187  }  }
1188    
1189  int32_t PMVfastSearch8_Refine(  int32_t Halfpel8_Refine(
1190                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
1191                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1192                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
# Line 963  Line 1229 
1229                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1230                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1231                                          const int x, const int y,                                          const int x, const int y,
1232                                          const int start_x, int start_y,                                          const int start_x, const int start_y,
1233                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1234                                          MBParam * const pParam,                                          const uint32_t iQuant,
1235                                          MACROBLOCK * const pMBs,                                          const uint32_t iFcode,
1236                                            const MBParam * const pParam,
1237                                            const MACROBLOCK * const pMBs,
1238                                            const MACROBLOCK * const prevMBs,
1239                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1240                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
1241  {  {
1242          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;  
1243          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1244          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
1245          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 991  Line 1257 
1257          int32_t psad[4];          int32_t psad[4];
1258          VECTOR newMV;          VECTOR newMV;
1259          VECTOR backupMV;          VECTOR backupMV;
1260            VECTOR startMV = { start_x, start_y };
1261    
1262          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1263            const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1264    
1265          static int32_t threshA,threshB;          static int32_t threshA,threshB;
1266          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
1267          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1268    
1269          int32_t iSubBlock = ((y&1)<<1) + (x&1);          int32_t iSubBlock = (y&1)+(y&1) + (x&1);
1270    
1271  /* Get maximum range */  /* Get maximum range */
1272      get_range(&min_dx, &max_dx, &min_dy, &max_dy,      get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1273                          x, y, 8, iWidth, iHeight, iFcode);                          x, y, 8, iWidth, iHeight, iFcode);
1274    
 /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */  
   
1275          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))
1276          { min_dx = EVEN(min_dx);          { min_dx = EVEN(min_dx);
1277            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
# Line 1033  Line 1299 
1299    
1300          iFound=0;          iFound=0;
1301    
 /* 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[iSubBlock]) ) )  
                 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/4) || (bPredEq) )  
                 iDiamondSize=1; // 1 halfpel!  
         else  
                 iDiamondSize=2; // 2 halfpel = 1 full pixel!  
   
         if (!(MotionFlags & PMV_HALFPELDIAMOND8) )  
                 iDiamondSize*=2;  
   
1302  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1303          MinSAD=SAD          MinSAD=SAD
1304          If Motion Vector equal to Previous frame motion vector          If Motion Vector equal to Previous frame motion vector
# Line 1063  Line 1309 
1309    
1310  // Prepare for main loop  // Prepare for main loop
1311    
1312          currMV->x=start_x;              /* start with mv16 */          *currMV = startMV;
         currMV->y=start_y;  
1313    
1314          iMinSAD = sad8( cur,          iMinSAD = sad8( cur,
1315                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
1316                  iEdgedWidth);                  iEdgedWidth);
1317          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);
1318    
1319          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock]))
1320                                    && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1321                  {                  {
1322                          if (MotionFlags & PMV_QUICKSTOP8)                  if (MotionFlags & PMV_QUICKSTOP16)
1323                                  goto step10_8b;                          goto PMVfast8_Terminate_without_Refine;
1324                          if (MotionFlags & PMV_EARLYSTOP8)                  if (MotionFlags & PMV_EARLYSTOP16)
1325                                  goto step10_8;                          goto PMVfast8_Terminate_with_Refine;
1326                  }                  }
1327    
1328    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1329       vector of the median.
1330       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1331    */
1332    
1333            if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[iSubBlock]) ) )
1334                    iFound=2;
1335    
1336    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1337       Otherwise select large Diamond Search.
1338    */
1339    
1340            if ( (!MVzero(pmv[0])) || (threshB<1536/4) || (bPredEq) )
1341                    iDiamondSize=1; // 1 halfpel!
1342            else
1343                    iDiamondSize=2; // 2 halfpel = 1 full pixel!
1344    
1345            if (!(MotionFlags & PMV_HALFPELDIAMOND8) )
1346                    iDiamondSize*=2;
1347    
1348    
1349  /*  /*
1350  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.
1351          Also calculate (0,0) but do not subtract offset.          Also calculate (0,0) but do not subtract offset.
1352          Let MinSAD be the smallest SAD up to this point.          Let MinSAD be the smallest SAD up to this point.
1353          If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1354  */  */
1355    
1356  // the prediction might be even better than mv16  // the median prediction might be even better than mv16
1357    
1358            if (!MVequal(pmv[0],startMV))
1359          CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);          CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);
1360    
1361  // (0,0) is always possible  // (0,0) if needed
1362            if (!MVzero(pmv[0]))
1363            if (!MVzero(startMV))
1364          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
1365    
1366  // previous frame MV is always possible  // previous frame MV if needed
1367          CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);          if (!MVzero(prevMB->mvs[iSubBlock]))
1368            if (!MVequal(prevMB->mvs[iSubBlock],startMV))
1369            if (!MVequal(prevMB->mvs[iSubBlock],pmv[0]))
1370            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
1371    
1372  // left neighbour, if allowed          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1373          if (psad[1] != MV_MAX_ERROR)          {
1374                    if (MotionFlags & PMV_QUICKSTOP16)
1375                            goto PMVfast8_Terminate_without_Refine;
1376                    if (MotionFlags & PMV_EARLYSTOP16)
1377                            goto PMVfast8_Terminate_with_Refine;
1378            }
1379    
1380    
1381    // left neighbour, if allowed and needed
1382            if (!MVzero(pmv[1]))
1383            if (!MVequal(pmv[1],startMV))
1384            if (!MVequal(pmv[1],prevMB->mvs[iSubBlock]))
1385            if (!MVequal(pmv[1],pmv[0]))
1386          {          {
1387                  if (!(MotionFlags & PMV_HALFPEL8 ))                  if (!(MotionFlags & PMV_HALFPEL8 ))
1388                  {       pmv[1].x = EVEN(pmv[1].x);                  {       pmv[1].x = EVEN(pmv[1].x);
# Line 1105  Line 1391 
1391                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1392          }          }
1393    
1394  // top neighbour, if allowed  // top neighbour, if allowed and needed
1395          if (psad[2] != MV_MAX_ERROR)          if (!MVzero(pmv[2]))
1396            if (!MVequal(pmv[2],startMV))
1397            if (!MVequal(pmv[2],prevMB->mvs[iSubBlock]))
1398            if (!MVequal(pmv[2],pmv[0]))
1399            if (!MVequal(pmv[2],pmv[1]))
1400          {          {
1401                  if (!(MotionFlags & PMV_HALFPEL8 ))                  if (!(MotionFlags & PMV_HALFPEL8 ))
1402                  {       pmv[2].x = EVEN(pmv[2].x);                  {       pmv[2].x = EVEN(pmv[2].x);
# Line 1114  Line 1404 
1404                  }                  }
1405                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1406    
1407  // top right neighbour, if allowed  // top right neighbour, if allowed and needed
1408                  if (psad[3] != MV_MAX_ERROR)          if (!MVzero(pmv[3]))
1409            if (!MVequal(pmv[3],startMV))
1410            if (!MVequal(pmv[3],prevMB->mvs[iSubBlock]))
1411            if (!MVequal(pmv[3],pmv[0]))
1412            if (!MVequal(pmv[3],pmv[1]))
1413            if (!MVequal(pmv[3],pmv[2]))
1414                  {                  {
1415                  if (!(MotionFlags & PMV_HALFPEL8 ))                  if (!(MotionFlags & PMV_HALFPEL8 ))
1416                  {       pmv[3].x = EVEN(pmv[3].x);                  {       pmv[3].x = EVEN(pmv[3].x);
# Line 1125  Line 1420 
1420                  }                  }
1421          }          }
1422    
1423            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1424                    iMinSAD -= MV8_00_BIAS;
1425    
1426    
1427  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1428     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.
1429  */  */
1430    
1431          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]) ) )
1432                  {                  {
1433                          if (MotionFlags & PMV_QUICKSTOP8)                  if (MotionFlags & PMV_QUICKSTOP16)
1434                                  goto step10_8b;                          goto PMVfast8_Terminate_without_Refine;
1435                          if (MotionFlags & PMV_EARLYSTOP8)                  if (MotionFlags & PMV_EARLYSTOP16)
1436                                  goto step10_8;                          goto PMVfast8_Terminate_with_Refine;
1437                  }                  }
1438    
1439  /************ (Diamond Search)  **************/  /************ (Diamond Search)  **************/
# Line 1150  Line 1449 
1449          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1450    
1451  /* 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 */
1452          iSAD = PMVfastSearch8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1453                  x, y,                  x, y,
1454                  currMV->x, currMV->y, iMinSAD, &newMV,                  currMV->x, currMV->y, iMinSAD, &newMV,
1455                  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 1166  Line 1465 
1465  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1466    
1467                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0],backupMV)) )
1468                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1469                                  x, y,                                  x, y,
1470                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1471                          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 1179  Line 1478 
1478                  }                  }
1479    
1480                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1481                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1482                                  x, y,                                  x, y,
1483                          0, 0, iMinSAD, &newMV,                          0, 0, iMinSAD, &newMV,
1484                          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 1196  Line 1495 
1495           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.
1496  */  */
1497    
1498  step10_8:  PMVfast8_Terminate_with_Refine:
1499          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
1500                  iMinSAD = PMVfastSearch8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1501                                  x, y,                                  x, y,
1502                                  currMV, iMinSAD,                                  currMV, iMinSAD,
1503                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1504    
 step10_8b:  
1505    
1506    PMVfast8_Terminate_without_Refine:
1507          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1508          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
1509    
1510          return iMinSAD;          return iMinSAD;
1511  }  }
1512    
1513    int32_t EPZSSearch16(
1514                                            const uint8_t * const pRef,
1515                                            const uint8_t * const pRefH,
1516                                            const uint8_t * const pRefV,
1517                                            const uint8_t * const pRefHV,
1518                                            const IMAGE * const pCur,
1519                                            const int x, const int y,
1520                                            const uint32_t MotionFlags,
1521                                            const uint32_t iQuant,
1522                                            const uint32_t iFcode,
1523                                            const MBParam * const pParam,
1524                                            const MACROBLOCK * const pMBs,
1525                                            const MACROBLOCK * const prevMBs,
1526                                            VECTOR * const currMV,
1527                                            VECTOR * const currPMV)
1528    {
1529        const uint32_t iWcount = pParam->mb_width;
1530        const uint32_t iHcount = pParam->mb_height;
1531    
1532            const int32_t iWidth = pParam->width;
1533            const int32_t iHeight = pParam->height;
1534            const int32_t iEdgedWidth = pParam->edged_width;
1535    
1536            const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
1537    
1538            int32_t min_dx;
1539            int32_t max_dx;
1540            int32_t min_dy;
1541            int32_t max_dy;
1542    
1543            VECTOR newMV;
1544            VECTOR backupMV;
1545    
1546            VECTOR pmv[4];
1547            int32_t psad[8];
1548    
1549            static MACROBLOCK * oldMBs = NULL;
1550            const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
1551            const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1552            MACROBLOCK * oldMB = NULL;
1553    
1554            static int32_t thresh2;
1555            int32_t bPredEq;
1556            int32_t iMinSAD,iSAD=9999;
1557    
1558            MainSearch16FuncPtr EPZSMainSearchPtr;
1559    
1560            if (oldMBs == NULL)
1561            {       oldMBs = (MACROBLOCK*) calloc(iWcount*iHcount,sizeof(MACROBLOCK));
1562    //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
1563            }
1564            oldMB = oldMBs + x + y * iWcount;
1565    
1566    /* Get maximum range */
1567            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1568                            x, y, 16, iWidth, iHeight, iFcode);
1569    
1570            if (!(MotionFlags & PMV_HALFPEL16 ))
1571            { min_dx = EVEN(min_dx);
1572              max_dx = EVEN(max_dx);
1573              min_dy = EVEN(min_dy);
1574              max_dy = EVEN(max_dy);
1575            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1576    
1577            bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1578    
1579    /* Step 4: Calculate SAD around the Median prediction.
1580            MinSAD=SAD
1581            If Motion Vector equal to Previous frame motion vector
1582                    and MinSAD<PrevFrmSAD goto Step 10.
1583            If SAD<=256 goto Step 10.
1584    */
1585    
1586    // Prepare for main loop
1587    
1588            *currMV=pmv[0];         /* current best := median prediction */
1589            if (!(MotionFlags & PMV_HALFPEL16))
1590            {
1591                    currMV->x = EVEN(currMV->x);
1592                    currMV->y = EVEN(currMV->y);
1593            }
1594    
1595            if (currMV->x > max_dx)
1596                    currMV->x=max_dx;
1597            if (currMV->x < min_dx)
1598                    currMV->x=min_dx;
1599            if (currMV->y > max_dy)
1600                    currMV->y=max_dy;
1601            if (currMV->y < min_dy)
1602                    currMV->y=min_dy;
1603    
1604    /***************** This is predictor SET A: only median prediction ******************/
1605    
1606            iMinSAD = sad16( cur,
1607                    get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
1608                    iEdgedWidth, MV_MAX_ERROR);
1609            iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);
1610    
1611    // thresh1 is fixed to 256
1612            if ( (iMinSAD < 256 ) || ( (MVequal(*currMV, prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
1613                    {
1614                            if (MotionFlags & PMV_QUICKSTOP16)
1615                                    goto EPZS16_Terminate_without_Refine;
1616                            if (MotionFlags & PMV_EARLYSTOP16)
1617                                    goto EPZS16_Terminate_with_Refine;
1618                    }
1619    
1620    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1621    
1622    // previous frame MV
1623            CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1624    
1625    // set threshhold based on Min of Prediction and SAD of collocated block
1626    // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
1627    
1628            if ((x==0) && (y==0) )
1629            {
1630                    thresh2 =  512;
1631            }
1632            else
1633            {
1634    /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */
1635    
1636                    thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
1637            }
1638    
1639    // MV=(0,0) is often a good choice
1640    
1641            CHECK_MV16_ZERO;
1642    
1643    
1644    // left neighbour, if allowed
1645            if (x != 0)
1646            {
1647                    if (!(MotionFlags & PMV_HALFPEL16 ))
1648                    {       pmv[1].x = EVEN(pmv[1].x);
1649                            pmv[1].y = EVEN(pmv[1].y);
1650                    }
1651                    CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1652            }
1653    
1654    // top neighbour, if allowed
1655            if (y != 0)
1656            {
1657                    if (!(MotionFlags & PMV_HALFPEL16 ))
1658                    {       pmv[2].x = EVEN(pmv[2].x);
1659                            pmv[2].y = EVEN(pmv[2].y);
1660                    }
1661                    CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1662    
1663    // top right neighbour, if allowed
1664                    if ((uint32_t)x != (iWcount-1))
1665                    {
1666                            if (!(MotionFlags & PMV_HALFPEL16 ))
1667                            {       pmv[3].x = EVEN(pmv[3].x);
1668                                    pmv[3].y = EVEN(pmv[3].y);
1669                            }
1670                            CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
1671                    }
1672            }
1673    
1674    /* Terminate if MinSAD <= T_2
1675       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1676    */
1677    
1678            if ( (iMinSAD <= thresh2)
1679                    || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )
1680                    {
1681                            if (MotionFlags & PMV_QUICKSTOP16)
1682                                    goto EPZS16_Terminate_without_Refine;
1683                            if (MotionFlags & PMV_EARLYSTOP16)
1684                                    goto EPZS16_Terminate_with_Refine;
1685                    }
1686    
1687    /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
1688    
1689            backupMV = prevMB->mvs[0];              // collocated MV
1690            backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x );    // acceleration X
1691            backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y );    // acceleration Y
1692    
1693            CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);
1694    
1695    // left neighbour
1696            if (x != 0)
1697                    CHECK_MV16_CANDIDATE((prevMB-1)->mvs[0].x,(prevMB-1)->mvs[0].y);
1698    
1699    // top neighbour
1700            if (y != 0)
1701                    CHECK_MV16_CANDIDATE((prevMB-iWcount)->mvs[0].x,(prevMB-iWcount)->mvs[0].y);
1702    
1703    // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
1704    
1705            if ((uint32_t)x != iWcount-1)
1706                    CHECK_MV16_CANDIDATE((prevMB+1)->mvs[0].x,(prevMB+1)->mvs[0].y);
1707    
1708    // bottom neighbour, dito
1709            if ((uint32_t)y != iHcount-1)
1710                    CHECK_MV16_CANDIDATE((prevMB+iWcount)->mvs[0].x,(prevMB+iWcount)->mvs[0].y);
1711    
1712    /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
1713            if (iMinSAD <= thresh2)
1714                    {
1715                            if (MotionFlags & PMV_QUICKSTOP16)
1716                                    goto EPZS16_Terminate_without_Refine;
1717                            if (MotionFlags & PMV_EARLYSTOP16)
1718                                    goto EPZS16_Terminate_with_Refine;
1719                    }
1720    
1721    /************ (if Diamond Search)  **************/
1722    
1723            backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1724    
1725    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1726    
1727            if (MotionFlags & PMV_USESQUARES16)
1728                    EPZSMainSearchPtr = Square16_MainSearch;
1729            else
1730                    EPZSMainSearchPtr = Diamond16_MainSearch;
1731    
1732            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1733                            x, y,
1734                            currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1735                            2, iFcode, iQuant, 0);
1736    
1737            if (iSAD < iMinSAD)
1738            {
1739                    *currMV = newMV;
1740                    iMinSAD = iSAD;
1741            }
1742    
1743    
1744            if (MotionFlags & PMV_EXTSEARCH16)
1745            {
1746    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
1747    
1748                    if (!(MVequal(pmv[0],backupMV)) )
1749                    {
1750                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1751                                    x, y,
1752                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1753                                    pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
1754                    }
1755    
1756                    if (iSAD < iMinSAD)
1757                    {
1758                            *currMV = newMV;
1759                            iMinSAD = iSAD;
1760                    }
1761    
1762                    if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1763                    {
1764                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1765                                    x, y,
1766                            0, 0, iMinSAD, &newMV,
1767                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
1768    
1769                            if (iSAD < iMinSAD)
1770                            {
1771                                    *currMV = newMV;
1772                                    iMinSAD = iSAD;
1773                            }
1774                    }
1775            }
1776    
1777    /***************        Choose best MV found     **************/
1778    
1779    EPZS16_Terminate_with_Refine:
1780            if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1781                    iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1782                                    x, y,
1783                                    currMV, iMinSAD,
1784                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1785    
1786    EPZS16_Terminate_without_Refine:
1787    
1788            *oldMB = *prevMB;
1789    
1790            currPMV->x = currMV->x - pmv[0].x;
1791            currPMV->y = currMV->y - pmv[0].y;
1792            return iMinSAD;
1793    }
1794    
1795    
1796    int32_t EPZSSearch8(
1797                                            const uint8_t * const pRef,
1798                                            const uint8_t * const pRefH,
1799                                            const uint8_t * const pRefV,
1800                                            const uint8_t * const pRefHV,
1801                                            const IMAGE * const pCur,
1802                                            const int x, const int y,
1803                                            const int start_x, const int start_y,
1804                                            const uint32_t MotionFlags,
1805                                            const uint32_t iQuant,
1806                                            const uint32_t iFcode,
1807                                            const MBParam * const pParam,
1808                                            const MACROBLOCK * const pMBs,
1809                                            const MACROBLOCK * const prevMBs,
1810                                            VECTOR * const currMV,
1811                                            VECTOR * const currPMV)
1812    {
1813    /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
1814    
1815            const uint32_t iWcount = pParam->mb_width;
1816            const int32_t iWidth = pParam->width;
1817            const int32_t iHeight = pParam->height;
1818            const int32_t iEdgedWidth = pParam->edged_width;
1819    
1820            const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;
1821    
1822            int32_t iDiamondSize=1;
1823    
1824            int32_t min_dx;
1825            int32_t max_dx;
1826            int32_t min_dy;
1827            int32_t max_dy;
1828    
1829            VECTOR newMV;
1830            VECTOR backupMV;
1831    
1832            VECTOR pmv[4];
1833            int32_t psad[8];
1834    
1835            const   int32_t iSubBlock = ((y&1)<<1) + (x&1);
1836    
1837            const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1838            const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1839    
1840            int32_t bPredEq;
1841            int32_t iMinSAD,iSAD=9999;
1842    
1843            MainSearch8FuncPtr EPZSMainSearchPtr;
1844    
1845    /* Get maximum range */
1846            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1847                            x, y, 8, iWidth, iHeight, iFcode);
1848    
1849    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1850    
1851            if (!(MotionFlags & PMV_HALFPEL8 ))
1852            { min_dx = EVEN(min_dx);
1853              max_dx = EVEN(max_dx);
1854              min_dy = EVEN(min_dy);
1855              max_dy = EVEN(max_dy);
1856            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1857    
1858            bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);
1859    
1860    
1861    /* Step 4: Calculate SAD around the Median prediction.
1862            MinSAD=SAD
1863            If Motion Vector equal to Previous frame motion vector
1864                    and MinSAD<PrevFrmSAD goto Step 10.
1865            If SAD<=256 goto Step 10.
1866    */
1867    
1868    // Prepare for main loop
1869    
1870    
1871            if (!(MotionFlags & PMV_HALFPEL8))
1872            {
1873                    currMV->x = EVEN(currMV->x);
1874                    currMV->y = EVEN(currMV->y);
1875            }
1876    
1877            if (currMV->x > max_dx)
1878                    currMV->x=max_dx;
1879            if (currMV->x < min_dx)
1880                    currMV->x=min_dx;
1881            if (currMV->y > max_dy)
1882                    currMV->y=max_dy;
1883            if (currMV->y < min_dy)
1884                    currMV->y=min_dy;
1885    
1886    /***************** This is predictor SET A: only median prediction ******************/
1887    
1888    
1889            iMinSAD = sad8( cur,
1890                    get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
1891                    iEdgedWidth);
1892            iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);
1893    
1894    
1895    // thresh1 is fixed to 256
1896            if (iMinSAD < 256/4 )
1897                    {
1898                            if (MotionFlags & PMV_QUICKSTOP8)
1899                                    goto EPZS8_Terminate_without_Refine;
1900                            if (MotionFlags & PMV_EARLYSTOP8)
1901                                    goto EPZS8_Terminate_with_Refine;
1902                    }
1903    
1904    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1905    
1906    
1907    // MV=(0,0) is often a good choice
1908            CHECK_MV8_ZERO;
1909    
1910    // previous frame MV
1911            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
1912    
1913    // left neighbour, if allowed
1914            if (psad[1] != MV_MAX_ERROR)
1915            {
1916                    if (!(MotionFlags & PMV_HALFPEL8 ))
1917                    {       pmv[1].x = EVEN(pmv[1].x);
1918                            pmv[1].y = EVEN(pmv[1].y);
1919                    }
1920                    CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1921            }
1922    
1923    // top neighbour, if allowed
1924            if (psad[2] != MV_MAX_ERROR)
1925            {
1926                    if (!(MotionFlags & PMV_HALFPEL8 ))
1927                    {       pmv[2].x = EVEN(pmv[2].x);
1928                            pmv[2].y = EVEN(pmv[2].y);
1929                    }
1930                    CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1931    
1932    // top right neighbour, if allowed
1933                    if (psad[3] != MV_MAX_ERROR)
1934                    {
1935                            if (!(MotionFlags & PMV_HALFPEL8 ))
1936                            {       pmv[3].x = EVEN(pmv[3].x);
1937                                    pmv[3].y = EVEN(pmv[3].y);
1938                            }
1939                            CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);
1940                    }
1941            }
1942    
1943    /*  // this bias is zero anyway, at the moment!
1944    
1945            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
1946                    iMinSAD -= MV8_00_BIAS;
1947    
1948    */
1949    
1950    /* Terminate if MinSAD <= T_2
1951       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1952    */
1953    
1954            if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */
1955                    {
1956                            if (MotionFlags & PMV_QUICKSTOP8)
1957                                    goto EPZS8_Terminate_without_Refine;
1958                            if (MotionFlags & PMV_EARLYSTOP8)
1959                                    goto EPZS8_Terminate_with_Refine;
1960                    }
1961    
1962    /************ (Diamond Search)  **************/
1963    
1964            backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1965    
1966            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
1967                    iDiamondSize *= 2;
1968    
1969    /* default: use best prediction as starting point for one call of EPZS_MainSearch */
1970    
1971    /* // there is no EPZS^2 for inter4v at the moment
1972    
1973            if (MotionFlags & PMV_USESQUARES8)
1974                    EPZSMainSearchPtr = Square8_MainSearch;
1975            else
1976    */
1977    
1978            EPZSMainSearchPtr = Diamond8_MainSearch;
1979    
1980            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1981                    x, y,
1982                    currMV->x, currMV->y, iMinSAD, &newMV,
1983                    pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1984                    iDiamondSize, iFcode, iQuant, 0);
1985    
1986    
1987            if (iSAD < iMinSAD)
1988            {
1989                    *currMV = newMV;
1990                    iMinSAD = iSAD;
1991            }
1992    
1993            if (MotionFlags & PMV_EXTSEARCH8)
1994            {
1995    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
1996    
1997                    if (!(MVequal(pmv[0],backupMV)) )
1998                    {
1999                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
2000                                    x, y,
2001                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,
2002                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
2003    
2004                            if (iSAD < iMinSAD)
2005                            {
2006                                    *currMV = newMV;
2007                                    iMinSAD = iSAD;
2008                            }
2009                    }
2010    
2011                    if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
2012                    {
2013                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
2014                                    x, y,
2015                            0, 0, iMinSAD, &newMV,
2016                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
2017    
2018                            if (iSAD < iMinSAD)
2019                            {
2020                                    *currMV = newMV;
2021                                    iMinSAD = iSAD;
2022                            }
2023                    }
2024            }
2025    
2026    /***************        Choose best MV found     **************/
2027    
2028    EPZS8_Terminate_with_Refine:
2029            if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2030                    iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
2031                                    x, y,
2032                                    currMV, iMinSAD,
2033                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
2034    
2035    EPZS8_Terminate_without_Refine:
2036    
2037            currPMV->x = currMV->x - pmv[0].x;
2038            currPMV->y = currMV->y - pmv[0].y;
2039            return iMinSAD;
2040    }
2041    
2042    
2043    
2044    
2045    
2046    /* ***********************************************************
2047            bvop motion estimation
2048    // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)
2049    ***************************************************************/
2050    
2051    
2052    void MotionEstimationBVOP(
2053                            MBParam * const pParam,
2054                            FRAMEINFO * const frame,
2055    
2056                            // forward (past) reference
2057                            const MACROBLOCK * const f_mbs,
2058                        const IMAGE * const f_ref,
2059                            const IMAGE * const f_refH,
2060                        const IMAGE * const f_refV,
2061                            const IMAGE * const f_refHV,
2062                            // backward (future) reference
2063                            const MACROBLOCK * const b_mbs,
2064                        const IMAGE * const b_ref,
2065                            const IMAGE * const b_refH,
2066                        const IMAGE * const b_refV,
2067                            const IMAGE * const b_refHV)
2068    {
2069        const uint32_t mb_width = pParam->mb_width;
2070        const uint32_t mb_height = pParam->mb_height;
2071            const int32_t edged_width = pParam->edged_width;
2072    
2073            uint32_t i,j;
2074    
2075            int32_t f_sad16;
2076            int32_t b_sad16;
2077            int32_t i_sad16;
2078            int32_t d_sad16;
2079            int32_t best_sad;
2080    
2081            VECTOR pmv_dontcare;
2082    
2083            // note: i==horizontal, j==vertical
2084        for (j = 0; j < mb_height; j++)
2085            {
2086                    for (i = 0; i < mb_width; i++)
2087                    {
2088                            MACROBLOCK *mb = &frame->mbs[i + j*mb_width];
2089                            const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];
2090                            const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];
2091    
2092                            if (b_mb->mode == MODE_INTER
2093                                    && b_mb->cbp == 0
2094                                    && b_mb->mvs[0].x == 0
2095                                    && b_mb->mvs[0].y == 0)
2096                            {
2097                                    mb->mode = MODE_NOT_CODED;
2098                                    mb->mvs[0].x = 0;
2099                                    mb->mvs[0].y = 0;
2100                                    mb->b_mvs[0].x = 0;
2101                                    mb->b_mvs[0].y = 0;
2102                                    continue;
2103                            }
2104    
2105    
2106                            // forward search
2107                            f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2108                                                    &frame->image,
2109                                                    i, j,
2110                                                    frame->motion_flags,  frame->quant, frame->fcode,
2111                                                    pParam,
2112                                                    f_mbs, f_mbs /* todo */,
2113                                                    &mb->mvs[0], &pmv_dontcare);    // ignore pmv
2114    
2115                            // backward search
2116                            b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2117                                                    &frame->image,
2118                                                    i, j,
2119                                                    frame->motion_flags,  frame->quant, frame->bcode,
2120                                                    pParam,
2121                                                    b_mbs, b_mbs, /* todo */
2122                                                    &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv
2123    
2124                            // interpolate search (simple, but effective)
2125                            i_sad16 = sad16bi_c(
2126                                            frame->image.y + i*16 + j*16*edged_width,
2127                                            get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2128                                                    i, j, 16, mb->mvs[0].x, mb->mvs[0].y, edged_width),
2129                                            get_ref(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2130                                                    i, j, 16, mb->b_mvs[0].x, mb->b_mvs[0].x, edged_width),
2131                                            edged_width);
2132    
2133                            // TODO: direct search
2134                            // predictor + range of [-32,32]
2135                            d_sad16 = 65535;
2136    
2137    
2138                            if (f_sad16 < b_sad16)
2139                            {
2140                                    best_sad = f_sad16;
2141                                    mb->mode = MODE_FORWARD;
2142                            }
2143                            else
2144                            {
2145                                    best_sad = b_sad16;
2146                                    mb->mode = MODE_BACKWARD;
2147                            }
2148    
2149                            if (i_sad16 < best_sad)
2150                            {
2151                                    best_sad = i_sad16;
2152                                    mb->mode = MODE_INTERPOLATE;
2153                            }
2154    
2155                            if (d_sad16 < best_sad)
2156                            {
2157                                    best_sad = d_sad16;
2158                                    mb->mode = MODE_DIRECT;
2159                            }
2160    
2161                    }
2162            }
2163    }

Legend:
Removed from v.3  
changed lines
  Added in v.169

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