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

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

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

revision 78, Thu Mar 28 20:57:25 2002 UTC revision 172, Sat May 11 15:32:59 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 MV16_INTER_BIAS 512
64    
65  /* Parameters which control inter/inter4v decision */  /* Parameters which control inter/inter4v decision */
66  #define IMV16X16                        5  #define IMV16X16                        5
# Line 60  Line 69 
69  #define NEIGH_TEND_16X16        2  #define NEIGH_TEND_16X16        2
70  #define NEIGH_TEND_8X8          2  #define NEIGH_TEND_8X8          2
71    
   
72  // fast ((A)/2)*2  // fast ((A)/2)*2
73  #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)  #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)
74    
75    #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )
76    #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )
77    
78    int32_t PMVfastSearch16(
79                                            const uint8_t * const pRef,
80                                            const uint8_t * const pRefH,
81                                            const uint8_t * const pRefV,
82                                            const uint8_t * const pRefHV,
83                                            const IMAGE * const pCur,
84                                            const int x, const int y,
85                                            const uint32_t MotionFlags,
86                                            const uint32_t iQuant,
87                                            const uint32_t iFcode,
88                                            const MBParam * const pParam,
89                                            const MACROBLOCK * const pMBs,
90                                            const MACROBLOCK * const prevMBs,
91                                            VECTOR * const currMV,
92                                            VECTOR * const currPMV);
93    
94  #define MIN(X, Y) ((X)<(Y)?(X):(Y))  int32_t EPZSSearch16(
95  #define MAX(X, Y) ((X)>(Y)?(X):(Y))                                          const uint8_t * const pRef,
96  #define ABS(X)    (((X)>0)?(X):-(X))                                          const uint8_t * const pRefH,
97  #define SIGN(X)   (((X)>0)?1:-1)                                          const uint8_t * const pRefV,
98                                            const uint8_t * const pRefHV,
99                                            const IMAGE * const pCur,
100                                            const int x, const int y,
101                                            const uint32_t MotionFlags,
102                                            const uint32_t iQuant,
103                                            const uint32_t iFcode,
104                                            const MBParam * const pParam,
105                                            const MACROBLOCK * const pMBs,
106                                            const MACROBLOCK * const prevMBs,
107                                            VECTOR * const currMV,
108                                            VECTOR * const currPMV);
109    
110    
111  int32_t PMVfastSearch8(  int32_t PMVfastSearch8(
# Line 78  Line 115 
115          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
116          const IMAGE * const pCur,          const IMAGE * const pCur,
117          const int x, const int y,          const int x, const int y,
118          const int start_x, int start_y,                                          const int start_x, const int start_y,
119          const uint32_t iQuality,                                          const uint32_t MotionFlags,
120          MBParam * const pParam,                                          const uint32_t iQuant,
121          MACROBLOCK * const pMBs,                                          const uint32_t iFcode,
122                                            const MBParam * const pParam,
123                                            const MACROBLOCK * const pMBs,
124                                            const MACROBLOCK * const prevMBs,
125          VECTOR * const currMV,          VECTOR * const currMV,
126          VECTOR * const currPMV);          VECTOR * const currPMV);
127    
128  int32_t PMVfastSearch16(  int32_t EPZSSearch8(
129          const uint8_t * const pRef,          const uint8_t * const pRef,
130          const uint8_t * const pRefH,          const uint8_t * const pRefH,
131          const uint8_t * const pRefV,          const uint8_t * const pRefV,
132          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
133          const IMAGE * const pCur,          const IMAGE * const pCur,
134          const int x, const int y,          const int x, const int y,
135          const uint32_t iQuality,                                          const int start_x, const int start_y,
136          MBParam * const pParam,                                          const uint32_t MotionFlags,
137          MACROBLOCK * const pMBs,                                          const uint32_t iQuant,
138                                            const uint32_t iFcode,
139                                            const MBParam * const pParam,
140                                            const MACROBLOCK * const pMBs,
141                                            const MACROBLOCK * const prevMBs,
142          VECTOR * const currMV,          VECTOR * const currMV,
143          VECTOR * const currPMV);          VECTOR * const currPMV);
144    
145    
146    typedef int32_t (MainSearch16Func)(
147            const uint8_t * const pRef,
148            const uint8_t * const pRefH,
149            const uint8_t * const pRefV,
150            const uint8_t * const pRefHV,
151            const uint8_t * const cur,
152            const int x, const int y,
153            int32_t startx, int32_t starty,
154            int32_t iMinSAD,
155            VECTOR * const currMV,
156            const VECTOR * const pmv,
157            const int32_t min_dx, const int32_t max_dx,
158            const int32_t min_dy, const int32_t max_dy,
159            const int32_t iEdgedWidth,
160            const int32_t iDiamondSize,
161            const int32_t iFcode,
162            const int32_t iQuant,
163            int iFound);
164    
165    typedef MainSearch16Func* MainSearch16FuncPtr;
166    
 /*  
  * diamond search stuff  
  * keep the the sequence in circular order (so optimization works)  
  */  
167    
168  typedef struct  typedef int32_t (MainSearch8Func)(
169  {          const uint8_t * const pRef,
170          int32_t dx;          const uint8_t * const pRefH,
171          int32_t dy;          const uint8_t * const pRefV,
172  }          const uint8_t * const pRefHV,
173  DPOINT;          const uint8_t * const cur,
174            const int x, const int y,
175            int32_t startx, int32_t starty,
176            int32_t iMinSAD,
177            VECTOR * const currMV,
178            const VECTOR * const pmv,
179            const int32_t min_dx, const int32_t max_dx,
180            const int32_t min_dy, const int32_t max_dy,
181            const int32_t iEdgedWidth,
182            const int32_t iDiamondSize,
183            const int32_t iFcode,
184            const int32_t iQuant,
185            int iFound);
186    
187    typedef MainSearch8Func* MainSearch8FuncPtr;
188    
189  static const DPOINT diamond_small[4] =  static int32_t lambda_vec16[32] =  /* rounded values for lambda param for weight of motion bits as in modified H.26L */
190  {          {     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),
191          {0, 1}, {1, 0}, {0, -1}, {-1, 0}          (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),
192  };          (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),
193            (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),
194            (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),
195            (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),
196            (int)(36.4949+0.5)      };
197    
198    static int32_t *lambda_vec8 = lambda_vec16;     /* same table for INTER and INTER4V for now*/
199    
 static const DPOINT diamond_large[8] =  
 {  
         {0, 2}, {1, 1}, {2, 0}, {1, -1}, {0, -2}, {-1, -1}, {-2, 0}, {-1, 1}  
 };  
200    
201    
202  // mv.length table  // mv.length table
# Line 160  Line 234 
234  }  }
235    
236    
237  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)  
   
