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

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

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

revision 78, Thu Mar 28 20:57:25 2002 UTC revision 170, Thu May 9 21:47:51 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  /*  typedef MainSearch16Func* MainSearch16FuncPtr;
  * diamond search stuff  
  * 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 160  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        return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));
         const int search_range = 32 << (fcode - 1);  
         const int high = search_range - 1;  
         const int low = -search_range;  
   
         // convert full-pixel measurements to half pixel  
         const int hp_width = 2 * width;  
         const int hp_height = 2 * height;  
         const int hp_edge = 2 * block_sz;  
         const int hp_x = 2 * (x) * block_sz;            // we need _right end_ of block, not x-coordinate  
         const int hp_y = 2 * (y) * block_sz;            // same for _bottom end_  
   
         *max_dx = MIN(high,     hp_width - hp_x);  
         *max_dy = MIN(high,     hp_height - hp_y);  
         *min_dx = MAX(low,      -(hp_edge + hp_x));  
         *min_dy = MAX(low,      -(hp_edge + hp_y));  
   
 }  
   
   
 /*  
  * getref: calculate reference image pointer  
  * the decision to use interpolation h/v/hv or the normal image is  
  * based on dx & dy.  
  */  
   
 static __inline const uint8_t * get_ref(  
         const uint8_t * const refn,  
         const uint8_t * const refh,  
         const uint8_t * const refv,  
         const uint8_t * const refhv,  
         const uint32_t x, const uint32_t y,  
         const uint32_t block,                                   // block dimension, 8 or 16  
         const int32_t dx, const int32_t dy,  
         const uint32_t stride)  
 {  
   
         switch ( ((dx&1)<<1) + (dy&1) )         // ((dx%2)?2:0)+((dy%2)?1:0)  
         {  
         case 0  : return refn + (x*block+dx/2) + (y*block+dy/2)*stride;  
         case 1  : return refv + (x*block+dx/2) + (y*block+(dy-1)/2)*stride;  
         case 2  : return refh + (x*block+(dx-1)/2) + (y*block+dy/2)*stride;  
         default :  
         case 3  : return refhv + (x*block+(dx-1)/2) + (y*block+(dy-1)/2)*stride;  
         }  
   
245  }  }
246    
247    
 /* This is somehow a copy of get_ref, but with MV instead of X,Y */  
   
 static __inline const uint8_t * get_ref_mv(  
         const uint8_t * const refn,  
         const uint8_t * const refh,  
         const uint8_t * const refv,  
         const uint8_t * const refhv,  
         const uint32_t x, const uint32_t y,  
         const uint32_t block,                   // block dimension, 8 or 16  
         const VECTOR* mv,       // measured in half-pel!  
         const uint32_t stride)  
 {  
248    
         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;  
         }  
249    
 }  
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 290  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 314  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 321  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 347  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 367  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 385  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 408  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 418  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 426  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 447  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 457  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 472  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 501  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 558  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 593  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 601  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 630  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 669  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.
         if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[0]) ) )  
                 iFound=2;  
   
 /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  
    Otherwise select large Diamond Search.  
909  */  */
910    
         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  
   
911          *currMV=pmv[0];         /* current best := prediction */          *currMV=pmv[0];         /* current best := prediction */
912          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16 ))
913          {       /* This should NOT be necessary! */          {       /* This should NOT be necessary! */
# Line 726  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 771  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 781  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 807  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 823  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 836  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 853  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 871  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 928  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 971  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 999  Line 1257 
1257          int32_t psad[4];          int32_t psad[4];
1258          VECTOR newMV;          VECTOR newMV;
1259          VECTOR backupMV;          VECTOR backupMV;
1260            VECTOR startMV;
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            /* Init variables */
1272            startMV.x = start_x;
1273            startMV.y = start_y;
1274    
1275  /* Get maximum range */  /* Get maximum range */
1276          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1277                    x, y, 8, iWidth, iHeight, iFcode);                    x, y, 8, iWidth, iHeight, iFcode);
1278    
 /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */  
   
