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

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

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

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

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

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