238  {  {
239      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));
240  }  }
241    
242    static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode, const uint32_t iQuant)
243    
   
   
 /* 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)  
244  {  {
245        return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));
         const int search_range = 32 << (fcode - 1);  
         const int high = search_range - 1;  
         const int low = -search_range;  
   
         // convert full-pixel measurements to half pixel  
         const int hp_width = 2 * width;  
         const int hp_height = 2 * height;  
         const int hp_edge = 2 * block_sz;  
         const int hp_x = 2 * (x) * block_sz;            // we need _right end_ of block, not x-coordinate  
         const int hp_y = 2 * (y) * block_sz;            // same for _bottom end_  
   
         *max_dx = MIN(high,     hp_width - hp_x);  
         *max_dy = MIN(high,     hp_height - hp_y);  
         *min_dx = MAX(low,      -(hp_edge + hp_x));  
         *min_dy = MAX(low,      -(hp_edge + hp_y));  
   
 }  
   
   
 /*  
  * getref: calculate reference image pointer  
  * the decision to use interpolation h/v/hv or the normal image is  
  * based on dx & dy.  
  */  
   
 static __inline const uint8_t * get_ref(  
         const uint8_t * const refn,  
         const uint8_t * const refh,  
         const uint8_t * const refv,  
         const uint8_t * const refhv,  
         const uint32_t x, const uint32_t y,  
         const uint32_t block,                                   // block dimension, 8 or 16  
         const int32_t dx, const int32_t dy,  
         const uint32_t stride)  
 {  
   
         switch ( ((dx&1)<<1) + (dy&1) )         // ((dx%2)?2:0)+((dy%2)?1:0)  
         {  
         case 0  : return refn + (x*block+dx/2) + (y*block+dy/2)*stride;  
         case 1  : return refv + (x*block+dx/2) + (y*block+(dy-1)/2)*stride;  
         case 2  : return refh + (x*block+(dx-1)/2) + (y*block+dy/2)*stride;  
         default :  
         case 3  : return refhv + (x*block+(dx-1)/2) + (y*block+(dy-1)/2)*stride;  
         }  
   
246  }  }
247    
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    
252  #ifndef SEARCH16  #ifndef SEARCH16
253  #define SEARCH16        PMVfastSearch16  #define SEARCH16        PMVfastSearch16
254    //#define SEARCH16      FullSearch16
255    //#define SEARCH16      EPZSSearch16
256  #endif  #endif
257    
258  #ifndef SEARCH8  #ifndef SEARCH8
259  #define SEARCH8         PMVfastSearch8  #define SEARCH8         PMVfastSearch8
260    //#define SEARCH8       EPZSSearch8
261  #endif  #endif
262    
263  bool MotionEstimation(  bool MotionEstimation(
         MACROBLOCK * const pMBs,  
264          MBParam * const pParam,          MBParam * const pParam,
265          const IMAGE * const pRef,          FRAMEINFO * const current,
266            FRAMEINFO * const reference,
267          const IMAGE * const pRefH,          const IMAGE * const pRefH,
268          const IMAGE * const pRefV,          const IMAGE * const pRefV,
269          const IMAGE * const pRefHV,          const IMAGE * const pRefHV,
         IMAGE * const pCurrent,  
270          const uint32_t iLimit)          const uint32_t iLimit)
271    
272  {  {
273          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
274          const uint32_t iHcount = pParam->mb_height;          const uint32_t iHcount = pParam->mb_height;
275            MACROBLOCK * const pMBs = current->mbs;
276            MACROBLOCK * const prevMBs = reference->mbs;    // previous frame
277    
278          uint32_t i, j, iIntra = 0;          const IMAGE * const pCurrent = &current->image;
279            const IMAGE * const pRef = &reference->image;
280    
281          VECTOR mv16;          const VECTOR zeroMV = {0,0};
         VECTOR pmv16;  
282    
283          int32_t sad8 = 0;          int32_t x, y;
284          int32_t sad16;          int32_t iIntra = 0;
285          int32_t deviation;          VECTOR pmv;
286    
287          // note: i==horizontal, j==vertical          if (sadInit)
288          for (i = 0; i < iHcount; i++)                  (*sadInit)();
                 for (j = 0; j < iWcount; j++)  
                 {  
                         MACROBLOCK *pMB = &pMBs[j + i * iWcount];  
289    
290                          sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,          for (y = 0; y < iHcount; y++)
291                                           j, i, pParam->motion_flags,                  for (x = 0; x < iWcount; x++)
292                                           pParam, pMBs, &mv16, &pmv16);                  {
293                          pMB->sad16=sad16;                          MACROBLOCK* const pMB = &pMBs[x + y * iWcount];
294    
295                            pMB->sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
296                                             x, y, current->motion_flags, current->quant, current->fcode,
297                                             pParam, pMBs, prevMBs, &pMB->mv16, &pMB->pmvs[0]);
298                    }
299    
300                          /* decide: MODE_INTER or MODE_INTRA          for (y = 0; y < iHcount; y++)
301                             if (dev_intra < sad_inter - 2 * nb) use_intra                  for (x = 0; x < iWcount; x++)
302                          */                  {
303                            MACROBLOCK* const pMB = &pMBs[x + y * iWcount];
304    
305                          deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width);                          if (0 < (pMB->sad16 - MV16_INTER_BIAS))
306                            {
307                                    int32_t deviation;
308                                    deviation = dev16(pCurrent->y + x*16 + y*16*pParam->edged_width,
309                                                             pParam->edged_width);
310    
311                          if (deviation < (sad16 - INTER_BIAS))                                  if (deviation < (pMB->sad16 - MV16_INTER_BIAS))
312                          {                          {
313                                  pMB->mode = MODE_INTRA;                                  pMB->mode = MODE_INTRA;
314                                  pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;                                          pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]
315                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;                                                                   = pMB->mvs[2] = pMB->mvs[3] = zeroMV;
316                                            pMB->sad16 = pMB->sad8[0] = pMB->sad8[1]
317                                                                 = pMB->sad8[2] = pMB->sad8[3] = 0;
318    
319                                  iIntra++;                                  iIntra++;
320                                  if(iIntra >= iLimit)                                  if(iIntra >= iLimit)
# Line 320  Line 322 
322    
323                                  continue;                                  continue;
324                          }                          }
   
                         if (pParam->global_flags & XVID_INTER4V)  
                         {  
                                 pMB->sad8[0] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                                        2 * j, 2 * i, mv16.x, mv16.y, pParam->motion_flags,  
                                                        pParam, pMBs, &pMB->mvs[0], &pMB->pmvs[0]);  
   
                                 pMB->sad8[1] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                                        2 * j + 1, 2 * i, mv16.x, mv16.y, pParam->motion_flags,  
                                                        pParam, pMBs, &pMB->mvs[1], &pMB->pmvs[1]);  
   
                                 pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                                        2 * j, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,  
                                                        pParam, pMBs, &pMB->mvs[2], &pMB->pmvs[2]);  
   
                                 pMB->sad8[3] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                                        2 * j + 1, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,  
                                                        pParam, pMBs, &pMB->mvs[3], &pMB->pmvs[3]);  
   
                                 sad8 = pMB->sad8[0] + pMB->sad8[1] + pMB->sad8[2] + pMB->sad8[3];  
325                          }                          }
326    
327                            if ( (current->global_flags & XVID_INTER4V)
328                                    && (!(current->global_flags & XVID_LUMIMASKING)
329                                            || pMB->dquant == NO_CHANGE) )
330                            {
331                                    int32_t sad8 = 129; //IMV16X16 * current->quant;
332    
333                                    if (sad8 < pMB->sad16)
334                                    sad8 += pMB->sad8[0]
335                                            = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
336                                                           2*x, 2*y, pMB->mv16.x, pMB->mv16.y,
337                                                               current->motion_flags, current->quant, current->fcode,
338                                                           pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]);
339    
340                                    if (sad8 < pMB->sad16)
341                                    sad8 += pMB->sad8[1]
342                                            = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
343                                   2*x+1, 2*y, pMB->mv16.x, pMB->mv16.y,
344                                                    current->motion_flags, current->quant, current->fcode,
345                                                    pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]);
346    
347                                    if (sad8 < pMB->sad16)
348                                    sad8 += pMB->sad8[2]
349                                            = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
350                                                    2*x, 2*y+1, pMB->mv16.x, pMB->mv16.y,
351                                                    current->motion_flags, current->quant, current->fcode,
352                                                    pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]);
353    
354                                    if (sad8 < pMB->sad16)
355                                    sad8 += pMB->sad8[3]
356                                            = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
357                                                    2*x+1, 2*y+1, pMB->mv16.x, pMB->mv16.y,
358                                                    current->motion_flags, current->quant, current->fcode,
359                                                    pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]);
360    
361                          /* decide: MODE_INTER or MODE_INTER4V                          /* decide: MODE_INTER or MODE_INTER4V
362                             mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
363                          */                          */
364    
365                          if (pMB->dquant == NO_CHANGE) {                                  if (sad8 < pMB->sad16)
366                                  if (((pParam->global_flags & XVID_INTER4V)==0) ||                                  {
                                     (sad16 < (sad8 + (int32_t)(IMV16X16 * pParam->quant)))) {  
   
                                         sad8 = sad16;  
                                         pMB->mode = MODE_INTER;  
                                         pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;  
                                         pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;  
                                         pMB->pmvs[0].x = pmv16.x;  
                                         pMB->pmvs[0].y = pmv16.y;  
                                 }  
                                 else  
367                                          pMB->mode = MODE_INTER4V;                                          pMB->mode = MODE_INTER4V;
368                   pMB->sad8[0] *= 4;
369                                            pMB->sad8[1] *= 4;
370                                            pMB->sad8[2] *= 4;
371                                            pMB->sad8[3] *= 4;
372                                            continue;
373                          }                          }
374                          else                          }
375                          {  
                                 sad8 = sad16;  
376                                  pMB->mode = MODE_INTER;                                  pMB->mode = MODE_INTER;
377                                  pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
378                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;           pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = pMB->sad16;
379                                  pMB->pmvs[0].x = pmv16.x;  
380                                  pMB->pmvs[0].y = pmv16.y;                          if (current->global_flags & XVID_INTER4V)
381                            {       pmv = get_pmv(pMBs, x, y, pParam->mb_width, 0);
382                                    // get_pmv has to be called again. inter4v changes predictors
383    
384                                    pMB->pmvs[0].x = pMB->mv16.x - pmv.x;
385                                    pMB->pmvs[0].y = pMB->mv16.y - pmv.y;
386                          }                          }
387                  }                  }
   