1279          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))
1280          { min_dx = EVEN(min_dx);          { min_dx = EVEN(min_dx);
1281          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
# Line 1041  Line 1303 
1303    
1304          iFound=0;          iFound=0;
1305    
 /* 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;  
   
1306  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1307     MinSAD=SAD     MinSAD=SAD
1308     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 1071  Line 1313 
1313    
1314  // Prepare for main loop  // Prepare for main loop
1315    
1316          currMV->x=start_x;              /* start with mv16 */          *currMV = startMV;
         currMV->y=start_y;  
1317    
1318          iMinSAD = sad8( cur,          iMinSAD = sad8( cur,
1319                          get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                          get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
1320                          iEdgedWidth);                          iEdgedWidth);
1321          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);
1322    
1323          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock]))
1324                                    && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1325          {          {
1326                  if (MotionFlags & PMV_QUICKSTOP8)                  if (MotionFlags & PMV_QUICKSTOP16)
1327                          goto step10_8b;                          goto PMVfast8_Terminate_without_Refine;
1328                  if (MotionFlags & PMV_EARLYSTOP8)                  if (MotionFlags & PMV_EARLYSTOP16)
1329                          goto step10_8;                          goto PMVfast8_Terminate_with_Refine;
1330          }          }
1331    
1332    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1333       vector of the median.
1334       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1335    */
1336    
1337            if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[iSubBlock]) ) )
1338                    iFound=2;
1339    
1340    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1341       Otherwise select large Diamond Search.
1342    */
1343    
1344            if ( (!MVzero(pmv[0])) || (threshB<1536/4) || (bPredEq) )
1345                    iDiamondSize=1; // 1 halfpel!
1346            else
1347                    iDiamondSize=2; // 2 halfpel = 1 full pixel!
1348    
1349            if (!(MotionFlags & PMV_HALFPELDIAMOND8) )
1350                    iDiamondSize*=2;
1351    
1352    
1353  /*  /*
1354     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.
1355     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1356     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1357     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1358  */  */
1359    
1360  // the prediction might be even better than mv16  // the median prediction might be even better than mv16
1361    
1362            if (!MVequal(pmv[0],startMV))
1363          CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);          CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);
1364    
1365  // (0,0) is always possible  // (0,0) if needed
1366            if (!MVzero(pmv[0]))
1367            if (!MVzero(startMV))
1368          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
1369    
1370  // previous frame MV is always possible  // previous frame MV if needed
1371          CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);          if (!MVzero(prevMB->mvs[iSubBlock]))
1372            if (!MVequal(prevMB->mvs[iSubBlock],startMV))
1373            if (!MVequal(prevMB->mvs[iSubBlock],pmv[0]))
1374            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
1375    
1376  // left neighbour, if allowed          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1377          if (psad[1] != MV_MAX_ERROR)          {
1378                    if (MotionFlags & PMV_QUICKSTOP16)
1379                            goto PMVfast8_Terminate_without_Refine;
1380                    if (MotionFlags & PMV_EARLYSTOP16)
1381                            goto PMVfast8_Terminate_with_Refine;
1382            }
1383    
1384    
1385    // left neighbour, if allowed and needed
1386            if (!MVzero(pmv[1]))
1387            if (!MVequal(pmv[1],startMV))
1388            if (!MVequal(pmv[1],prevMB->mvs[iSubBlock]))
1389            if (!MVequal(pmv[1],pmv[0]))
1390          {          {
1391                  if (!(MotionFlags & PMV_HALFPEL8 ))                  if (!(MotionFlags & PMV_HALFPEL8 ))
1392                  {       pmv[1].x = EVEN(pmv[1].x);                  {       pmv[1].x = EVEN(pmv[1].x);
# Line 1113  Line 1395 
1395                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1396          }          }
1397    
1398  // top neighbour, if allowed  // top neighbour, if allowed and needed
1399          if (psad[2] != MV_MAX_ERROR)          if (!MVzero(pmv[2]))
1400            if (!MVequal(pmv[2],startMV))
1401            if (!MVequal(pmv[2],prevMB->mvs[iSubBlock]))
1402            if (!MVequal(pmv[2],pmv[0]))
1403            if (!MVequal(pmv[2],pmv[1]))
1404          {          {
1405                  if (!(MotionFlags & PMV_HALFPEL8 ))                  if (!(MotionFlags & PMV_HALFPEL8 ))
1406                  {       pmv[2].x = EVEN(pmv[2].x);                  {       pmv[2].x = EVEN(pmv[2].x);
# Line 1122  Line 1408 
1408                  }                  }
1409                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1410    
1411  // top right neighbour, if allowed  // top right neighbour, if allowed and needed
1412                  if (psad[3] != MV_MAX_ERROR)          if (!MVzero(pmv[3]))
1413            if (!MVequal(pmv[3],startMV))
1414            if (!MVequal(pmv[3],prevMB->mvs[iSubBlock]))
1415            if (!MVequal(pmv[3],pmv[0]))
1416            if (!MVequal(pmv[3],pmv[1]))
1417            if (!MVequal(pmv[3],pmv[2]))
1418                  {                  {
1419                          if (!(MotionFlags & PMV_HALFPEL8 ))                          if (!(MotionFlags & PMV_HALFPEL8 ))
1420                          {       pmv[3].x = EVEN(pmv[3].x);                          {       pmv[3].x = EVEN(pmv[3].x);
# Line 1133  Line 1424 
1424                  }                  }
1425          }          }
1426    
1427            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1428                    iMinSAD -= MV8_00_BIAS;
1429    
1430    
1431  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1432     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.
1433  */  */
1434    
1435          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]) ) )
1436          {          {
1437                  if (MotionFlags & PMV_QUICKSTOP8)                  if (MotionFlags & PMV_QUICKSTOP16)
1438                          goto step10_8b;                          goto PMVfast8_Terminate_without_Refine;
1439                  if (MotionFlags & PMV_EARLYSTOP8)                  if (MotionFlags & PMV_EARLYSTOP16)
1440                          goto step10_8;                          goto PMVfast8_Terminate_with_Refine;
1441          }          }
1442    
1443  /************ (Diamond Search)  **************/  /************ (Diamond Search)  **************/
# Line 1158  Line 1453 
1453          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1454    
1455  /* 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 */
1456          iSAD = PMVfastSearch8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1457                                           x, y,                                           x, y,
1458                                           currMV->x, currMV->y, iMinSAD, &newMV,                                           currMV->x, currMV->y, iMinSAD, &newMV,
1459                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 1174  Line 1469 
1469  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1470    
1471                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0],backupMV)) )
1472                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1473                                                            x, y,                                                            x, y,
1474                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1475                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 1187  Line 1482 
1482                  }                  }
1483    
1484                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1485                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1486                                                            x, y,                                                            x, y,
1487                                                            0, 0, iMinSAD, &newMV,                                                            0, 0, iMinSAD, &newMV,
1488                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 1204  Line 1499 
1499     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.
1500  */  */
1501    
1502   step10_8:  PMVfast8_Terminate_with_Refine:
1503          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
1504                  iMinSAD = PMVfastSearch8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1505                                                   x, y,                                                   x, y,
1506                                                   currMV, iMinSAD,                                                   currMV, iMinSAD,
1507                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1508    
  step10_8b:  