388          return 0;          return 0;
389  }  }
390    
 #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )  
   
 #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )  
   
   
391  #define CHECK_MV16_ZERO {\  #define CHECK_MV16_ZERO {\
392    if ( (0 <= max_dx) && (0 >= min_dx) \    if ( (0 <= max_dx) && (0 >= min_dx) \
393      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
394    { \    { \
395      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); \
396      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; \  
397      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
398      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
399  }  }
400    
401    #define NOCHECK_MV16_CANDIDATE(X,Y) { \
402        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
403        iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
404        if (iSAD < iMinSAD) \
405        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
406    }
407    
408  #define CHECK_MV16_CANDIDATE(X,Y) { \  #define CHECK_MV16_CANDIDATE(X,Y) { \
409    if ( ((X) <= max_dx) && ((X) >= min_dx) \    if ( ((X) <= max_dx) && ((X) >= min_dx) \
410      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
411    { \    { \
412      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); \
413      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);\
414      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
415      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
416  }  }
# Line 408  Line 420 
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); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
426  }  }
# Line 418  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); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
436  }  }
# Line 426  Line 438 
438    
439  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
440    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); \
441    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);\
442    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
443    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
444  }  }
445    
446    #define NOCHECK_MV8_CANDIDATE(X,Y) \
447      { \
448        iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
449        iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
450        if (iSAD < iMinSAD) \
451        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
452    }
453    
454  #define CHECK_MV8_CANDIDATE(X,Y) { \  #define CHECK_MV8_CANDIDATE(X,Y) { \
455    if ( ((X) <= max_dx) && ((X) >= min_dx) \    if ( ((X) <= max_dx) && ((X) >= min_dx) \
456      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
457    { \    { \
458      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); \
459      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);\
460      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
461      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
462  }  }
# Line 447  Line 466 
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); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
472  }  }
# Line 457  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); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
482  }  }
# Line 472  Line 491 
491                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
492                                          const int x, const int y,                                          const int x, const int y,
493                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
494                                            const uint32_t iQuant,
495                                            const uint32_t iFcode,
496                                          MBParam * const pParam,                                          MBParam * const pParam,
497                                          MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
498                                            const MACROBLOCK * const prevMBs,
499                                          VECTOR * const currMV,                                          VECTOR * const currMV,
500                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
501  {  {
502          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
         const int32_t iQuant = pParam->quant;  
503          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
504          int32_t iSAD;          int32_t iSAD;
505          int32_t pred_x,pred_y;          int32_t pred_x,pred_y;
# Line 501  Line 522 
522  }  }
523  */  */
524    
525  int32_t PMVfastSearch16_MainSearch(  int32_t Diamond16_MainSearch(
526          const uint8_t * const pRef,          const uint8_t * const pRef,
527          const uint8_t * const pRefH,          const uint8_t * const pRefH,
528          const uint8_t * const pRefV,          const uint8_t * const pRefV,
# Line 558  Line 579 
579          return iMinSAD;          return iMinSAD;
580  }  }
581    
582  int32_t PMVfastSearch16_Refine(  int32_t Square16_MainSearch(
583          const uint8_t * const pRef,          const uint8_t * const pRef,
584          const uint8_t * const pRefH,          const uint8_t * const pRefH,
585          const uint8_t * const pRefV,          const uint8_t * const pRefV,
586          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
587          const uint8_t * const cur,          const uint8_t * const cur,
588          const int x, const int y,          const int x, const int y,
589          VECTOR * const currMV,                                          int32_t startx, int32_t starty,
590          int32_t iMinSAD,          int32_t iMinSAD,
591                                            VECTOR * const currMV,
592          const VECTOR * const pmv,          const VECTOR * const pmv,
593          const int32_t min_dx, const int32_t max_dx,          const int32_t min_dx, const int32_t max_dx,
594          const int32_t min_dy, const int32_t max_dy,          const int32_t min_dy, const int32_t max_dy,
595                                            const int32_t iEdgedWidth,
596                                            const int32_t iDiamondSize,
597          const int32_t iFcode,          const int32_t iFcode,
598          const int32_t iQuant,          const int32_t iQuant,
599          const int32_t iEdgedWidth)                                          int iFound)
600  {  {
601  /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  /* Do a square search around given starting point, return SAD of best */
602    
603            int32_t iDirection=0;
604          int32_t iSAD;          int32_t iSAD;
605          VECTOR backupMV = *currMV;          VECTOR backupMV;
606            backupMV.x = startx;
607          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y-1);          backupMV.y = starty;
         CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y-1);  
         CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y-1);  
         CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y);  
         CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y);  
         CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y+1);  
         CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y+1);  
         CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y+1);  
   
         return iMinSAD;  
 }  
   
 #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  
608    
609  int32_t PMVfastSearch16(  /* It's one search with full square pattern, and new parts for all following diamonds */
         const uint8_t * const pRef,  
         const uint8_t * const pRefH,  
         const uint8_t * const pRefV,  
         const uint8_t * const pRefHV,  
         const IMAGE * const pCur,  
         const int x, const int y,  
         const uint32_t MotionFlags,  
         MBParam * const pParam,  
         MACROBLOCK * const pMBs,  
         VECTOR * const currMV,  
         VECTOR * const currPMV)  
 {  
         const uint32_t iWcount = pParam->mb_width;  
         const int32_t iFcode = pParam->fixed_code;  
         const int32_t iQuant = pParam->quant;  
         const int32_t iWidth = pParam->width;  
         const int32_t iHeight = pParam->height;  
         const int32_t iEdgedWidth = pParam->edged_width;  
610    
611          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;  /*   new direction are extra, so 1-4 is normal diamond
612          537
613          1*2
614          648
615    */
616    
617          int32_t iDiamondSize;          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
618            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
619            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
620            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
621    
622          int32_t min_dx;          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
623          int32_t max_dx;          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
624          int32_t min_dy;          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
625          int32_t max_dy;          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
626    
         int32_t iFound;  
627    
628          VECTOR newMV;          if (iDirection)
629          VECTOR backupMV;        /* just for PMVFAST */                  while (!iFound)
630                    {
631                            iFound = 1;
632                            backupMV=*currMV;
633    
634          VECTOR pmv[4];                          switch (iDirection)
635          int32_t psad[4];                          {
636                                    case 1:
637                                            CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
638                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
639                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
640                                            break;
641                                    case 2:
642                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
643                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
644                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
645                                            break;
646    
647          MACROBLOCK * const pMB = pMBs + x + y * iWcount;                                  case 3:
648                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
649                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
650                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
651                                            break;
652    
653          static int32_t threshA,threshB;                                  case 4:
654          int32_t bPredEq;                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
655          int32_t iMinSAD,iSAD;                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
656                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
657                                            break;
658    
659  /* Get maximum range */                                  case 5:
660          get_range(&min_dx, &max_dx, &min_dy, &max_dy,                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
661                    x, y, 16, iWidth, iHeight, iFcode);                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
662                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
663                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
664                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
665                                            break;
666    
667  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */                                  case 6:
668                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
669                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
670    
671          if (!(MotionFlags & PMV_HALFPEL16 ))                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
672          { min_dx = EVEN(min_dx);                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
673          max_dx = EVEN(max_dx);                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
         min_dy = EVEN(min_dy);  
         max_dy = EVEN(max_dy);  
         }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */  
674    
675                                            break;
676    
677          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);                                  case 7:
678                                            CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
679                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
680                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
681                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
682                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
683                                            break;
684    
685          if ((x==0) && (y==0) )                                  case 8:
686          {                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
687                  threshA =  512;                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
688                  threshB = 1024;                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
689                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
690                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
691                                            break;
692                            default:
693                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
694                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
695                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
696                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
697    
698                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
699                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
700                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
701                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
702                                            break;
703                            }
704          }          }
705          else          else
706          {          {
707                  threshA = psad[0];                          currMV->x = startx;
708                  threshB = threshA+256;                          currMV->y = starty;
709                  if (threshA< 512) threshA =  512;                  }
710                  if (threshA>1024) threshA = 1024;          return iMinSAD;
                 if (threshB>1792) threshB = 1792;  
711          }          }
712    
         iFound=0;  
   
 /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  
    vector of the median.  
    If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2  
 */  
   
         if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[0]) ) )  
                 iFound=2;  
   
 /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  
    Otherwise select large Diamond Search.  
 */  
713    
714          if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536) || (bPredEq) )  int32_t Full16_MainSearch(
715                  iDiamondSize=1; // halfpel!                                          const uint8_t * const pRef,
716          else                                          const uint8_t * const pRefH,
717                  iDiamondSize=2; // halfpel!                                          const uint8_t * const pRefV,
718                                            const uint8_t * const pRefHV,
719                                            const uint8_t * const cur,
720                                            const int x, const int y,
721                                            int32_t startx, int32_t starty,
722                                            int32_t iMinSAD,
723                                            VECTOR * const currMV,
724                                            const VECTOR * const pmv,
725                                            const int32_t min_dx, const int32_t max_dx,
726                                            const int32_t min_dy, const int32_t max_dy,
727                                            const int32_t iEdgedWidth,
728                                            const int32_t iDiamondSize,
729                                            const int32_t iFcode,
730                                            const int32_t iQuant,
731                                            int iFound)
732    {
733            int32_t iSAD;
734            int32_t dx,dy;
735            VECTOR backupMV;
736            backupMV.x = startx;
737            backupMV.y = starty;
738    
739          if (!(MotionFlags & PMV_HALFPELDIAMOND16) )          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
740                  iDiamondSize*=2;                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
741                            NOCHECK_MV16_CANDIDATE(dx,dy);
742    
743            return iMinSAD;
744    }
745    
746    int32_t Full8_MainSearch(
747                                            const uint8_t * const pRef,
748                                            const uint8_t * const pRefH,
749                                            const uint8_t * const pRefV,
750                                            const uint8_t * const pRefHV,
751                                            const uint8_t * const cur,
752                                            const int x, const int y,
753                                            int32_t startx, int32_t starty,
754                                            int32_t iMinSAD,
755                                            VECTOR * const currMV,
756                                            const VECTOR * const pmv,
757                                            const int32_t min_dx, const int32_t max_dx,
758                                            const int32_t min_dy, const int32_t max_dy,
759                                            const int32_t iEdgedWidth,
760                                            const int32_t iDiamondSize,
761                                            const int32_t iFcode,
762                                            const int32_t iQuant,
763                                            int iFound)
764    {
765            int32_t iSAD;
766            int32_t dx,dy;
767            VECTOR backupMV;
768            backupMV.x = startx;
769            backupMV.y = starty;
770    
771            for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
772                    for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
773                            NOCHECK_MV8_CANDIDATE(dx,dy);
774    
775            return iMinSAD;
776    }
777    
778    
779    
780    int32_t Halfpel16_Refine(
781            const uint8_t * const pRef,
782            const uint8_t * const pRefH,
783            const uint8_t * const pRefV,
784            const uint8_t * const pRefHV,
785            const uint8_t * const cur,
786            const int x, const int y,
787            VECTOR * const currMV,
788            int32_t iMinSAD,
789            const VECTOR * const pmv,
790            const int32_t min_dx, const int32_t max_dx,
791            const int32_t min_dy, const int32_t max_dy,
792            const int32_t iFcode,
793            const int32_t iQuant,
794            const int32_t iEdgedWidth)
795    {
796    /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
797    
798            int32_t iSAD;
799            VECTOR backupMV = *currMV;
800    
801            CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y-1);
802            CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y-1);
803            CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y-1);
804            CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y);
805            CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y);
806            CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y+1);
807            CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y+1);
808            CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y+1);
809    
810            return iMinSAD;
811    }
812    
813    #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
814    
815    
816    int32_t PMVfastSearch16(
817                                            const uint8_t * const pRef,
818                                            const uint8_t * const pRefH,
819                                            const uint8_t * const pRefV,
820                                            const uint8_t * const pRefHV,
821                                            const IMAGE * const pCur,
822                                            const int x, const int y,
823                                            const uint32_t MotionFlags,
824                                            const uint32_t iQuant,
825                                            const uint32_t iFcode,
826                                            const MBParam * const pParam,
827                                            const MACROBLOCK * const pMBs,
828                                            const MACROBLOCK * const prevMBs,
829                                            VECTOR * const currMV,
830                                            VECTOR * const currPMV)
831    {
832        const uint32_t iWcount = pParam->mb_width;
833            const int32_t iWidth = pParam->width;
834            const int32_t iHeight = pParam->height;
835            const int32_t iEdgedWidth = pParam->edged_width;
836    
837            const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
838    
839            int32_t iDiamondSize;
840    
841            int32_t min_dx;
842            int32_t max_dx;
843            int32_t min_dy;
844            int32_t max_dy;
845    
846            int32_t iFound;
847    
848            VECTOR newMV;
849            VECTOR backupMV;        /* just for PMVFAST */
850    
851            VECTOR pmv[4];
852            int32_t psad[4];
853    
854    //      const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
855            const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
856    
857            static int32_t threshA,threshB;
858            int32_t bPredEq;
859            int32_t iMinSAD,iSAD;
860    
861    /* Get maximum range */
862            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
863                      x, y, 16, iWidth, iHeight, iFcode);
864    
865    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
866    
867            if (!(MotionFlags & PMV_HALFPEL16 ))
868            { min_dx = EVEN(min_dx);
869            max_dx = EVEN(max_dx);
870            min_dy = EVEN(min_dy);
871            max_dy = EVEN(max_dy);
872            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
873    
874    
875            bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
876    
877            if ((x==0) && (y==0) )
878            {
879                    threshA =  512;
880                    threshB = 1024;
881    
882            }
883            else
884            {
885                    threshA = psad[0];
886                    threshB = threshA+256;
887                    if (threshA< 512) threshA =  512;
888                    if (threshA>1024) threshA = 1024;
889                    if (threshB>1792) threshB = 1792;
890            }
891    
892            iFound=0;
893    
894  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
895     MinSAD=SAD     MinSAD=SAD
# Line 696  Line 898 
898     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
899  */  */
900    
   
 // Prepare for main loop  
   
901          *currMV=pmv[0];         /* current best := prediction */          *currMV=pmv[0];         /* current best := prediction */
902          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16 ))
903          {       /* This should NOT be necessary! */          {       /* This should NOT be necessary! */
# Line 726  Line 925 
925          iMinSAD = sad16( cur,          iMinSAD = sad16( cur,
926                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
927                           iEdgedWidth, MV_MAX_ERROR);                           iEdgedWidth, MV_MAX_ERROR);
928          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);
929    
930          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
931            {
932                    if (iMinSAD < 2*iQuant) // high chances for SKIP-mode
933                    {
934                            if (!MVzero(*currMV))
935          {          {
936                                    iMinSAD += MV16_00_BIAS;
937                                    CHECK_MV16_ZERO;                // (0,0) saves space for letterboxed pictures
938                                    iMinSAD -= MV16_00_BIAS;
939                            }
940                    }
941    
942                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
943                          goto step10b;                          goto PMVfast16_Terminate_without_Refine;
944                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
945                          goto step10;                          goto PMVfast16_Terminate_with_Refine;
946          }          }
947    
948    
949    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
950       vector of the median.
951       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
952    */
953    
954            if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[0]) ) )
955                    iFound=2;
956    
957    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
958       Otherwise select large Diamond Search.
959    */
960    
961            if ( (!MVzero(pmv[0])) || (threshB<1536) || (bPredEq) )
962                    iDiamondSize=1; // halfpel!
963            else
964                    iDiamondSize=2; // halfpel!
965    
966            if (!(MotionFlags & PMV_HALFPELDIAMOND16) )
967                    iDiamondSize*=2;
968    
969  /*  /*
970     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.
971     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
972     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
973     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
974  */  */
975    
976  // (0,0) is always possible  // (0,0) is always possible
977    
978            if (!MVzero(pmv[0]))
979          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
980    
981  // previous frame MV is always possible  // previous frame MV is always possible
982          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);  
983            if (!MVzero(prevMB->mvs[0]))
984            if (!MVequal(prevMB->mvs[0],pmv[0]))
985                    CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
986    
987  // left neighbour, if allowed  // left neighbour, if allowed
988          if (x != 0)  
989            if (!MVzero(pmv[1]))
990            if (!MVequal(pmv[1],prevMB->mvs[0]))
991            if (!MVequal(pmv[1],pmv[0]))
992          {          {
993                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!(MotionFlags & PMV_HALFPEL16 ))
994                  {       pmv[1].x = EVEN(pmv[1].x);                  {       pmv[1].x = EVEN(pmv[1].x);
995                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
996                  }                  }
997    
998                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
999          }          }
1000    
1001  // top neighbour, if allowed  // top neighbour, if allowed
1002          if (y != 0)          if (!MVzero(pmv[2]))
1003            if (!MVequal(pmv[2],prevMB->mvs[0]))
1004            if (!MVequal(pmv[2],pmv[0]))
1005            if (!MVequal(pmv[2],pmv[1]))
1006          {          {
1007                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!(MotionFlags & PMV_HALFPEL16 ))
1008                  {       pmv[2].x = EVEN(pmv[2].x);                  {       pmv[2].x = EVEN(pmv[2].x);
# Line 771  Line 1011 
1011                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1012    
1013  // top right neighbour, if allowed  // top right neighbour, if allowed
1014                  if (x != (iWcount-1))                  if (!MVzero(pmv[3]))
1015                    if (!MVequal(pmv[3],prevMB->mvs[0]))
1016                    if (!MVequal(pmv[3],pmv[0]))
1017                    if (!MVequal(pmv[3],pmv[1]))
1018                    if (!MVequal(pmv[3],pmv[2]))
1019                  {                  {
1020                          if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!(MotionFlags & PMV_HALFPEL16 ))
1021                          {       pmv[3].x = EVEN(pmv[3].x);                          {       pmv[3].x = EVEN(pmv[3].x);
# Line 781  Line 1025 
1025                  }                  }
1026          }          }
1027    
1028            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96)*/ )
1029                    iMinSAD -= MV16_00_BIAS;
1030    
1031    
1032  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1033     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.
1034  */  */
1035    
1036          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
1037          {          {
1038                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1039                          goto step10b;                          goto PMVfast16_Terminate_without_Refine;
1040                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
1041                          goto step10;                          goto PMVfast16_Terminate_with_Refine;
1042          }          }
1043    
1044    
# Line 807  Line 1055 
1055          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1056    
1057  /* 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 */
1058          iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1059                                            x, y,                                            x, y,
1060                                            currMV->x, currMV->y, iMinSAD, &newMV,                                            currMV->x, currMV->y, iMinSAD, &newMV,
1061                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 823  Line 1071 
1071  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1072    
1073                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0],backupMV)) )
1074                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1075                                                            x, y,                                                            x, y,
1076                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1077                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 836  Line 1084 
1084                  }                  }
1085    
1086                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1087                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1088                                                            x, y,                                                            x, y,
1089                                                            0, 0, iMinSAD, &newMV,                                                            0, 0, iMinSAD, &newMV,
1090                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 853  Line 1101 
1101     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.
1102  */  */
1103    
1104   step10:  PMVfast16_Terminate_with_Refine:
1105          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1106                  iMinSAD = PMVfastSearch16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1107                                                    x, y,                                                    x, y,
1108                                                    currMV, iMinSAD,                                                    currMV, iMinSAD,
1109                                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1110    
1111   step10b:  PMVfast16_Terminate_without_Refine:
1112          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1113          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
1114          return iMinSAD;          return iMinSAD;
# Line 871  Line 1119 
1119    
1120    
1121    
1122  int32_t PMVfastSearch8_MainSearch(  int32_t Diamond8_MainSearch(
1123          const uint8_t * const pRef,          const uint8_t * const pRef,
1124          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1125          const uint8_t * const pRefV,          const uint8_t * const pRefV,
# Line 928  Line 1176 
1176          return iMinSAD;          return iMinSAD;
1177  }  }
1178    
1179  int32_t PMVfastSearch8_Refine(  int32_t Halfpel8_Refine(
1180          const uint8_t * const pRef,          const uint8_t * const pRef,
1181          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1182          const uint8_t * const pRefV,          const uint8_t * const pRefV,
# Line 971  Line 1219 
1219          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1220          const IMAGE * const pCur,          const IMAGE * const pCur,
1221          const int x, const int y,          const int x, const int y,
1222          const int start_x, int start_y,                                          const int start_x, const int start_y,
1223          const uint32_t MotionFlags,          const uint32_t MotionFlags,
1224          MBParam * const pParam,                                          const uint32_t iQuant,
1225          MACROBLOCK * const pMBs,                                          const uint32_t iFcode,
1226                                            const MBParam * const pParam,
1227                                            const MACROBLOCK * const pMBs,
1228                                            const MACROBLOCK * const prevMBs,
1229          VECTOR * const currMV,          VECTOR * const currMV,
1230          VECTOR * const currPMV)          VECTOR * const currPMV)
1231  {  {
1232          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;  
1233          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1234          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
1235          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 999  Line 1247 
1247          int32_t psad[4];          int32_t psad[4];
1248          VECTOR newMV;          VECTOR newMV;
1249          VECTOR backupMV;          VECTOR backupMV;
1250            VECTOR startMV;
1251    
1252          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //      const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1253            const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1254    
1255          static int32_t threshA,threshB;          static int32_t threshA,threshB;
1256          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
1257          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1258    
1259          int32_t iSubBlock = ((y&1)<<1) + (x&1);          int32_t iSubBlock = (y&1)+(y&1) + (x&1);
1260    
1261            /* Init variables */
1262            startMV.x = start_x;
1263            startMV.y = start_y;
1264    
1265  /* Get maximum range */  /* Get maximum range */
1266          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1267                    x, y, 8, iWidth, iHeight, iFcode);                    x, y, 8, iWidth, iHeight, iFcode);
1268    
 /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */  
   