1509    
1510    PMVfast8_Terminate_without_Refine:
1511          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1512          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
1513    
1514          return iMinSAD;          return iMinSAD;
1515  }  }
1516    
1517    int32_t EPZSSearch16(
1518                                            const uint8_t * const pRef,
1519                                            const uint8_t * const pRefH,
1520                                            const uint8_t * const pRefV,
1521                                            const uint8_t * const pRefHV,
1522                                            const IMAGE * const pCur,
1523                                            const int x, const int y,
1524                                            const uint32_t MotionFlags,
1525                                            const uint32_t iQuant,
1526                                            const uint32_t iFcode,
1527                                            const MBParam * const pParam,
1528                                            const MACROBLOCK * const pMBs,
1529                                            const MACROBLOCK * const prevMBs,
1530                                            VECTOR * const currMV,
1531                                            VECTOR * const currPMV)
1532    {
1533        const uint32_t iWcount = pParam->mb_width;
1534        const uint32_t iHcount = pParam->mb_height;
1535    
1536            const int32_t iWidth = pParam->width;
1537            const int32_t iHeight = pParam->height;
1538            const int32_t iEdgedWidth = pParam->edged_width;
1539    
1540            const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
1541    
1542            int32_t min_dx;
1543            int32_t max_dx;
1544            int32_t min_dy;
1545            int32_t max_dy;
1546    
1547            VECTOR newMV;
1548            VECTOR backupMV;
1549    
1550            VECTOR pmv[4];
1551            int32_t psad[8];
1552    
1553            static MACROBLOCK * oldMBs = NULL;
1554            const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
1555            const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1556            MACROBLOCK * oldMB = NULL;
1557    
1558            static int32_t thresh2;
1559            int32_t bPredEq;
1560            int32_t iMinSAD,iSAD=9999;
1561    
1562            MainSearch16FuncPtr EPZSMainSearchPtr;
1563    
1564            if (oldMBs == NULL)
1565            {       oldMBs = (MACROBLOCK*) calloc(iWcount*iHcount,sizeof(MACROBLOCK));
1566    //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
1567            }
1568            oldMB = oldMBs + x + y * iWcount;
1569    
1570    /* Get maximum range */
1571            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1572                            x, y, 16, iWidth, iHeight, iFcode);
1573    
1574            if (!(MotionFlags & PMV_HALFPEL16 ))
1575            { min_dx = EVEN(min_dx);
1576              max_dx = EVEN(max_dx);
1577              min_dy = EVEN(min_dy);
1578              max_dy = EVEN(max_dy);
1579            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1580    
1581            bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1582    
1583    /* Step 4: Calculate SAD around the Median prediction.
1584            MinSAD=SAD
1585            If Motion Vector equal to Previous frame motion vector
1586                    and MinSAD<PrevFrmSAD goto Step 10.
1587            If SAD<=256 goto Step 10.
1588    */
1589    
1590    // Prepare for main loop
1591    
1592            *currMV=pmv[0];         /* current best := median prediction */
1593            if (!(MotionFlags & PMV_HALFPEL16))
1594            {
1595                    currMV->x = EVEN(currMV->x);
1596                    currMV->y = EVEN(currMV->y);
1597            }
1598    
1599            if (currMV->x > max_dx)
1600                    currMV->x=max_dx;
1601            if (currMV->x < min_dx)
1602                    currMV->x=min_dx;
1603            if (currMV->y > max_dy)
1604                    currMV->y=max_dy;
1605            if (currMV->y < min_dy)
1606                    currMV->y=min_dy;
1607    
1608    /***************** This is predictor SET A: only median prediction ******************/
1609    
1610            iMinSAD = sad16( cur,
1611                    get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
1612                    iEdgedWidth, MV_MAX_ERROR);
1613            iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);
1614    
1615    // thresh1 is fixed to 256
1616            if ( (iMinSAD < 256 ) || ( (MVequal(*currMV, prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
1617                    {
1618                            if (MotionFlags & PMV_QUICKSTOP16)
1619                                    goto EPZS16_Terminate_without_Refine;
1620                            if (MotionFlags & PMV_EARLYSTOP16)
1621                                    goto EPZS16_Terminate_with_Refine;
1622                    }
1623    
1624    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1625    
1626    // previous frame MV
1627            CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1628    
1629    // set threshhold based on Min of Prediction and SAD of collocated block
1630    // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
1631    
1632            if ((x==0) && (y==0) )
1633            {
1634                    thresh2 =  512;
1635            }
1636            else
1637            {
1638    /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */
1639    
1640                    thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
1641            }
1642    
1643    // MV=(0,0) is often a good choice
1644    
1645            CHECK_MV16_ZERO;
1646    
1647    
1648    // left neighbour, if allowed
1649            if (x != 0)
1650            {
1651                    if (!(MotionFlags & PMV_HALFPEL16 ))
1652                    {       pmv[1].x = EVEN(pmv[1].x);
1653                            pmv[1].y = EVEN(pmv[1].y);
1654                    }
1655                    CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1656            }
1657    
1658    // top neighbour, if allowed
1659            if (y != 0)
1660            {
1661                    if (!(MotionFlags & PMV_HALFPEL16 ))
1662                    {       pmv[2].x = EVEN(pmv[2].x);
1663                            pmv[2].y = EVEN(pmv[2].y);
1664                    }
1665                    CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1666    
1667    // top right neighbour, if allowed
1668                    if ((uint32_t)x != (iWcount-1))
1669                    {
1670                            if (!(MotionFlags & PMV_HALFPEL16 ))
1671                            {       pmv[3].x = EVEN(pmv[3].x);
1672                                    pmv[3].y = EVEN(pmv[3].y);
1673                            }
1674                            CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
1675                    }
1676            }
1677    
1678    /* Terminate if MinSAD <= T_2
1679       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1680    */
1681    
1682            if ( (iMinSAD <= thresh2)
1683                    || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )
1684                    {
1685                            if (MotionFlags & PMV_QUICKSTOP16)
1686                                    goto EPZS16_Terminate_without_Refine;
1687                            if (MotionFlags & PMV_EARLYSTOP16)
1688                                    goto EPZS16_Terminate_with_Refine;
1689                    }
1690    
1691    /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
1692    
1693            backupMV = prevMB->mvs[0];              // collocated MV
1694            backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x );    // acceleration X
1695            backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y );    // acceleration Y
1696    
1697            CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);
1698    
1699    // left neighbour
1700            if (x != 0)
1701                    CHECK_MV16_CANDIDATE((prevMB-1)->mvs[0].x,(prevMB-1)->mvs[0].y);
1702    
1703    // top neighbour
1704            if (y != 0)
1705                    CHECK_MV16_CANDIDATE((prevMB-iWcount)->mvs[0].x,(prevMB-iWcount)->mvs[0].y);
1706    
1707    // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
1708    
1709            if ((uint32_t)x != iWcount-1)
1710                    CHECK_MV16_CANDIDATE((prevMB+1)->mvs[0].x,(prevMB+1)->mvs[0].y);
1711    
1712    // bottom neighbour, dito
1713            if ((uint32_t)y != iHcount-1)
1714                    CHECK_MV16_CANDIDATE((prevMB+iWcount)->mvs[0].x,(prevMB+iWcount)->mvs[0].y);
1715    
1716    /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
1717            if (iMinSAD <= thresh2)
1718                    {
1719                            if (MotionFlags & PMV_QUICKSTOP16)
1720                                    goto EPZS16_Terminate_without_Refine;
1721                            if (MotionFlags & PMV_EARLYSTOP16)
1722                                    goto EPZS16_Terminate_with_Refine;
1723                    }
1724    
1725    /************ (if Diamond Search)  **************/
1726    
1727            backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1728    
1729    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1730    
1731            if (MotionFlags & PMV_USESQUARES16)
1732                    EPZSMainSearchPtr = Square16_MainSearch;
1733            else
1734                    EPZSMainSearchPtr = Diamond16_MainSearch;
1735    
1736            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1737                            x, y,
1738                            currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1739                            2, iFcode, iQuant, 0);
1740    
1741            if (iSAD < iMinSAD)
1742            {
1743                    *currMV = newMV;
1744                    iMinSAD = iSAD;
1745            }
1746    
1747    
1748            if (MotionFlags & PMV_EXTSEARCH16)
1749            {
1750    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
1751    
1752                    if (!(MVequal(pmv[0],backupMV)) )
1753                    {
1754                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1755                                    x, y,
1756                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1757                                    pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
1758                    }
1759    
1760                    if (iSAD < iMinSAD)
1761                    {
1762                            *currMV = newMV;
1763                            iMinSAD = iSAD;
1764                    }
1765    
1766                    if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1767                    {
1768                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1769                                    x, y,
1770                            0, 0, iMinSAD, &newMV,
1771                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
1772    
1773                            if (iSAD < iMinSAD)
1774                            {
1775                                    *currMV = newMV;
1776                                    iMinSAD = iSAD;
1777                            }
1778                    }
1779            }
1780    
1781    /***************        Choose best MV found     **************/
1782    
1783    EPZS16_Terminate_with_Refine:
1784            if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1785                    iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1786                                    x, y,
1787                                    currMV, iMinSAD,
1788                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1789    
1790    EPZS16_Terminate_without_Refine:
1791    
1792            *oldMB = *prevMB;
1793    
1794            currPMV->x = currMV->x - pmv[0].x;
1795            currPMV->y = currMV->y - pmv[0].y;
1796            return iMinSAD;
1797    }
1798    
1799    
1800    int32_t EPZSSearch8(
1801                                            const uint8_t * const pRef,
1802                                            const uint8_t * const pRefH,
1803                                            const uint8_t * const pRefV,
1804                                            const uint8_t * const pRefHV,
1805                                            const IMAGE * const pCur,
1806                                            const int x, const int y,
1807                                            const int start_x, const int start_y,
1808                                            const uint32_t MotionFlags,
1809                                            const uint32_t iQuant,
1810                                            const uint32_t iFcode,
1811                                            const MBParam * const pParam,
1812                                            const MACROBLOCK * const pMBs,
1813                                            const MACROBLOCK * const prevMBs,
1814                                            VECTOR * const currMV,
1815                                            VECTOR * const currPMV)
1816    {
1817    /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
1818    
1819            const uint32_t iWcount = pParam->mb_width;
1820            const int32_t iWidth = pParam->width;
1821            const int32_t iHeight = pParam->height;
1822            const int32_t iEdgedWidth = pParam->edged_width;
1823    
1824            const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;
1825    
1826            int32_t iDiamondSize=1;
1827    
1828            int32_t min_dx;
1829            int32_t max_dx;
1830            int32_t min_dy;
1831            int32_t max_dy;
1832    
1833            VECTOR newMV;
1834            VECTOR backupMV;
1835    
1836            VECTOR pmv[4];
1837            int32_t psad[8];
1838    
1839            const   int32_t iSubBlock = ((y&1)<<1) + (x&1);
1840    
1841            const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1842            const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1843    
1844            int32_t bPredEq;
1845            int32_t iMinSAD,iSAD=9999;
1846    
1847            MainSearch8FuncPtr EPZSMainSearchPtr;
1848    
1849    /* Get maximum range */
1850            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1851                            x, y, 8, iWidth, iHeight, iFcode);
1852    
1853    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1854    
1855            if (!(MotionFlags & PMV_HALFPEL8 ))
1856            { min_dx = EVEN(min_dx);
1857              max_dx = EVEN(max_dx);
1858              min_dy = EVEN(min_dy);
1859              max_dy = EVEN(max_dy);
1860            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1861    
1862            bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);
1863    
1864    
1865    /* Step 4: Calculate SAD around the Median prediction.
1866            MinSAD=SAD
1867            If Motion Vector equal to Previous frame motion vector
1868                    and MinSAD<PrevFrmSAD goto Step 10.
1869            If SAD<=256 goto Step 10.
1870    */
1871    
1872    // Prepare for main loop
1873    
1874    
1875            if (!(MotionFlags & PMV_HALFPEL8))
1876            {
1877                    currMV->x = EVEN(currMV->x);
1878                    currMV->y = EVEN(currMV->y);
1879            }
1880    
1881            if (currMV->x > max_dx)
1882                    currMV->x=max_dx;
1883            if (currMV->x < min_dx)
1884                    currMV->x=min_dx;
1885            if (currMV->y > max_dy)
1886                    currMV->y=max_dy;
1887            if (currMV->y < min_dy)
1888                    currMV->y=min_dy;
1889    
1890    /***************** This is predictor SET A: only median prediction ******************/
1891    
1892    
1893            iMinSAD = sad8( cur,
1894                    get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
1895                    iEdgedWidth);
1896            iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);
1897    
1898    
1899    // thresh1 is fixed to 256
1900            if (iMinSAD < 256/4 )
1901                    {
1902                            if (MotionFlags & PMV_QUICKSTOP8)
1903                                    goto EPZS8_Terminate_without_Refine;
1904                            if (MotionFlags & PMV_EARLYSTOP8)
1905                                    goto EPZS8_Terminate_with_Refine;
1906                    }
1907    
1908    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1909    
1910    
1911    // MV=(0,0) is often a good choice
1912            CHECK_MV8_ZERO;
1913    
1914    // previous frame MV
1915            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
1916    
1917    // left neighbour, if allowed
1918            if (psad[1] != MV_MAX_ERROR)
1919            {
1920                    if (!(MotionFlags & PMV_HALFPEL8 ))
1921                    {       pmv[1].x = EVEN(pmv[1].x);
1922                            pmv[1].y = EVEN(pmv[1].y);
1923                    }
1924                    CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1925            }
1926    
1927    // top neighbour, if allowed
1928            if (psad[2] != MV_MAX_ERROR)
1929            {
1930                    if (!(MotionFlags & PMV_HALFPEL8 ))
1931                    {       pmv[2].x = EVEN(pmv[2].x);
1932                            pmv[2].y = EVEN(pmv[2].y);
1933                    }
1934                    CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1935    
1936    // top right neighbour, if allowed
1937                    if (psad[3] != MV_MAX_ERROR)
1938                    {
1939                            if (!(MotionFlags & PMV_HALFPEL8 ))
1940                            {       pmv[3].x = EVEN(pmv[3].x);
1941                                    pmv[3].y = EVEN(pmv[3].y);
1942                            }
1943                            CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);
1944                    }
1945            }
1946    
1947    /*  // this bias is zero anyway, at the moment!
1948    
1949            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
1950                    iMinSAD -= MV8_00_BIAS;
1951    
1952    */
1953    
1954    /* Terminate if MinSAD <= T_2
1955       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1956    */
1957    
1958            if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */
1959                    {
1960                            if (MotionFlags & PMV_QUICKSTOP8)
1961                                    goto EPZS8_Terminate_without_Refine;
1962                            if (MotionFlags & PMV_EARLYSTOP8)
1963                                    goto EPZS8_Terminate_with_Refine;
1964                    }
1965    
1966    /************ (Diamond Search)  **************/
1967    
1968            backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1969    
1970            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
1971                    iDiamondSize *= 2;
1972    
1973    /* default: use best prediction as starting point for one call of EPZS_MainSearch */
1974    
1975    /* // there is no EPZS^2 for inter4v at the moment
1976    
1977            if (MotionFlags & PMV_USESQUARES8)
1978                    EPZSMainSearchPtr = Square8_MainSearch;
1979            else
1980    */
1981    
1982            EPZSMainSearchPtr = Diamond8_MainSearch;
1983    
1984            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1985                    x, y,
1986                    currMV->x, currMV->y, iMinSAD, &newMV,
1987                    pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1988                    iDiamondSize, iFcode, iQuant, 0);
1989    
1990    
1991            if (iSAD < iMinSAD)
1992            {
1993                    *currMV = newMV;
1994                    iMinSAD = iSAD;
1995            }
1996    
1997            if (MotionFlags & PMV_EXTSEARCH8)
1998            {
1999    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2000    
2001                    if (!(MVequal(pmv[0],backupMV)) )
2002                    {
2003                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
2004                                    x, y,
2005                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,
2006                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
2007    
2008                            if (iSAD < iMinSAD)
2009                            {
2010                                    *currMV = newMV;
2011                                    iMinSAD = iSAD;
2012                            }
2013                    }
2014    
2015                    if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
2016                    {
2017                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
2018                                    x, y,
2019                            0, 0, iMinSAD, &newMV,
2020                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
2021    
2022                            if (iSAD < iMinSAD)
2023                            {
2024                                    *currMV = newMV;
2025                                    iMinSAD = iSAD;
2026                            }
2027                    }
2028            }
2029    
2030    /***************        Choose best MV found     **************/
2031    
2032    EPZS8_Terminate_with_Refine:
2033            if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2034                    iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
2035                                    x, y,
2036                                    currMV, iMinSAD,
2037                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
2038    
2039    EPZS8_Terminate_without_Refine:
2040    
2041            currPMV->x = currMV->x - pmv[0].x;
2042            currPMV->y = currMV->y - pmv[0].y;
2043            return iMinSAD;
2044    }
2045    
2046    
2047    
2048    
2049    
2050    /* ***********************************************************
2051            bvop motion estimation
2052    // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)
2053    ***************************************************************/
2054    
2055    
2056    void MotionEstimationBVOP(
2057                            MBParam * const pParam,
2058                            FRAMEINFO * const frame,
2059    
2060                            // forward (past) reference
2061                            const MACROBLOCK * const f_mbs,
2062                        const IMAGE * const f_ref,
2063                            const IMAGE * const f_refH,
2064                        const IMAGE * const f_refV,
2065                            const IMAGE * const f_refHV,
2066                            // backward (future) reference
2067                            const MACROBLOCK * const b_mbs,
2068                        const IMAGE * const b_ref,
2069                            const IMAGE * const b_refH,
2070                        const IMAGE * const b_refV,
2071                            const IMAGE * const b_refHV)
2072    {
2073        const uint32_t mb_width = pParam->mb_width;
2074        const uint32_t mb_height = pParam->mb_height;
2075            const int32_t edged_width = pParam->edged_width;
2076    
2077            uint32_t i,j;
2078    
2079            int32_t f_sad16;
2080            int32_t b_sad16;
2081            int32_t i_sad16;
2082            int32_t d_sad16;
2083            int32_t best_sad;
2084    
2085            VECTOR pmv_dontcare;
2086    
2087            // note: i==horizontal, j==vertical
2088        for (j = 0; j < mb_height; j++)
2089            {
2090                    for (i = 0; i < mb_width; i++)
2091                    {
2092                            MACROBLOCK *mb = &frame->mbs[i + j*mb_width];
2093                            const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];
2094                            const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];
2095    
2096                            if (b_mb->mode == MODE_INTER
2097                                    && b_mb->cbp == 0
2098                                    && b_mb->mvs[0].x == 0
2099                                    && b_mb->mvs[0].y == 0)
2100                            {
2101                                    mb->mode = MODE_NOT_CODED;
2102                                    mb->mvs[0].x = 0;
2103                                    mb->mvs[0].y = 0;
2104                                    mb->b_mvs[0].x = 0;
2105                                    mb->b_mvs[0].y = 0;
2106                                    continue;
2107                            }
2108    
2109    
2110                            // forward search
2111                            f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2112                                                    &frame->image,
2113                                                    i, j,
2114                                                    frame->motion_flags,  frame->quant, frame->fcode,
2115                                                    pParam,
2116                                                    f_mbs, f_mbs /* todo */,
2117                                                    &mb->mvs[0], &pmv_dontcare);    // ignore pmv
2118    
2119                            // backward search
2120                            b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2121                                                    &frame->image,
2122                                                    i, j,
2123                                                    frame->motion_flags,  frame->quant, frame->bcode,
2124                                                    pParam,
2125                                                    b_mbs, b_mbs, /* todo */
2126                                                    &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv
2127    
2128                            // interpolate search (simple, but effective)
2129                            i_sad16 = sad16bi_c(
2130                                            frame->image.y + i*16 + j*16*edged_width,
2131                                            get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2132                                                    i, j, 16, mb->mvs[0].x, mb->mvs[0].y, edged_width),
2133                                            get_ref(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2134                                                    i, j, 16, mb->b_mvs[0].x, mb->b_mvs[0].x, edged_width),
2135                                            edged_width);
2136    
2137                            // TODO: direct search
2138                            // predictor + range of [-32,32]
2139                            d_sad16 = 65535;
2140    
2141    
2142                            if (f_sad16 < b_sad16)
2143                            {
2144                                    best_sad = f_sad16;
2145                                    mb->mode = MODE_FORWARD;
2146                            }
2147                            else
2148                            {
2149                                    best_sad = b_sad16;
2150                                    mb->mode = MODE_BACKWARD;
2151                            }
2152    
2153                            if (i_sad16 < best_sad)
2154                            {
2155                                    best_sad = i_sad16;
2156                                    mb->mode = MODE_INTERPOLATE;
2157                            }
2158    
2159                            if (d_sad16 < best_sad)
2160                            {
2161                                    best_sad = d_sad16;
2162                                    mb->mode = MODE_DIRECT;
2163                            }
2164    
2165                    }
2166            }
2167    }

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

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