1269          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))
1270          { min_dx = EVEN(min_dx);          { min_dx = EVEN(min_dx);
1271          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
# Line 1041  Line 1293 
1293    
1294          iFound=0;          iFound=0;
1295    
 /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  
    vector of the median.  
    If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2  
 */  
   
         if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[iSubBlock]) ) )  
                 iFound=2;  
   
 /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  
    Otherwise select large Diamond Search.  
 */  
   
         if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536/4) || (bPredEq) )  
                 iDiamondSize=1; // 1 halfpel!  
         else  
                 iDiamondSize=2; // 2 halfpel = 1 full pixel!  
   
         if (!(MotionFlags & PMV_HALFPELDIAMOND8) )  
                 iDiamondSize*=2;  
   
1296  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1297     MinSAD=SAD     MinSAD=SAD
1298     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 1071  Line 1303 
1303    
1304  // Prepare for main loop  // Prepare for main loop
1305    
1306          currMV->x=start_x;              /* start with mv16 */          *currMV = startMV;
         currMV->y=start_y;  
1307    
1308          iMinSAD = sad8( cur,          iMinSAD = sad8( cur,
1309                          get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                          get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
1310                          iEdgedWidth);                          iEdgedWidth);
1311          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);
1312    
1313          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock]))
1314                                    && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1315          {          {
1316                  if (MotionFlags & PMV_QUICKSTOP8)                  if (MotionFlags & PMV_QUICKSTOP16)
1317                          goto step10_8b;                          goto PMVfast8_Terminate_without_Refine;
1318                  if (MotionFlags & PMV_EARLYSTOP8)                  if (MotionFlags & PMV_EARLYSTOP16)
1319                          goto step10_8;                          goto PMVfast8_Terminate_with_Refine;
1320          }          }
1321    
1322    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1323       vector of the median.
1324       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1325    */
1326    
1327            if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[iSubBlock]) ) )
1328                    iFound=2;
1329    
1330    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1331       Otherwise select large Diamond Search.
1332    */
1333    
1334            if ( (!MVzero(pmv[0])) || (threshB<1536/4) || (bPredEq) )
1335                    iDiamondSize=1; // 1 halfpel!
1336            else
1337                    iDiamondSize=2; // 2 halfpel = 1 full pixel!
1338    
1339            if (!(MotionFlags & PMV_HALFPELDIAMOND8) )
1340                    iDiamondSize*=2;
1341    
1342    
1343  /*  /*
1344     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.
1345     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1346     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1347     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1348  */  */
1349    
1350  // the prediction might be even better than mv16  // the median prediction might be even better than mv16
1351    
1352            if (!MVequal(pmv[0],startMV))
1353          CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);          CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);
1354    
1355  // (0,0) is always possible  // (0,0) if needed
1356            if (!MVzero(pmv[0]))
1357            if (!MVzero(startMV))
1358          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
1359    
1360  // previous frame MV is always possible  // previous frame MV if needed
1361          CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);          if (!MVzero(prevMB->mvs[iSubBlock]))
1362            if (!MVequal(prevMB->mvs[iSubBlock],startMV))
1363            if (!MVequal(prevMB->mvs[iSubBlock],pmv[0]))
1364            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
1365    
1366  // left neighbour, if allowed          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1367          if (psad[1] != MV_MAX_ERROR)          {
1368                    if (MotionFlags & PMV_QUICKSTOP16)
1369                            goto PMVfast8_Terminate_without_Refine;
1370                    if (MotionFlags & PMV_EARLYSTOP16)
1371                            goto PMVfast8_Terminate_with_Refine;
1372            }
1373    
1374    
1375    // left neighbour, if allowed and needed
1376            if (!MVzero(pmv[1]))
1377            if (!MVequal(pmv[1],startMV))
1378            if (!MVequal(pmv[1],prevMB->mvs[iSubBlock]))
1379            if (!MVequal(pmv[1],pmv[0]))
1380          {          {
1381                  if (!(MotionFlags & PMV_HALFPEL8 ))                  if (!(MotionFlags & PMV_HALFPEL8 ))
1382                  {       pmv[1].x = EVEN(pmv[1].x);                  {       pmv[1].x = EVEN(pmv[1].x);
# Line 1113  Line 1385 
1385                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1386          }          }
1387    
1388  // top neighbour, if allowed  // top neighbour, if allowed and needed
1389          if (psad[2] != MV_MAX_ERROR)          if (!MVzero(pmv[2]))
1390            if (!MVequal(pmv[2],startMV))
1391            if (!MVequal(pmv[2],prevMB->mvs[iSubBlock]))
1392            if (!MVequal(pmv[2],pmv[0]))
1393            if (!MVequal(pmv[2],pmv[1]))
1394          {          {
1395                  if (!(MotionFlags & PMV_HALFPEL8 ))                  if (!(MotionFlags & PMV_HALFPEL8 ))
1396                  {       pmv[2].x = EVEN(pmv[2].x);                  {       pmv[2].x = EVEN(pmv[2].x);
# Line 1122  Line 1398 
1398                  }                  }
1399                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1400    
1401  // top right neighbour, if allowed  // top right neighbour, if allowed and needed
1402                  if (psad[3] != MV_MAX_ERROR)          if (!MVzero(pmv[3]))
1403            if (!MVequal(pmv[3],startMV))
1404            if (!MVequal(pmv[3],prevMB->mvs[iSubBlock]))
1405            if (!MVequal(pmv[3],pmv[0]))
1406            if (!MVequal(pmv[3],pmv[1]))
1407            if (!MVequal(pmv[3],pmv[2]))
1408                  {                  {
1409                          if (!(MotionFlags & PMV_HALFPEL8 ))                          if (!(MotionFlags & PMV_HALFPEL8 ))
1410                          {       pmv[3].x = EVEN(pmv[3].x);                          {       pmv[3].x = EVEN(pmv[3].x);
# Line 1133  Line 1414 
1414                  }                  }
1415          }          }
1416    
1417            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1418                    iMinSAD -= MV8_00_BIAS;
1419    
1420    
1421  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1422     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.
1423  */  */
1424    
1425          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]) ) )
1426          {          {
1427                  if (MotionFlags & PMV_QUICKSTOP8)                  if (MotionFlags & PMV_QUICKSTOP16)
1428                          goto step10_8b;                          goto PMVfast8_Terminate_without_Refine;
1429                  if (MotionFlags & PMV_EARLYSTOP8)                  if (MotionFlags & PMV_EARLYSTOP16)
1430                          goto step10_8;                          goto PMVfast8_Terminate_with_Refine;
1431          }          }
1432    
1433  /************ (Diamond Search)  **************/  /************ (Diamond Search)  **************/
# Line 1158  Line 1443 
1443          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1444    
1445  /* 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 */
1446          iSAD = PMVfastSearch8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1447                                           x, y,                                           x, y,
1448                                           currMV->x, currMV->y, iMinSAD, &newMV,                                           currMV->x, currMV->y, iMinSAD, &newMV,
1449                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 1174  Line 1459 
1459  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1460    
1461                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0],backupMV)) )
1462                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1463                                                            x, y,                                                            x, y,
1464                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1465                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 1187  Line 1472 
1472                  }                  }
1473    
1474                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1475                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1476                                                            x, y,                                                            x, y,
1477                                                            0, 0, iMinSAD, &newMV,                                                            0, 0, iMinSAD, &newMV,
1478                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 1204  Line 1489 
1489     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.
1490  */  */
1491    
1492   step10_8:  PMVfast8_Terminate_with_Refine:
1493          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
1494                  iMinSAD = PMVfastSearch8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1495                                                   x, y,                                                   x, y,
1496                                                   currMV, iMinSAD,                                                   currMV, iMinSAD,
1497                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1498    
  step10_8b:  
1499    
1500    PMVfast8_Terminate_without_Refine:
1501          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1502          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
1503    
1504          return iMinSAD;          return iMinSAD;
1505  }  }
1506    
1507    int32_t EPZSSearch16(
1508                                            const uint8_t * const pRef,
1509                                            const uint8_t * const pRefH,
1510                                            const uint8_t * const pRefV,
1511                                            const uint8_t * const pRefHV,
1512                                            const IMAGE * const pCur,
1513                                            const int x, const int y,
1514                                            const uint32_t MotionFlags,
1515                                            const uint32_t iQuant,
1516                                            const uint32_t iFcode,
1517                                            const MBParam * const pParam,
1518                                            const MACROBLOCK * const pMBs,
1519                                            const MACROBLOCK * const prevMBs,
1520                                            VECTOR * const currMV,
1521                                            VECTOR * const currPMV)
1522    {
1523        const uint32_t iWcount = pParam->mb_width;
1524        const uint32_t iHcount = pParam->mb_height;
1525    
1526            const int32_t iWidth = pParam->width;
1527            const int32_t iHeight = pParam->height;
1528            const int32_t iEdgedWidth = pParam->edged_width;
1529    
1530            const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
1531    
1532            int32_t min_dx;
1533            int32_t max_dx;
1534            int32_t min_dy;
1535            int32_t max_dy;
1536    
1537            VECTOR newMV;
1538            VECTOR backupMV;
1539    
1540            VECTOR pmv[4];
1541            int32_t psad[8];
1542    
1543            static MACROBLOCK * oldMBs = NULL;
1544    //      const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
1545            const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1546            MACROBLOCK * oldMB = NULL;
1547    
1548            static int32_t thresh2;
1549            int32_t bPredEq;
1550            int32_t iMinSAD,iSAD=9999;
1551    
1552            MainSearch16FuncPtr EPZSMainSearchPtr;
1553    
1554            if (oldMBs == NULL)
1555            {       oldMBs = (MACROBLOCK*) calloc(iWcount*iHcount,sizeof(MACROBLOCK));
1556    //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
1557            }
1558            oldMB = oldMBs + x + y * iWcount;
1559    
1560    /* Get maximum range */
1561            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1562                            x, y, 16, iWidth, iHeight, iFcode);
1563    
1564            if (!(MotionFlags & PMV_HALFPEL16 ))
1565            { min_dx = EVEN(min_dx);
1566              max_dx = EVEN(max_dx);
1567              min_dy = EVEN(min_dy);
1568              max_dy = EVEN(max_dy);
1569            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1570    
1571            bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1572    
1573    /* Step 4: Calculate SAD around the Median prediction.
1574            MinSAD=SAD
1575            If Motion Vector equal to Previous frame motion vector
1576                    and MinSAD<PrevFrmSAD goto Step 10.
1577            If SAD<=256 goto Step 10.
1578    */
1579    
1580    // Prepare for main loop
1581    
1582            *currMV=pmv[0];         /* current best := median prediction */
1583            if (!(MotionFlags & PMV_HALFPEL16))
1584            {
1585                    currMV->x = EVEN(currMV->x);
1586                    currMV->y = EVEN(currMV->y);
1587            }
1588    
1589            if (currMV->x > max_dx)
1590                    currMV->x=max_dx;
1591            if (currMV->x < min_dx)
1592                    currMV->x=min_dx;
1593            if (currMV->y > max_dy)
1594                    currMV->y=max_dy;
1595            if (currMV->y < min_dy)
1596                    currMV->y=min_dy;
1597    
1598    /***************** This is predictor SET A: only median prediction ******************/
1599    
1600            iMinSAD = sad16( cur,
1601                    get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
1602                    iEdgedWidth, MV_MAX_ERROR);
1603            iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);
1604    
1605    // thresh1 is fixed to 256
1606            if ( (iMinSAD < 256 ) || ( (MVequal(*currMV, prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
1607                    {
1608                            if (MotionFlags & PMV_QUICKSTOP16)
1609                                    goto EPZS16_Terminate_without_Refine;
1610                            if (MotionFlags & PMV_EARLYSTOP16)
1611                                    goto EPZS16_Terminate_with_Refine;
1612                    }
1613    
1614    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1615    
1616    // previous frame MV
1617            CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1618    
1619    // set threshhold based on Min of Prediction and SAD of collocated block
1620    // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
1621    
1622            if ((x==0) && (y==0) )
1623            {
1624                    thresh2 =  512;
1625            }
1626            else
1627            {
1628    /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */
1629    
1630                    thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
1631            }
1632    
1633    // MV=(0,0) is often a good choice
1634    
1635            CHECK_MV16_ZERO;
1636    
1637    
1638    // left neighbour, if allowed
1639            if (x != 0)
1640            {
1641                    if (!(MotionFlags & PMV_HALFPEL16 ))
1642                    {       pmv[1].x = EVEN(pmv[1].x);
1643                            pmv[1].y = EVEN(pmv[1].y);
1644                    }
1645                    CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1646            }
1647    
1648    // top neighbour, if allowed
1649            if (y != 0)
1650            {
1651                    if (!(MotionFlags & PMV_HALFPEL16 ))
1652                    {       pmv[2].x = EVEN(pmv[2].x);
1653                            pmv[2].y = EVEN(pmv[2].y);
1654                    }
1655                    CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1656    
1657    // top right neighbour, if allowed
1658                    if ((uint32_t)x != (iWcount-1))
1659                    {
1660                            if (!(MotionFlags & PMV_HALFPEL16 ))
1661                            {       pmv[3].x = EVEN(pmv[3].x);
1662                                    pmv[3].y = EVEN(pmv[3].y);
1663                            }
1664                            CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
1665                    }
1666            }
1667    
1668    /* Terminate if MinSAD <= T_2
1669       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1670    */
1671    
1672            if ( (iMinSAD <= thresh2)
1673                    || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )
1674                    {
1675                            if (MotionFlags & PMV_QUICKSTOP16)
1676                                    goto EPZS16_Terminate_without_Refine;
1677                            if (MotionFlags & PMV_EARLYSTOP16)
1678                                    goto EPZS16_Terminate_with_Refine;
1679                    }
1680    
1681    /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
1682    
1683            backupMV = prevMB->mvs[0];              // collocated MV
1684            backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x );    // acceleration X
1685            backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y );    // acceleration Y
1686    
1687            CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);
1688    
1689    // left neighbour
1690            if (x != 0)
1691                    CHECK_MV16_CANDIDATE((prevMB-1)->mvs[0].x,(prevMB-1)->mvs[0].y);
1692    
1693    // top neighbour
1694            if (y != 0)
1695                    CHECK_MV16_CANDIDATE((prevMB-iWcount)->mvs[0].x,(prevMB-iWcount)->mvs[0].y);
1696    
1697    // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
1698    
1699            if ((uint32_t)x != iWcount-1)
1700                    CHECK_MV16_CANDIDATE((prevMB+1)->mvs[0].x,(prevMB+1)->mvs[0].y);
1701    
1702    // bottom neighbour, dito
1703            if ((uint32_t)y != iHcount-1)
1704                    CHECK_MV16_CANDIDATE((prevMB+iWcount)->mvs[0].x,(prevMB+iWcount)->mvs[0].y);
1705    
1706    /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
1707            if (iMinSAD <= thresh2)
1708                    {
1709                            if (MotionFlags & PMV_QUICKSTOP16)
1710                                    goto EPZS16_Terminate_without_Refine;
1711                            if (MotionFlags & PMV_EARLYSTOP16)
1712                                    goto EPZS16_Terminate_with_Refine;
1713                    }
1714    
1715    /************ (if Diamond Search)  **************/
1716    
1717            backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1718    
1719    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1720    
1721            if (MotionFlags & PMV_USESQUARES16)
1722                    EPZSMainSearchPtr = Square16_MainSearch;
1723            else
1724                    EPZSMainSearchPtr = Diamond16_MainSearch;
1725    
1726            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1727                            x, y,
1728                            currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1729                            2, iFcode, iQuant, 0);
1730    
1731            if (iSAD < iMinSAD)
1732            {
1733                    *currMV = newMV;
1734                    iMinSAD = iSAD;
1735            }
1736    
1737    
1738            if (MotionFlags & PMV_EXTSEARCH16)
1739            {
1740    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
1741    
1742                    if (!(MVequal(pmv[0],backupMV)) )
1743                    {
1744                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1745                                    x, y,
1746                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1747                                    pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
1748                    }
1749    
1750                    if (iSAD < iMinSAD)
1751                    {
1752                            *currMV = newMV;
1753                            iMinSAD = iSAD;
1754                    }
1755    
1756                    if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1757                    {
1758                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1759                                    x, y,
1760                            0, 0, iMinSAD, &newMV,
1761                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
1762    
1763                            if (iSAD < iMinSAD)
1764                            {
1765                                    *currMV = newMV;
1766                                    iMinSAD = iSAD;
1767                            }
1768                    }
1769            }
1770    
1771    /***************        Choose best MV found     **************/
1772    
1773    EPZS16_Terminate_with_Refine:
1774            if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1775                    iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1776                                    x, y,
1777                                    currMV, iMinSAD,
1778                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1779    
1780    EPZS16_Terminate_without_Refine:
1781    
1782            *oldMB = *prevMB;
1783    
1784            currPMV->x = currMV->x - pmv[0].x;
1785            currPMV->y = currMV->y - pmv[0].y;
1786            return iMinSAD;
1787    }
1788    
1789    
1790    int32_t EPZSSearch8(
1791                                            const uint8_t * const pRef,
1792                                            const uint8_t * const pRefH,
1793                                            const uint8_t * const pRefV,
1794                                            const uint8_t * const pRefHV,
1795                                            const IMAGE * const pCur,
1796                                            const int x, const int y,
1797                                            const int start_x, const int start_y,
1798                                            const uint32_t MotionFlags,
1799                                            const uint32_t iQuant,
1800                                            const uint32_t iFcode,
1801                                            const MBParam * const pParam,
1802                                            const MACROBLOCK * const pMBs,
1803                                            const MACROBLOCK * const prevMBs,
1804                                            VECTOR * const currMV,
1805                                            VECTOR * const currPMV)
1806    {
1807    /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
1808    
1809            const uint32_t iWcount = pParam->mb_width;
1810            const int32_t iWidth = pParam->width;
1811            const int32_t iHeight = pParam->height;
1812            const int32_t iEdgedWidth = pParam->edged_width;
1813    
1814            const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;
1815    
1816            int32_t iDiamondSize=1;
1817    
1818            int32_t min_dx;
1819            int32_t max_dx;
1820            int32_t min_dy;
1821            int32_t max_dy;
1822    
1823            VECTOR newMV;
1824            VECTOR backupMV;
1825    
1826            VECTOR pmv[4];
1827            int32_t psad[8];
1828    
1829            const   int32_t iSubBlock = ((y&1)<<1) + (x&1);
1830    
1831    //      const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1832            const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1833    
1834            int32_t bPredEq;
1835            int32_t iMinSAD,iSAD=9999;
1836    
1837            MainSearch8FuncPtr EPZSMainSearchPtr;
1838    
1839    /* Get maximum range */
1840            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1841                            x, y, 8, iWidth, iHeight, iFcode);
1842    
1843    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1844    
1845            if (!(MotionFlags & PMV_HALFPEL8 ))
1846            { min_dx = EVEN(min_dx);
1847              max_dx = EVEN(max_dx);
1848              min_dy = EVEN(min_dy);
1849              max_dy = EVEN(max_dy);
1850            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1851    
1852            bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);
1853    
1854    
1855    /* Step 4: Calculate SAD around the Median prediction.
1856            MinSAD=SAD
1857            If Motion Vector equal to Previous frame motion vector
1858                    and MinSAD<PrevFrmSAD goto Step 10.
1859            If SAD<=256 goto Step 10.
1860    */
1861    
1862    // Prepare for main loop
1863    
1864    
1865            if (!(MotionFlags & PMV_HALFPEL8))
1866            {
1867                    currMV->x = EVEN(currMV->x);
1868                    currMV->y = EVEN(currMV->y);
1869            }
1870    
1871            if (currMV->x > max_dx)
1872                    currMV->x=max_dx;
1873            if (currMV->x < min_dx)
1874                    currMV->x=min_dx;
1875            if (currMV->y > max_dy)
1876                    currMV->y=max_dy;
1877            if (currMV->y < min_dy)
1878                    currMV->y=min_dy;
1879    
1880    /***************** This is predictor SET A: only median prediction ******************/
1881    
1882    
1883            iMinSAD = sad8( cur,
1884                    get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
1885                    iEdgedWidth);
1886            iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);
1887    
1888    
1889    // thresh1 is fixed to 256
1890            if (iMinSAD < 256/4 )
1891                    {
1892                            if (MotionFlags & PMV_QUICKSTOP8)
1893                                    goto EPZS8_Terminate_without_Refine;
1894                            if (MotionFlags & PMV_EARLYSTOP8)
1895                                    goto EPZS8_Terminate_with_Refine;
1896                    }
1897    
1898    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1899    
1900    
1901    // MV=(0,0) is often a good choice
1902            CHECK_MV8_ZERO;
1903    
1904    // previous frame MV
1905            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
1906    
1907    // left neighbour, if allowed
1908            if (psad[1] != MV_MAX_ERROR)
1909            {
1910                    if (!(MotionFlags & PMV_HALFPEL8 ))
1911                    {       pmv[1].x = EVEN(pmv[1].x);
1912                            pmv[1].y = EVEN(pmv[1].y);
1913                    }
1914                    CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1915            }
1916    
1917    // top neighbour, if allowed
1918            if (psad[2] != MV_MAX_ERROR)
1919            {
1920                    if (!(MotionFlags & PMV_HALFPEL8 ))
1921                    {       pmv[2].x = EVEN(pmv[2].x);
1922                            pmv[2].y = EVEN(pmv[2].y);
1923                    }
1924                    CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1925    
1926    // top right neighbour, if allowed
1927                    if (psad[3] != MV_MAX_ERROR)
1928                    {
1929                            if (!(MotionFlags & PMV_HALFPEL8 ))
1930                            {       pmv[3].x = EVEN(pmv[3].x);
1931                                    pmv[3].y = EVEN(pmv[3].y);
1932                            }
1933                            CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);
1934                    }
1935            }
1936    
1937    /*  // this bias is zero anyway, at the moment!
1938    
1939            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
1940                    iMinSAD -= MV8_00_BIAS;
1941    
1942    */
1943    
1944    /* Terminate if MinSAD <= T_2
1945       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1946    */
1947    
1948            if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */
1949                    {
1950                            if (MotionFlags & PMV_QUICKSTOP8)
1951                                    goto EPZS8_Terminate_without_Refine;
1952                            if (MotionFlags & PMV_EARLYSTOP8)
1953                                    goto EPZS8_Terminate_with_Refine;
1954                    }
1955    
1956    /************ (Diamond Search)  **************/
1957    
1958            backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1959    
1960            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
1961                    iDiamondSize *= 2;
1962    
1963    /* default: use best prediction as starting point for one call of EPZS_MainSearch */
1964    
1965    /* // there is no EPZS^2 for inter4v at the moment
1966    
1967            if (MotionFlags & PMV_USESQUARES8)
1968                    EPZSMainSearchPtr = Square8_MainSearch;
1969            else
1970    */
1971    
1972            EPZSMainSearchPtr = Diamond8_MainSearch;
1973    
1974            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1975                    x, y,
1976                    currMV->x, currMV->y, iMinSAD, &newMV,
1977                    pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1978                    iDiamondSize, iFcode, iQuant, 0);
1979    
1980    
1981            if (iSAD < iMinSAD)
1982            {
1983                    *currMV = newMV;
1984                    iMinSAD = iSAD;
1985            }
1986    
1987            if (MotionFlags & PMV_EXTSEARCH8)
1988            {
1989    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
1990    
1991                    if (!(MVequal(pmv[0],backupMV)) )
1992                    {
1993                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1994                                    x, y,
1995                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1996                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
1997    
1998                            if (iSAD < iMinSAD)
1999                            {
2000                                    *currMV = newMV;
2001                                    iMinSAD = iSAD;
2002                            }
2003                    }
2004    
2005                    if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
2006                    {
2007                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
2008                                    x, y,
2009                            0, 0, iMinSAD, &newMV,
2010                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
2011    
2012                            if (iSAD < iMinSAD)
2013                            {
2014                                    *currMV = newMV;
2015                                    iMinSAD = iSAD;
2016                            }
2017                    }
2018            }
2019    
2020    /***************        Choose best MV found     **************/
2021    
2022    EPZS8_Terminate_with_Refine:
2023            if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2024                    iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
2025                                    x, y,
2026                                    currMV, iMinSAD,
2027                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
2028    
2029    EPZS8_Terminate_without_Refine:
2030    
2031            currPMV->x = currMV->x - pmv[0].x;
2032            currPMV->y = currMV->y - pmv[0].y;
2033            return iMinSAD;
2034    }
2035    
2036    
2037    
2038    
2039    
2040    /* ***********************************************************
2041            bvop motion estimation
2042    // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)
2043    ***************************************************************/
2044    
2045    
2046    void MotionEstimationBVOP(
2047                            MBParam * const pParam,
2048                            FRAMEINFO * const frame,
2049    
2050                            // forward (past) reference
2051                            const MACROBLOCK * const f_mbs,
2052                        const IMAGE * const f_ref,
2053                            const IMAGE * const f_refH,
2054                        const IMAGE * const f_refV,
2055                            const IMAGE * const f_refHV,
2056                            // backward (future) reference
2057                            const MACROBLOCK * const b_mbs,
2058                        const IMAGE * const b_ref,
2059                            const IMAGE * const b_refH,
2060                        const IMAGE * const b_refV,
2061                            const IMAGE * const b_refHV)
2062    {
2063        const uint32_t mb_width = pParam->mb_width;
2064        const uint32_t mb_height = pParam->mb_height;
2065            const int32_t edged_width = pParam->edged_width;
2066    
2067            uint32_t i,j;
2068    
2069            int32_t f_sad16;
2070            int32_t b_sad16;
2071            int32_t i_sad16;
2072            int32_t d_sad16;
2073            int32_t best_sad;
2074    
2075            VECTOR pmv_dontcare;
2076    
2077            // note: i==horizontal, j==vertical
2078        for (j = 0; j < mb_height; j++)
2079            {
2080                    for (i = 0; i < mb_width; i++)
2081                    {
2082                            MACROBLOCK *mb = &frame->mbs[i + j*mb_width];
2083                            const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];
2084                            const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];
2085    
2086                            if (b_mb->mode == MODE_INTER
2087                                    && b_mb->cbp == 0
2088                                    && b_mb->mvs[0].x == 0
2089                                    && b_mb->mvs[0].y == 0)
2090                            {
2091                                    mb->mode = MODE_NOT_CODED;
2092                                    mb->mvs[0].x = 0;
2093                                    mb->mvs[0].y = 0;
2094                                    mb->b_mvs[0].x = 0;
2095                                    mb->b_mvs[0].y = 0;
2096                                    continue;
2097                            }
2098    
2099    
2100                            // forward search
2101                            f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2102                                                    &frame->image,
2103                                                    i, j,
2104                                                    frame->motion_flags,  frame->quant, frame->fcode,
2105                                                    pParam,
2106                                                    f_mbs, f_mbs /* todo */,
2107                                                    &mb->mvs[0], &pmv_dontcare);    // ignore pmv
2108    
2109                            // backward search
2110                            b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2111                                                    &frame->image,
2112                                                    i, j,
2113                                                    frame->motion_flags,  frame->quant, frame->bcode,
2114                                                    pParam,
2115                                                    b_mbs, b_mbs, /* todo */
2116                                                    &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv
2117    
2118                            // interpolate search (simple, but effective)
2119                            i_sad16 = sad16bi_c(
2120                                            frame->image.y + i*16 + j*16*edged_width,
2121                                            get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2122                                                    i, j, 16, mb->mvs[0].x, mb->mvs[0].y, edged_width),
2123                                            get_ref(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2124                                                    i, j, 16, mb->b_mvs[0].x, mb->b_mvs[0].x, edged_width),
2125                                            edged_width);
2126    
2127                            // TODO: direct search
2128                            // predictor + range of [-32,32]
2129                            d_sad16 = 65535;
2130    
2131    
2132                            if (f_sad16 < b_sad16)
2133                            {
2134                                    best_sad = f_sad16;
2135                                    mb->mode = MODE_FORWARD;
2136                            }
2137                            else
2138                            {
2139                                    best_sad = b_sad16;
2140                                    mb->mode = MODE_BACKWARD;
2141                            }
2142    
2143                            if (i_sad16 < best_sad)
2144                            {
2145                                    best_sad = i_sad16;
2146                                    mb->mode = MODE_INTERPOLATE;
2147                            }
2148    
2149                            if (d_sad16 < best_sad)
2150                            {
2151                                    best_sad = d_sad16;
2152                                    mb->mode = MODE_DIRECT;
2153                            }
2154    
2155                    }
2156            }
2157    }

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

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