[svn] / branches / dev-api-4 / xvidcore / src / motion / motion_est.c Repository:
ViewVC logotype

Diff of /branches/dev-api-4/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 141, Thu Apr 25 23:24:59 2002 UTC
# Line 2  Line 2 
2   *   *
3   *  Modifications:   *  Modifications:
4   *   *
5     *      25.04.2002 partial prevMB conversion
6     *  22.04.2002 remove some compile warning by chenm001 <chenm001@163.com>
7     *  14.04.2002 added MotionEstimationBVOP()
8     *  02.04.2002 add EPZS(^2) as ME algorithm, use PMV_USESQUARES to choose between
9     *             EPZS and EPZS^2
10   *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop   *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop
11   *             PMVFast_Refine to support multiple searches with different start points   *             PMVFast_Refine to support multiple searches with different start points
12   *  07.01.2002 uv-block-based interpolation   *  07.01.2002 uv-block-based interpolation
# Line 31  Line 36 
36    
37  #include <assert.h>  #include <assert.h>
38  #include <stdio.h>  #include <stdio.h>
39    #include <stdlib.h>
40    
41  #include "../encoder.h"  #include "../encoder.h"
42  #include "../utils/mbfunctions.h"  #include "../utils/mbfunctions.h"
43  #include "../prediction/mbprediction.h"  #include "../prediction/mbprediction.h"
44  #include "../global.h"  #include "../global.h"
45  #include "../utils/timer.h"  #include "../utils/timer.h"
46    #include "motion.h"
47  #include "sad.h"  #include "sad.h"
48    
49  // very large value  // very large value
# Line 49  Line 56 
56  /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */  /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */
57  /* nb  = vop pixels * 2^(bpp-8) */  /* nb  = vop pixels * 2^(bpp-8) */
58  #define MV16_00_BIAS    (128+1)  #define MV16_00_BIAS    (128+1)
59    #define MV8_00_BIAS     (0)
60    
61  /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */  /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */
62  #define INTER_BIAS      512  #define INTER_BIAS      512
# Line 65  Line 73 
73  #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)  #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)
74    
75    
76  #define MIN(X, Y) ((X)<(Y)?(X):(Y))  int32_t PMVfastSearch16(
77  #define MAX(X, Y) ((X)>(Y)?(X):(Y))                                          const uint8_t * const pRef,
78  #define ABS(X)    (((X)>0)?(X):-(X))                                          const uint8_t * const pRefH,
79  #define SIGN(X)   (((X)>0)?1:-1)                                          const uint8_t * const pRefV,
80                                            const uint8_t * const pRefHV,
81                                            const IMAGE * const pCur,
82                                            const int x, const int y,
83                                            const uint32_t MotionFlags,
84                                            const uint32_t iQuant,
85                                            const uint32_t iFcode,
86                                            const MBParam * const pParam,
87                                            const MACROBLOCK * const pMBs,
88                                            const MACROBLOCK * const prevMBs,
89                                            VECTOR * const currMV,
90                                            VECTOR * const currPMV);
91    
92    int32_t EPZSSearch16(
93                                            const uint8_t * const pRef,
94                                            const uint8_t * const pRefH,
95                                            const uint8_t * const pRefV,
96                                            const uint8_t * const pRefHV,
97                                            const IMAGE * const pCur,
98                                            const int x, const int y,
99                                            const uint32_t MotionFlags,
100                                            const uint32_t iQuant,
101                                            const uint32_t iFcode,
102                                            const MBParam * const pParam,
103                                            const MACROBLOCK * const pMBs,
104                                            const MACROBLOCK * const prevMBs,
105                                            VECTOR * const currMV,
106                                            VECTOR * const currPMV);
107    
108    
109  int32_t PMVfastSearch8(  int32_t PMVfastSearch8(
# Line 78  Line 113 
113          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
114          const IMAGE * const pCur,          const IMAGE * const pCur,
115          const int x, const int y,          const int x, const int y,
116          const int start_x, int start_y,                                          const int start_x, const int start_y,
117          const uint32_t iQuality,                                          const uint32_t MotionFlags,
118          MBParam * const pParam,                                          const uint32_t iQuant,
119          MACROBLOCK * const pMBs,                                          const uint32_t iFcode,
120                                            const MBParam * const pParam,
121                                            const MACROBLOCK * const pMBs,
122                                            const MACROBLOCK * const prevMBs,
123          VECTOR * const currMV,          VECTOR * const currMV,
124          VECTOR * const currPMV);          VECTOR * const currPMV);
125    
126  int32_t PMVfastSearch16(  int32_t EPZSSearch8(
127          const uint8_t * const pRef,          const uint8_t * const pRef,
128          const uint8_t * const pRefH,          const uint8_t * const pRefH,
129          const uint8_t * const pRefV,          const uint8_t * const pRefV,
130          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
131          const IMAGE * const pCur,          const IMAGE * const pCur,
132          const int x, const int y,          const int x, const int y,
133          const uint32_t iQuality,                                          const int start_x, const int start_y,
134          MBParam * const pParam,                                          const uint32_t MotionFlags,
135          MACROBLOCK * const pMBs,                                          const uint32_t iQuant,
136                                            const uint32_t iFcode,
137                                            const MBParam * const pParam,
138                                            const MACROBLOCK * const pMBs,
139                                            const MACROBLOCK * const prevMBs,
140          VECTOR * const currMV,          VECTOR * const currMV,
141          VECTOR * const currPMV);          VECTOR * const currPMV);
142    
143    
144    typedef int32_t (MainSearch16Func)(
145            const uint8_t * const pRef,
146            const uint8_t * const pRefH,
147            const uint8_t * const pRefV,
148            const uint8_t * const pRefHV,
149            const uint8_t * const cur,
150            const int x, const int y,
151            int32_t startx, int32_t starty,
152            int32_t iMinSAD,
153            VECTOR * const currMV,
154            const VECTOR * const pmv,
155            const int32_t min_dx, const int32_t max_dx,
156            const int32_t min_dy, const int32_t max_dy,
157            const int32_t iEdgedWidth,
158            const int32_t iDiamondSize,
159            const int32_t iFcode,
160            const int32_t iQuant,
161            int iFound);
162    
163  /*  typedef MainSearch16Func* MainSearch16FuncPtr;
  * diamond search stuff  
  * keep the the sequence in circular order (so optimization works)  
  */  
164    
 typedef struct  
 {  
         int32_t dx;  
         int32_t dy;  
 }  
 DPOINT;  
165    
166    typedef int32_t (MainSearch8Func)(
167            const uint8_t * const pRef,
168            const uint8_t * const pRefH,
169            const uint8_t * const pRefV,
170            const uint8_t * const pRefHV,
171            const uint8_t * const cur,
172            const int x, const int y,
173            int32_t startx, int32_t starty,
174            int32_t iMinSAD,
175            VECTOR * const currMV,
176            const VECTOR * const pmv,
177            const int32_t min_dx, const int32_t max_dx,
178            const int32_t min_dy, const int32_t max_dy,
179            const int32_t iEdgedWidth,
180            const int32_t iDiamondSize,
181            const int32_t iFcode,
182            const int32_t iQuant,
183            int iFound);
184    
185  static const DPOINT diamond_small[4] =  typedef MainSearch8Func* MainSearch8FuncPtr;
 {  
         {0, 1}, {1, 0}, {0, -1}, {-1, 0}  
 };  
186    
187    static int32_t lambda_vec16[32] =  /* rounded values for lambda param for weight of motion bits as in modified H.26L */
188            {     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),
189            (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),
190            (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),
191            (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),
192            (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),
193            (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),
194            (int)(36.4949+0.5)      };
195    
196    static int32_t *lambda_vec8 = lambda_vec16;     /* same table for INTER and INTER4V for now*/
197    
 static const DPOINT diamond_large[8] =  
 {  
         {0, 2}, {1, 1}, {2, 0}, {1, -1}, {0, -2}, {-1, -1}, {-2, 0}, {-1, 1}  
 };  
198    
199    
200  // mv.length table  // mv.length table
# Line 160  Line 232 
232  }  }
233    
234    
235  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)  
   
236  {  {
237      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));
238  }  }
239    
240    static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode, const uint32_t iQuant)
241    
   
   
 /* 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)  
242  {  {
243        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;  
         }  
   
244  }  }
245    
246    
 /* This is somehow a copy of get_ref, but with MV instead of X,Y */  
   
 static __inline const uint8_t * get_ref_mv(  
         const uint8_t * const refn,  
         const uint8_t * const refh,  
         const uint8_t * const refv,  
         const uint8_t * const refhv,  
         const uint32_t x, const uint32_t y,  
         const uint32_t block,                   // block dimension, 8 or 16  
         const VECTOR* mv,       // measured in half-pel!  
         const uint32_t stride)  
 {  
247    
         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;  
         }  
248    
 }  
249    
250  #ifndef SEARCH16  #ifndef SEARCH16
251  #define SEARCH16        PMVfastSearch16  #define SEARCH16        PMVfastSearch16
252    //#define SEARCH16      FullSearch16
253    //#define SEARCH16      EPZSSearch16
254  #endif  #endif
255    
256  #ifndef SEARCH8  #ifndef SEARCH8
257  #define SEARCH8         PMVfastSearch8  #define SEARCH8         PMVfastSearch8
258    //#define SEARCH8       EPZSSearch8
259  #endif  #endif
260    
261  bool MotionEstimation(  bool MotionEstimation(
         MACROBLOCK * const pMBs,  
262          MBParam * const pParam,          MBParam * const pParam,
263          const IMAGE * const pRef,          FRAMEINFO * const current,
264            FRAMEINFO * const reference,
265          const IMAGE * const pRefH,          const IMAGE * const pRefH,
266          const IMAGE * const pRefV,          const IMAGE * const pRefV,
267          const IMAGE * const pRefHV,          const IMAGE * const pRefHV,
         IMAGE * const pCurrent,  
268          const uint32_t iLimit)          const uint32_t iLimit)
269    
270  {  {
271          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
272          const uint32_t iHcount = pParam->mb_height;          const uint32_t iHcount = pParam->mb_height;
273            MACROBLOCK * pMBs = current->mbs;
274            IMAGE * pCurrent = &current->image;
275    
276            MACROBLOCK * prevMBs = reference->mbs;  // previous frame
277            IMAGE * pRef = &reference->image;
278    
279    
280          uint32_t i, j, iIntra = 0;          uint32_t i, j, iIntra = 0;
281    
# Line 290  Line 286 
286          int32_t sad16;          int32_t sad16;
287          int32_t deviation;          int32_t deviation;
288    
289            if (sadInit)
290                    (*sadInit)();
291    
292    
293            /* eventhough we have a seperate prevMBs,
294               pmvfast/epsz does something "funny" with the previous frames data */
295    
296    /*      for (i = 0; i < iHcount; i++)
297                    for (j = 0; j < iWcount; j++)
298                    {
299                            pMBs[j + i * iWcount].mvs[0] = prevMBs[j + i * iWcount].mvs[0];
300                            pMBs[j + i * iWcount].mvs[1] = prevMBs[j + i * iWcount].mvs[1];
301                            pMBs[j + i * iWcount].mvs[2] = prevMBs[j + i * iWcount].mvs[2];
302                            pMBs[j + i * iWcount].mvs[3] = prevMBs[j + i * iWcount].mvs[3];
303                    }
304    */
305            /*dprintf("*** BEFORE ***");
306            for (i = 0; i < iHcount; i++)
307                    for (j = 0; j < iWcount; j++)
308                    {
309                            dprintf("   [%i,%i] mode=%i dquant=%i mvs=(%i %i %i %i) sad8=(%i %i %i %i) sad16=(%i)", j,i,
310                                    pMBs[j + i * iWcount].mode,
311                                    pMBs[j + i * iWcount].dquant,
312                                    pMBs[j + i * iWcount].mvs[0],
313                                    pMBs[j + i * iWcount].mvs[1],
314                                    pMBs[j + i * iWcount].mvs[2],
315                                    pMBs[j + i * iWcount].mvs[3],
316                                    prevMBs[j + i * iWcount].sad8[0],
317                                    prevMBs[j + i * iWcount].sad8[1],
318                                    prevMBs[j + i * iWcount].sad8[2],
319                                    prevMBs[j + i * iWcount].sad8[3],
320                                    prevMBs[j + i * iWcount].sad16);
321                    }
322            */
323    
324          // note: i==horizontal, j==vertical          // note: i==horizontal, j==vertical
325          for (i = 0; i < iHcount; i++)          for (i = 0; i < iHcount; i++)
326                  for (j = 0; j < iWcount; j++)                  for (j = 0; j < iWcount; j++)
327                  {                  {
328                          MACROBLOCK *pMB = &pMBs[j + i * iWcount];                          MACROBLOCK *pMB = &pMBs[j + i * iWcount];
329                            MACROBLOCK *prevMB = &prevMBs[j + i * iWcount];
330    
331                          sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                          sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
332                                           j, i, pParam->motion_flags,                                           j, i, current->motion_flags, current->quant, current->fcode,
333                                           pParam, pMBs, &mv16, &pmv16);                                           pParam, pMBs, prevMBs, &mv16, &pmv16);
334                          pMB->sad16=sad16;                          pMB->sad16=sad16;
335    
336    
# Line 314  Line 346 
346                                  pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;                                  pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;
347                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;
348    
349                                    pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = 0;
350    
351                                  iIntra++;                                  iIntra++;
352                                  if(iIntra >= iLimit)                                  if(iIntra >= iLimit)
353                                          return 1;                                          return 1;
# Line 321  Line 355 
355                                  continue;                                  continue;
356                          }                          }
357    
358                          if (pParam->global_flags & XVID_INTER4V)                          if (current->global_flags & XVID_INTER4V)
359                          {                          {
360                                  pMB->sad8[0] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                  pMB->sad8[0] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
361                                                         2 * j, 2 * i, mv16.x, mv16.y, pParam->motion_flags,                                                         2 * j, 2 * i, mv16.x, mv16.y,
362                                                         pParam, pMBs, &pMB->mvs[0], &pMB->pmvs[0]);                                                             current->motion_flags, current->quant, current->fcode,
363                                                           pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]);
364    
365                                  pMB->sad8[1] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                  pMB->sad8[1] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
366                                                         2 * j + 1, 2 * i, mv16.x, mv16.y, pParam->motion_flags,                                                         2 * j + 1, 2 * i, mv16.x, mv16.y,
367                                                         pParam, pMBs, &pMB->mvs[1], &pMB->pmvs[1]);                                                             current->motion_flags, current->quant, current->fcode,
368                                                           pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]);
369    
370                                  pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                  pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
371                                                         2 * j, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,                                                         2 * j, 2 * i + 1, mv16.x, mv16.y,
372                                                         pParam, pMBs, &pMB->mvs[2], &pMB->pmvs[2]);                                                             current->motion_flags, current->quant, current->fcode,
373                                                           pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]);
374    
375                                  pMB->sad8[3] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                  pMB->sad8[3] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
376                                                         2 * j + 1, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,                                                         2 * j + 1, 2 * i + 1, mv16.x, mv16.y,
377                                                         pParam, pMBs, &pMB->mvs[3], &pMB->pmvs[3]);                                                             current->motion_flags, current->quant, current->fcode,
378                                                           pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]);
379    
380                                  sad8 = pMB->sad8[0] + pMB->sad8[1] + pMB->sad8[2] + pMB->sad8[3];                                  sad8 = pMB->sad8[0] + pMB->sad8[1] + pMB->sad8[2] + pMB->sad8[3];
381                          }                          }
# Line 347  Line 385 
385                             mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v                             mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v
386                          */                          */
387    
388                          if (pMB->dquant == NO_CHANGE) {                          if (!(current->global_flags & XVID_LUMIMASKING) || pMB->dquant == NO_CHANGE)
389                                  if (((pParam->global_flags & XVID_INTER4V)==0) ||                          {
390                                      (sad16 < (sad8 + (int32_t)(IMV16X16 * pParam->quant)))) {                                  if (((current->global_flags & XVID_INTER4V)==0) ||
391                                        (sad16 < (sad8 + (int32_t)(IMV16X16 * current->quant))))
392                                    {
393    
394                                          sad8 = sad16;                                          sad8 = sad16;
395                                          pMB->mode = MODE_INTER;                                          pMB->mode = MODE_INTER;
# Line 372  Line 412 
412                          }                          }
413                  }                  }
414    
415    /*      dprintf("*** AFTER ***", pMBs[0].b_mvs[0].x);
416            for (i = 0; i < iHcount; i++)
417                    for (j = 0; j < iWcount; j++)
418                    {
419                            dprintf("   [%i,%i] mode=%i dquant=%i mvs=(%i %i %i %i) sad8=(%i %i %i %i) sad16=(%i)", j,i,
420                                    pMBs[j + i * iWcount].mode,
421                                    pMBs[j + i * iWcount].dquant,
422                                    pMBs[j + i * iWcount].mvs[0],
423                                    pMBs[j + i * iWcount].mvs[1],
424                                    pMBs[j + i * iWcount].mvs[2],
425                                    pMBs[j + i * iWcount].mvs[3],
426                                    pMBs[j + i * iWcount].sad8[0],
427                                    pMBs[j + i * iWcount].sad8[1],
428                                    pMBs[j + i * iWcount].sad8[2],
429                                    pMBs[j + i * iWcount].sad8[3],
430                                    pMBs[j + i * iWcount].sad16);
431                    }
432            */
433    
434          return 0;          return 0;
435  }  }
436    
# Line 385  Line 444 
444      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
445    { \    { \
446      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); \
447      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; \  
448      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
449      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
450  }  }
451    
452    #define NOCHECK_MV16_CANDIDATE(X,Y) { \
453        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
454        iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
455        if (iSAD < iMinSAD) \
456        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
457    }
458    
459  #define CHECK_MV16_CANDIDATE(X,Y) { \  #define CHECK_MV16_CANDIDATE(X,Y) { \
460    if ( ((X) <= max_dx) && ((X) >= min_dx) \    if ( ((X) <= max_dx) && ((X) >= min_dx) \
461      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
462    { \    { \
463      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); \
464      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);\
465      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
466      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
467  }  }
# Line 408  Line 471 
471      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
472    { \    { \
473      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); \
474      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);\
475      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
476      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
477  }  }
# Line 418  Line 481 
481      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
482    { \    { \
483      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); \
484      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);\
485      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
486      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
487  }  }
# Line 426  Line 489 
489    
490  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
491    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); \
492    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);\
493    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
494    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
495  }  }
496    
497    #define NOCHECK_MV8_CANDIDATE(X,Y) \
498      { \
499        iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
500        iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
501        if (iSAD < iMinSAD) \
502        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
503    }
504    
505  #define CHECK_MV8_CANDIDATE(X,Y) { \  #define CHECK_MV8_CANDIDATE(X,Y) { \
506    if ( ((X) <= max_dx) && ((X) >= min_dx) \    if ( ((X) <= max_dx) && ((X) >= min_dx) \
507      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
508    { \    { \
509      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); \
510      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);\
511      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
512      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
513  }  }
# Line 447  Line 517 
517      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
518    { \    { \
519      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); \
520      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);\
521      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
522      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
523  }  }
# Line 457  Line 527 
527      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
528    { \    { \
529      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); \
530      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);\
531      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
532      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
533  }  }
# Line 472  Line 542 
542                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
543                                          const int x, const int y,                                          const int x, const int y,
544                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
545                                            const uint32_t iQuant,
546                                            const uint32_t iFcode,
547                                          MBParam * const pParam,                                          MBParam * const pParam,
548                                          MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
549                                            const MACROBLOCK * const prevMBs,
550                                          VECTOR * const currMV,                                          VECTOR * const currMV,
551                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
552  {  {
553          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
         const int32_t iQuant = pParam->quant;  
554          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
555          int32_t iSAD;          int32_t iSAD;
556          int32_t pred_x,pred_y;          int32_t pred_x,pred_y;
# Line 501  Line 573 
573  }  }
574  */  */
575    
576  int32_t PMVfastSearch16_MainSearch(  int32_t Diamond16_MainSearch(
577          const uint8_t * const pRef,          const uint8_t * const pRef,
578          const uint8_t * const pRefH,          const uint8_t * const pRefH,
579          const uint8_t * const pRefV,          const uint8_t * const pRefV,
# Line 558  Line 630 
630          return iMinSAD;          return iMinSAD;
631  }  }
632    
633  int32_t PMVfastSearch16_Refine(  int32_t Square16_MainSearch(
634          const uint8_t * const pRef,          const uint8_t * const pRef,
635          const uint8_t * const pRefH,          const uint8_t * const pRefH,
636          const uint8_t * const pRefV,          const uint8_t * const pRefV,
637          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
638          const uint8_t * const cur,          const uint8_t * const cur,
639          const int x, const int y,          const int x, const int y,
640          VECTOR * const currMV,                                          int32_t startx, int32_t starty,
641          int32_t iMinSAD,          int32_t iMinSAD,
642                                            VECTOR * const currMV,
643          const VECTOR * const pmv,          const VECTOR * const pmv,
644          const int32_t min_dx, const int32_t max_dx,          const int32_t min_dx, const int32_t max_dx,
645          const int32_t min_dy, const int32_t max_dy,          const int32_t min_dy, const int32_t max_dy,
646                                            const int32_t iEdgedWidth,
647                                            const int32_t iDiamondSize,
648          const int32_t iFcode,          const int32_t iFcode,
649          const int32_t iQuant,          const int32_t iQuant,
650          const int32_t iEdgedWidth)                                          int iFound)
651  {  {
652  /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  /* Do a square search around given starting point, return SAD of best */
653    
654            int32_t iDirection=0;
655          int32_t iSAD;          int32_t iSAD;
656          VECTOR backupMV = *currMV;          VECTOR backupMV;
657            backupMV.x = startx;
658          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)  
659    
660  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;  
661    
662          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;  /*   new direction are extra, so 1-4 is normal diamond
663          537
664          1*2
665          648
666    */
667    
668          int32_t iDiamondSize;          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
669            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
670            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
671            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
672    
673          int32_t min_dx;          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
674          int32_t max_dx;          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
675          int32_t min_dy;          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
676          int32_t max_dy;          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
677    
         int32_t iFound;  
678    
679          VECTOR newMV;          if (iDirection)
680          VECTOR backupMV;        /* just for PMVFAST */                  while (!iFound)
681                    {
682                            iFound = 1;
683                            backupMV=*currMV;
684    
685          VECTOR pmv[4];                          switch (iDirection)
686          int32_t psad[4];                          {
687                                    case 1:
688                                            CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
689                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
690                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
691                                            break;
692                                    case 2:
693                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
694                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
695                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
696                                            break;
697    
698          MACROBLOCK * const pMB = pMBs + x + y * iWcount;                                  case 3:
699                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
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          static int32_t threshA,threshB;                                  case 4:
705          int32_t bPredEq;                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
706          int32_t iMinSAD,iSAD;                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
707                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
708                                            break;
709    
710  /* Get maximum range */                                  case 5:
711          get_range(&min_dx, &max_dx, &min_dy, &max_dy,                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
712                    x, y, 16, iWidth, iHeight, iFcode);                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
713                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
714                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
715                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
716                                            break;
717    
718  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */                                  case 6:
719                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
720                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
721    
722          if (!(MotionFlags & PMV_HALFPEL16 ))                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
723          { min_dx = EVEN(min_dx);                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
724          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; */  
725    
726                                            break;
727    
728          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);                                  case 7:
729                                            CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
730                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
731                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
732                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
733                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
734                                            break;
735    
736          if ((x==0) && (y==0) )                                  case 8:
737          {                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
738                  threshA =  512;                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
739                  threshB = 1024;                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
740                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
741                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
742                                            break;
743                            default:
744                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
745                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
746                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
747                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
748    
749                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
750                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
751                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
752                                            CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
753                                            break;
754                            }
755          }          }
756          else          else
757          {          {
758                  threshA = psad[0];                          currMV->x = startx;
759                  threshB = threshA+256;                          currMV->y = starty;
760                  if (threshA< 512) threshA =  512;                  }
761                  if (threshA>1024) threshA = 1024;          return iMinSAD;
                 if (threshB>1792) threshB = 1792;  
762          }          }
763    
         iFound=0;  
   
 /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  
    vector of the median.  
    If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2  
 */  
   
         if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[0]) ) )  
                 iFound=2;  
   
 /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  
    Otherwise select large Diamond Search.  
 */  
   
         if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536) || (bPredEq) )  
                 iDiamondSize=1; // halfpel!  
         else  
                 iDiamondSize=2; // halfpel!  
   
         if (!(MotionFlags & PMV_HALFPELDIAMOND16) )  
                 iDiamondSize*=2;  
764    
765  /* Step 4: Calculate SAD around the Median prediction.  int32_t Full16_MainSearch(
766     MinSAD=SAD                                          const uint8_t * const pRef,
767     If Motion Vector equal to Previous frame motion vector                                          const uint8_t * const pRefH,
768     and MinSAD<PrevFrmSAD goto Step 10.                                          const uint8_t * const pRefV,
769                                            const uint8_t * const pRefHV,
770                                            const uint8_t * const cur,
771                                            const int x, const int y,
772                                            int32_t startx, int32_t starty,
773                                            int32_t iMinSAD,
774                                            VECTOR * const currMV,
775                                            const VECTOR * const pmv,
776                                            const int32_t min_dx, const int32_t max_dx,
777                                            const int32_t min_dy, const int32_t max_dy,
778                                            const int32_t iEdgedWidth,
779                                            const int32_t iDiamondSize,
780                                            const int32_t iFcode,
781                                            const int32_t iQuant,
782                                            int iFound)
783    {
784            int32_t iSAD;
785            int32_t dx,dy;
786            VECTOR backupMV;
787            backupMV.x = startx;
788            backupMV.y = starty;
789    
790            for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
791                    for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
792                            NOCHECK_MV16_CANDIDATE(dx,dy);
793    
794            return iMinSAD;
795    }
796    
797    int32_t Full8_MainSearch(
798                                            const uint8_t * const pRef,
799                                            const uint8_t * const pRefH,
800                                            const uint8_t * const pRefV,
801                                            const uint8_t * const pRefHV,
802                                            const uint8_t * const cur,
803                                            const int x, const int y,
804                                            int32_t startx, int32_t starty,
805                                            int32_t iMinSAD,
806                                            VECTOR * const currMV,
807                                            const VECTOR * const pmv,
808                                            const int32_t min_dx, const int32_t max_dx,
809                                            const int32_t min_dy, const int32_t max_dy,
810                                            const int32_t iEdgedWidth,
811                                            const int32_t iDiamondSize,
812                                            const int32_t iFcode,
813                                            const int32_t iQuant,
814                                            int iFound)
815    {
816            int32_t iSAD;
817            int32_t dx,dy;
818            VECTOR backupMV;
819            backupMV.x = startx;
820            backupMV.y = starty;
821    
822            for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
823                    for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
824                            NOCHECK_MV8_CANDIDATE(dx,dy);
825    
826            return iMinSAD;
827    }
828    
829    
830    
831    int32_t Halfpel16_Refine(
832            const uint8_t * const pRef,
833            const uint8_t * const pRefH,
834            const uint8_t * const pRefV,
835            const uint8_t * const pRefHV,
836            const uint8_t * const cur,
837            const int x, const int y,
838            VECTOR * const currMV,
839            int32_t iMinSAD,
840            const VECTOR * const pmv,
841            const int32_t min_dx, const int32_t max_dx,
842            const int32_t min_dy, const int32_t max_dy,
843            const int32_t iFcode,
844            const int32_t iQuant,
845            const int32_t iEdgedWidth)
846    {
847    /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
848    
849            int32_t iSAD;
850            VECTOR backupMV = *currMV;
851    
852            CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y-1);
853            CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y-1);
854            CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y-1);
855            CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y);
856            CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y);
857            CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y+1);
858            CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y+1);
859            CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y+1);
860    
861            return iMinSAD;
862    }
863    
864    #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
865    
866    
867    int32_t PMVfastSearch16(
868                                            const uint8_t * const pRef,
869                                            const uint8_t * const pRefH,
870                                            const uint8_t * const pRefV,
871                                            const uint8_t * const pRefHV,
872                                            const IMAGE * const pCur,
873                                            const int x, const int y,
874                                            const uint32_t MotionFlags,
875                                            const uint32_t iQuant,
876                                            const uint32_t iFcode,
877                                            const MBParam * const pParam,
878                                            const MACROBLOCK * const pMBs,
879                                            const MACROBLOCK * const prevMBs,
880                                            VECTOR * const currMV,
881                                            VECTOR * const currPMV)
882    {
883        const uint32_t iWcount = pParam->mb_width;
884            const int32_t iWidth = pParam->width;
885            const int32_t iHeight = pParam->height;
886            const int32_t iEdgedWidth = pParam->edged_width;
887    
888            const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
889    
890            int32_t iDiamondSize;
891    
892            int32_t min_dx;
893            int32_t max_dx;
894            int32_t min_dy;
895            int32_t max_dy;
896    
897            int32_t iFound;
898    
899            VECTOR newMV;
900            VECTOR backupMV;        /* just for PMVFAST */
901    
902            VECTOR pmv[4];
903            int32_t psad[4];
904    
905            const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
906            const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
907    
908            static int32_t threshA,threshB;
909            int32_t bPredEq;
910            int32_t iMinSAD,iSAD;
911    
912    /* Get maximum range */
913            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
914                      x, y, 16, iWidth, iHeight, iFcode);
915    
916    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
917    
918            if (!(MotionFlags & PMV_HALFPEL16 ))
919            { min_dx = EVEN(min_dx);
920            max_dx = EVEN(max_dx);
921            min_dy = EVEN(min_dy);
922            max_dy = EVEN(max_dy);
923            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
924    
925    
926            bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
927    
928            if ((x==0) && (y==0) )
929            {
930                    threshA =  512;
931                    threshB = 1024;
932    
933            }
934            else
935            {
936                    threshA = psad[0];
937                    threshB = threshA+256;
938                    if (threshA< 512) threshA =  512;
939                    if (threshA>1024) threshA = 1024;
940                    if (threshB>1792) threshB = 1792;
941            }
942    
943            iFound=0;
944    
945    /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
946       vector of the median.
947       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
948    */
949    
950            if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[0]) ) )
951                    iFound=2;
952    
953    /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
954       Otherwise select large Diamond Search.
955    */
956    
957            if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536) || (bPredEq) )
958                    iDiamondSize=1; // halfpel!
959            else
960                    iDiamondSize=2; // halfpel!
961    
962            if (!(MotionFlags & PMV_HALFPELDIAMOND16) )
963                    iDiamondSize*=2;
964    
965    /* Step 4: Calculate SAD around the Median prediction.
966       MinSAD=SAD
967       If Motion Vector equal to Previous frame motion vector
968       and MinSAD<PrevFrmSAD goto Step 10.
969     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
970  */  */
971    
# Line 726  Line 999 
999          iMinSAD = sad16( cur,          iMinSAD = sad16( cur,
1000                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
1001                           iEdgedWidth, MV_MAX_ERROR);                           iEdgedWidth, MV_MAX_ERROR);
1002          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);
1003    
1004          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
1005          {          {
1006    
1007                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1008                          goto step10b;                          goto PMVfast16_Terminate_without_Refine;
1009                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
1010                          goto step10;                          goto PMVfast16_Terminate_with_Refine;
1011          }          }
1012    
1013  /*  /*
1014     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.
1015     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1016     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1017     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1018  */  */
1019    
1020  // (0,0) is always possible  // (0,0) is always possible
# Line 749  Line 1022 
1022          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1023    
1024  // previous frame MV is always possible  // previous frame MV is always possible
1025          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1026    
1027  // left neighbour, if allowed  // left neighbour, if allowed
1028          if (x != 0)          if (x != 0)
# Line 771  Line 1044 
1044                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1045    
1046  // top right neighbour, if allowed  // top right neighbour, if allowed
1047                  if (x != (iWcount-1))                  if ((uint32_t)x != (iWcount-1))
1048                  {                  {
1049                          if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!(MotionFlags & PMV_HALFPEL16 ))
1050                          {       pmv[3].x = EVEN(pmv[3].x);                          {       pmv[3].x = EVEN(pmv[3].x);
# Line 781  Line 1054 
1054                  }                  }
1055          }          }
1056    
1057            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96)*/ )
1058                    iMinSAD -= MV16_00_BIAS;
1059    
1060    
1061  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1062     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.
1063  */  */
1064    
1065          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
1066          {          {
1067                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1068                          goto step10b;                          goto PMVfast16_Terminate_without_Refine;
1069                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
1070                          goto step10;                          goto PMVfast16_Terminate_with_Refine;
1071          }          }
1072    
1073    
# Line 807  Line 1084 
1084          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1085    
1086  /* 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 */
1087          iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1088                                            x, y,                                            x, y,
1089                                            currMV->x, currMV->y, iMinSAD, &newMV,                                            currMV->x, currMV->y, 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 823  Line 1100 
1100  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1101    
1102                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0],backupMV)) )
1103                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1104                                                            x, y,                                                            x, y,
1105                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1106                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 836  Line 1113 
1113                  }                  }
1114    
1115                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1116                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1117                                                            x, y,                                                            x, y,
1118                                                            0, 0, iMinSAD, &newMV,                                                            0, 0, iMinSAD, &newMV,
1119                                                            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 1130 
1130     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.
1131  */  */
1132    
1133   step10:  PMVfast16_Terminate_with_Refine:
1134          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1135                  iMinSAD = PMVfastSearch16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1136                                                    x, y,                                                    x, y,
1137                                                    currMV, iMinSAD,                                                    currMV, iMinSAD,
1138                                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1139    
1140   step10b:  PMVfast16_Terminate_without_Refine:
1141          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1142          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
1143          return iMinSAD;          return iMinSAD;
# Line 871  Line 1148 
1148    
1149    
1150    
1151  int32_t PMVfastSearch8_MainSearch(  int32_t Diamond8_MainSearch(
1152          const uint8_t * const pRef,          const uint8_t * const pRef,
1153          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1154          const uint8_t * const pRefV,          const uint8_t * const pRefV,
# Line 928  Line 1205 
1205          return iMinSAD;          return iMinSAD;
1206  }  }
1207    
1208  int32_t PMVfastSearch8_Refine(  int32_t Halfpel8_Refine(
1209          const uint8_t * const pRef,          const uint8_t * const pRef,
1210          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1211          const uint8_t * const pRefV,          const uint8_t * const pRefV,
# Line 971  Line 1248 
1248          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1249          const IMAGE * const pCur,          const IMAGE * const pCur,
1250          const int x, const int y,          const int x, const int y,
1251          const int start_x, int start_y,                                          const int start_x, const int start_y,
1252          const uint32_t MotionFlags,          const uint32_t MotionFlags,
1253          MBParam * const pParam,                                          const uint32_t iQuant,
1254          MACROBLOCK * const pMBs,                                          const uint32_t iFcode,
1255                                            const MBParam * const pParam,
1256                                            const MACROBLOCK * const pMBs,
1257                                            const MACROBLOCK * const prevMBs,
1258          VECTOR * const currMV,          VECTOR * const currMV,
1259          VECTOR * const currPMV)          VECTOR * const currPMV)
1260  {  {
1261          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;  
1262          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1263          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
1264          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 1000  Line 1277 
1277          VECTOR newMV;          VECTOR newMV;
1278          VECTOR backupMV;          VECTOR backupMV;
1279    
1280          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1281            const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1282    
1283          static int32_t threshA,threshB;          static int32_t threshA,threshB;
1284          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
# Line 1012  Line 1290 
1290          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1291                    x, y, 8, iWidth, iHeight, iFcode);                    x, y, 8, iWidth, iHeight, iFcode);
1292    
 /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */  
   
1293          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))
1294          { min_dx = EVEN(min_dx);          { min_dx = EVEN(min_dx);
1295          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
# Line 1046  Line 1322 
1322     If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2     If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1323  */  */
1324    
1325          if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[iSubBlock]) ) )          if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[iSubBlock]) ) )
1326                  iFound=2;                  iFound=2;
1327    
1328  /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
# Line 1077  Line 1353 
1353          iMinSAD = sad8( cur,          iMinSAD = sad8( cur,
1354                          get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                          get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
1355                          iEdgedWidth);                          iEdgedWidth);
1356          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);
1357    
1358          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock])) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )
1359          {          {
1360                  if (MotionFlags & PMV_QUICKSTOP8)                  if (MotionFlags & PMV_QUICKSTOP16)
1361                          goto step10_8b;                          goto PMVfast8_Terminate_without_Refine;
1362                  if (MotionFlags & PMV_EARLYSTOP8)                  if (MotionFlags & PMV_EARLYSTOP16)
1363                          goto step10_8;                          goto PMVfast8_Terminate_with_Refine;
1364          }          }
1365    
1366    
1367  /*  /*
1368     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.
1369     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1370     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1371     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1372  */  */
1373    
1374  // the prediction might be even better than mv16  // the prediction might be even better than mv16
# Line 1101  Line 1378 
1378          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
1379    
1380  // previous frame MV is always possible  // previous frame MV is always possible
1381          CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
1382    
1383  // left neighbour, if allowed  // left neighbour, if allowed
1384          if (psad[1] != MV_MAX_ERROR)          if (psad[1] != MV_MAX_ERROR)
# Line 1133  Line 1410 
1410                  }                  }
1411          }          }
1412    
1413            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1414                    iMinSAD -= MV8_00_BIAS;
1415    
1416    
1417  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1418     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.
1419  */  */
1420    
1421          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]) ) )
1422          {          {
1423                  if (MotionFlags & PMV_QUICKSTOP8)                  if (MotionFlags & PMV_QUICKSTOP16)
1424                          goto step10_8b;                          goto PMVfast8_Terminate_without_Refine;
1425                  if (MotionFlags & PMV_EARLYSTOP8)                  if (MotionFlags & PMV_EARLYSTOP16)
1426                          goto step10_8;                          goto PMVfast8_Terminate_with_Refine;
1427          }          }
1428    
1429  /************ (Diamond Search)  **************/  /************ (Diamond Search)  **************/
# Line 1158  Line 1439 
1439          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1440    
1441  /* 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 */
1442          iSAD = PMVfastSearch8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1443                                           x, y,                                           x, y,
1444                                           currMV->x, currMV->y, iMinSAD, &newMV,                                           currMV->x, currMV->y, iMinSAD, &newMV,
1445                                           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 1455 
1455  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1456    
1457                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0],backupMV)) )
1458                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1459                                                            x, y,                                                            x, y,
1460                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1461                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
# Line 1187  Line 1468 
1468                  }                  }
1469    
1470                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1471                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
1472                                                            x, y,                                                            x, y,
1473                                                            0, 0, iMinSAD, &newMV,                                                            0, 0, iMinSAD, &newMV,
1474                                                            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 1485 
1485     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.
1486  */  */
1487    
1488   step10_8:  PMVfast8_Terminate_with_Refine:
1489          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
1490                  iMinSAD = PMVfastSearch8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1491                                                   x, y,                                                   x, y,
1492                                                   currMV, iMinSAD,                                                   currMV, iMinSAD,
1493                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1494    
  step10_8b:  
1495    
1496    PMVfast8_Terminate_without_Refine:
1497          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1498          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
1499    
1500          return iMinSAD;          return iMinSAD;
1501  }  }
1502    
1503    int32_t EPZSSearch16(
1504                                            const uint8_t * const pRef,
1505                                            const uint8_t * const pRefH,
1506                                            const uint8_t * const pRefV,
1507                                            const uint8_t * const pRefHV,
1508                                            const IMAGE * const pCur,
1509                                            const int x, const int y,
1510                                            const uint32_t MotionFlags,
1511                                            const uint32_t iQuant,
1512                                            const uint32_t iFcode,
1513                                            const MBParam * const pParam,
1514                                            const MACROBLOCK * const pMBs,
1515                                            const MACROBLOCK * const prevMBs,
1516                                            VECTOR * const currMV,
1517                                            VECTOR * const currPMV)
1518    {
1519        const uint32_t iWcount = pParam->mb_width;
1520        const uint32_t iHcount = pParam->mb_height;
1521    
1522            const int32_t iWidth = pParam->width;
1523            const int32_t iHeight = pParam->height;
1524            const int32_t iEdgedWidth = pParam->edged_width;
1525    
1526            const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
1527    
1528            int32_t min_dx;
1529            int32_t max_dx;
1530            int32_t min_dy;
1531            int32_t max_dy;
1532    
1533            VECTOR newMV;
1534            VECTOR backupMV;
1535    
1536            VECTOR pmv[4];
1537            int32_t psad[8];
1538    
1539            static MACROBLOCK * oldMBs = NULL;
1540            const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
1541            const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1542            MACROBLOCK * oldMB = NULL;
1543    
1544            static int32_t thresh2;
1545            int32_t bPredEq;
1546            int32_t iMinSAD,iSAD=9999;
1547    
1548            MainSearch16FuncPtr EPZSMainSearchPtr;
1549    
1550            if (oldMBs == NULL)
1551            {       oldMBs = (MACROBLOCK*) calloc(iWcount*iHcount,sizeof(MACROBLOCK));
1552    //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
1553            }
1554            oldMB = oldMBs + x + y * iWcount;
1555    
1556    /* Get maximum range */
1557            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1558                            x, y, 16, iWidth, iHeight, iFcode);
1559    
1560            if (!(MotionFlags & PMV_HALFPEL16 ))
1561            { min_dx = EVEN(min_dx);
1562              max_dx = EVEN(max_dx);
1563              min_dy = EVEN(min_dy);
1564              max_dy = EVEN(max_dy);
1565            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1566    
1567            bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1568    
1569    /* Step 4: Calculate SAD around the Median prediction.
1570            MinSAD=SAD
1571            If Motion Vector equal to Previous frame motion vector
1572                    and MinSAD<PrevFrmSAD goto Step 10.
1573            If SAD<=256 goto Step 10.
1574    */
1575    
1576    // Prepare for main loop
1577    
1578            *currMV=pmv[0];         /* current best := median prediction */
1579            if (!(MotionFlags & PMV_HALFPEL16))
1580            {
1581                    currMV->x = EVEN(currMV->x);
1582                    currMV->y = EVEN(currMV->y);
1583            }
1584    
1585            if (currMV->x > max_dx)
1586                    currMV->x=max_dx;
1587            if (currMV->x < min_dx)
1588                    currMV->x=min_dx;
1589            if (currMV->y > max_dy)
1590                    currMV->y=max_dy;
1591            if (currMV->y < min_dy)
1592                    currMV->y=min_dy;
1593    
1594    /***************** This is predictor SET A: only median prediction ******************/
1595    
1596            iMinSAD = sad16( cur,
1597                    get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
1598                    iEdgedWidth, MV_MAX_ERROR);
1599            iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);
1600    
1601    // thresh1 is fixed to 256
1602            if ( (iMinSAD < 256 ) || ( (MVequal(*currMV, prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )
1603                    {
1604                            if (MotionFlags & PMV_QUICKSTOP16)
1605                                    goto EPZS16_Terminate_without_Refine;
1606                            if (MotionFlags & PMV_EARLYSTOP16)
1607                                    goto EPZS16_Terminate_with_Refine;
1608                    }
1609    
1610    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1611    
1612    // previous frame MV
1613            CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1614    
1615    // set threshhold based on Min of Prediction and SAD of collocated block
1616    // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
1617    
1618            if ((x==0) && (y==0) )
1619            {
1620                    thresh2 =  512;
1621            }
1622            else
1623            {
1624    /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */
1625    
1626                    thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
1627            }
1628    
1629    // MV=(0,0) is often a good choice
1630    
1631            CHECK_MV16_ZERO;
1632    
1633    
1634    // left neighbour, if allowed
1635            if (x != 0)
1636            {
1637                    if (!(MotionFlags & PMV_HALFPEL16 ))
1638                    {       pmv[1].x = EVEN(pmv[1].x);
1639                            pmv[1].y = EVEN(pmv[1].y);
1640                    }
1641                    CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1642            }
1643    
1644    // top neighbour, if allowed
1645            if (y != 0)
1646            {
1647                    if (!(MotionFlags & PMV_HALFPEL16 ))
1648                    {       pmv[2].x = EVEN(pmv[2].x);
1649                            pmv[2].y = EVEN(pmv[2].y);
1650                    }
1651                    CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1652    
1653    // top right neighbour, if allowed
1654                    if ((uint32_t)x != (iWcount-1))
1655                    {
1656                            if (!(MotionFlags & PMV_HALFPEL16 ))
1657                            {       pmv[3].x = EVEN(pmv[3].x);
1658                                    pmv[3].y = EVEN(pmv[3].y);
1659                            }
1660                            CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
1661                    }
1662            }
1663    
1664    /* Terminate if MinSAD <= T_2
1665       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1666    */
1667    
1668            if ( (iMinSAD <= thresh2)
1669                    || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )
1670                    {
1671                            if (MotionFlags & PMV_QUICKSTOP16)
1672                                    goto EPZS16_Terminate_without_Refine;
1673                            if (MotionFlags & PMV_EARLYSTOP16)
1674                                    goto EPZS16_Terminate_with_Refine;
1675                    }
1676    
1677    /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
1678    
1679            backupMV = prevMB->mvs[0];              // collocated MV
1680            backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x );    // acceleration X
1681            backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y );    // acceleration Y
1682    
1683            CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);
1684    
1685    // left neighbour
1686            if (x != 0)
1687                    CHECK_MV16_CANDIDATE((prevMB-1)->mvs[0].x,(prevMB-1)->mvs[0].y);
1688    
1689    // top neighbour
1690            if (y != 0)
1691                    CHECK_MV16_CANDIDATE((prevMB-iWcount)->mvs[0].x,(prevMB-iWcount)->mvs[0].y);
1692    
1693    // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
1694    
1695            if ((uint32_t)x != iWcount-1)
1696                    CHECK_MV16_CANDIDATE((prevMB+1)->mvs[0].x,(prevMB+1)->mvs[0].y);
1697    
1698    // bottom neighbour, dito
1699            if ((uint32_t)y != iHcount-1)
1700                    CHECK_MV16_CANDIDATE((prevMB+iWcount)->mvs[0].x,(prevMB+iWcount)->mvs[0].y);
1701    
1702    /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
1703            if (iMinSAD <= thresh2)
1704                    {
1705                            if (MotionFlags & PMV_QUICKSTOP16)
1706                                    goto EPZS16_Terminate_without_Refine;
1707                            if (MotionFlags & PMV_EARLYSTOP16)
1708                                    goto EPZS16_Terminate_with_Refine;
1709                    }
1710    
1711    /************ (if Diamond Search)  **************/
1712    
1713            backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1714    
1715    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1716    
1717            if (MotionFlags & PMV_USESQUARES16)
1718                    EPZSMainSearchPtr = Square16_MainSearch;
1719            else
1720                    EPZSMainSearchPtr = Diamond16_MainSearch;
1721    
1722            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1723                            x, y,
1724                            currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1725                            2, iFcode, iQuant, 0);
1726    
1727            if (iSAD < iMinSAD)
1728            {
1729                    *currMV = newMV;
1730                    iMinSAD = iSAD;
1731            }
1732    
1733    
1734            if (MotionFlags & PMV_EXTSEARCH16)
1735            {
1736    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
1737    
1738                    if (!(MVequal(pmv[0],backupMV)) )
1739                    {
1740                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1741                                    x, y,
1742                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1743                                    pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
1744                    }
1745    
1746                    if (iSAD < iMinSAD)
1747                    {
1748                            *currMV = newMV;
1749                            iMinSAD = iSAD;
1750                    }
1751    
1752                    if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
1753                    {
1754                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1755                                    x, y,
1756                            0, 0, iMinSAD, &newMV,
1757                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
1758    
1759                            if (iSAD < iMinSAD)
1760                            {
1761                                    *currMV = newMV;
1762                                    iMinSAD = iSAD;
1763                            }
1764                    }
1765            }
1766    
1767    /***************        Choose best MV found     **************/
1768    
1769    EPZS16_Terminate_with_Refine:
1770            if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1771                    iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
1772                                    x, y,
1773                                    currMV, iMinSAD,
1774                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
1775    
1776    EPZS16_Terminate_without_Refine:
1777    
1778            *oldMB = *prevMB;
1779    
1780            currPMV->x = currMV->x - pmv[0].x;
1781            currPMV->y = currMV->y - pmv[0].y;
1782            return iMinSAD;
1783    }
1784    
1785    
1786    int32_t EPZSSearch8(
1787                                            const uint8_t * const pRef,
1788                                            const uint8_t * const pRefH,
1789                                            const uint8_t * const pRefV,
1790                                            const uint8_t * const pRefHV,
1791                                            const IMAGE * const pCur,
1792                                            const int x, const int y,
1793                                            const int start_x, const int start_y,
1794                                            const uint32_t MotionFlags,
1795                                            const uint32_t iQuant,
1796                                            const uint32_t iFcode,
1797                                            const MBParam * const pParam,
1798                                            const MACROBLOCK * const pMBs,
1799                                            const MACROBLOCK * const prevMBs,
1800                                            VECTOR * const currMV,
1801                                            VECTOR * const currPMV)
1802    {
1803    /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
1804    
1805            const uint32_t iWcount = pParam->mb_width;
1806            const int32_t iWidth = pParam->width;
1807            const int32_t iHeight = pParam->height;
1808            const int32_t iEdgedWidth = pParam->edged_width;
1809    
1810            const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;
1811    
1812            int32_t iDiamondSize=1;
1813    
1814            int32_t min_dx;
1815            int32_t max_dx;
1816            int32_t min_dy;
1817            int32_t max_dy;
1818    
1819            VECTOR newMV;
1820            VECTOR backupMV;
1821    
1822            VECTOR pmv[4];
1823            int32_t psad[8];
1824    
1825            const   int32_t iSubBlock = ((y&1)<<1) + (x&1);
1826    
1827            const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1828            const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1829    
1830            int32_t bPredEq;
1831            int32_t iMinSAD,iSAD=9999;
1832    
1833            MainSearch8FuncPtr EPZSMainSearchPtr;
1834    
1835    /* Get maximum range */
1836            get_range(&min_dx, &max_dx, &min_dy, &max_dy,
1837                            x, y, 8, iWidth, iHeight, iFcode);
1838    
1839    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1840    
1841            if (!(MotionFlags & PMV_HALFPEL8 ))
1842            { min_dx = EVEN(min_dx);
1843              max_dx = EVEN(max_dx);
1844              min_dy = EVEN(min_dy);
1845              max_dy = EVEN(max_dy);
1846            }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1847    
1848            bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);
1849    
1850    
1851    /* Step 4: Calculate SAD around the Median prediction.
1852            MinSAD=SAD
1853            If Motion Vector equal to Previous frame motion vector
1854                    and MinSAD<PrevFrmSAD goto Step 10.
1855            If SAD<=256 goto Step 10.
1856    */
1857    
1858    // Prepare for main loop
1859    
1860    
1861            if (!(MotionFlags & PMV_HALFPEL8))
1862            {
1863                    currMV->x = EVEN(currMV->x);
1864                    currMV->y = EVEN(currMV->y);
1865            }
1866    
1867            if (currMV->x > max_dx)
1868                    currMV->x=max_dx;
1869            if (currMV->x < min_dx)
1870                    currMV->x=min_dx;
1871            if (currMV->y > max_dy)
1872                    currMV->y=max_dy;
1873            if (currMV->y < min_dy)
1874                    currMV->y=min_dy;
1875    
1876    /***************** This is predictor SET A: only median prediction ******************/
1877    
1878    
1879            iMinSAD = sad8( cur,
1880                    get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
1881                    iEdgedWidth);
1882            iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);
1883    
1884    
1885    // thresh1 is fixed to 256
1886            if (iMinSAD < 256/4 )
1887                    {
1888                            if (MotionFlags & PMV_QUICKSTOP8)
1889                                    goto EPZS8_Terminate_without_Refine;
1890                            if (MotionFlags & PMV_EARLYSTOP8)
1891                                    goto EPZS8_Terminate_with_Refine;
1892                    }
1893    
1894    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1895    
1896    
1897    // MV=(0,0) is often a good choice
1898            CHECK_MV8_ZERO;
1899    
1900    // previous frame MV
1901            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
1902    
1903    // left neighbour, if allowed
1904            if (psad[1] != MV_MAX_ERROR)
1905            {
1906                    if (!(MotionFlags & PMV_HALFPEL8 ))
1907                    {       pmv[1].x = EVEN(pmv[1].x);
1908                            pmv[1].y = EVEN(pmv[1].y);
1909                    }
1910                    CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1911            }
1912    
1913    // top neighbour, if allowed
1914            if (psad[2] != MV_MAX_ERROR)
1915            {
1916                    if (!(MotionFlags & PMV_HALFPEL8 ))
1917                    {       pmv[2].x = EVEN(pmv[2].x);
1918                            pmv[2].y = EVEN(pmv[2].y);
1919                    }
1920                    CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1921    
1922    // top right neighbour, if allowed
1923                    if (psad[3] != MV_MAX_ERROR)
1924                    {
1925                            if (!(MotionFlags & PMV_HALFPEL8 ))
1926                            {       pmv[3].x = EVEN(pmv[3].x);
1927                                    pmv[3].y = EVEN(pmv[3].y);
1928                            }
1929                            CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);
1930                    }
1931            }
1932    
1933    /*  // this bias is zero anyway, at the moment!
1934    
1935            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
1936                    iMinSAD -= MV8_00_BIAS;
1937    
1938    */
1939    
1940    /* Terminate if MinSAD <= T_2
1941       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1942    */
1943    
1944            if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */
1945                    {
1946                            if (MotionFlags & PMV_QUICKSTOP8)
1947                                    goto EPZS8_Terminate_without_Refine;
1948                            if (MotionFlags & PMV_EARLYSTOP8)
1949                                    goto EPZS8_Terminate_with_Refine;
1950                    }
1951    
1952    /************ (Diamond Search)  **************/
1953    
1954            backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1955    
1956            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
1957                    iDiamondSize *= 2;
1958    
1959    /* default: use best prediction as starting point for one call of EPZS_MainSearch */
1960    
1961    /* // there is no EPZS^2 for inter4v at the moment
1962    
1963            if (MotionFlags & PMV_USESQUARES8)
1964                    EPZSMainSearchPtr = Square8_MainSearch;
1965            else
1966    */
1967    
1968            EPZSMainSearchPtr = Diamond8_MainSearch;
1969    
1970            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1971                    x, y,
1972                    currMV->x, currMV->y, iMinSAD, &newMV,
1973                    pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1974                    iDiamondSize, iFcode, iQuant, 0);
1975    
1976    
1977            if (iSAD < iMinSAD)
1978            {
1979                    *currMV = newMV;
1980                    iMinSAD = iSAD;
1981            }
1982    
1983            if (MotionFlags & PMV_EXTSEARCH8)
1984            {
1985    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
1986    
1987                    if (!(MVequal(pmv[0],backupMV)) )
1988                    {
1989                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
1990                                    x, y,
1991                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,
1992                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
1993    
1994                            if (iSAD < iMinSAD)
1995                            {
1996                                    *currMV = newMV;
1997                                    iMinSAD = iSAD;
1998                            }
1999                    }
2000    
2001                    if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
2002                    {
2003                            iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
2004                                    x, y,
2005                            0, 0, iMinSAD, &newMV,
2006                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
2007    
2008                            if (iSAD < iMinSAD)
2009                            {
2010                                    *currMV = newMV;
2011                                    iMinSAD = iSAD;
2012                            }
2013                    }
2014            }
2015    
2016    /***************        Choose best MV found     **************/
2017    
2018    EPZS8_Terminate_with_Refine:
2019            if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2020                    iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
2021                                    x, y,
2022                                    currMV, iMinSAD,
2023                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
2024    
2025    EPZS8_Terminate_without_Refine:
2026    
2027            currPMV->x = currMV->x - pmv[0].x;
2028            currPMV->y = currMV->y - pmv[0].y;
2029            return iMinSAD;
2030    }
2031    
2032    
2033    
2034    
2035    
2036    /* ***********************************************************
2037            bvop motion estimation
2038    // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)
2039    ***************************************************************/
2040    
2041    /*
2042    void MotionEstimationBVOP(
2043                            MBParam * const pParam,
2044                            FRAMEINFO * const frame,
2045    
2046                            // forward (past) reference
2047                            const MACROBLOCK * const f_mbs,
2048                        const IMAGE * const f_ref,
2049                            const IMAGE * const f_refH,
2050                        const IMAGE * const f_refV,
2051                            const IMAGE * const f_refHV,
2052                            // backward (future) reference
2053                            const MACROBLOCK * const b_mbs,
2054                        const IMAGE * const b_ref,
2055                            const IMAGE * const b_refH,
2056                        const IMAGE * const b_refV,
2057                            const IMAGE * const b_refHV)
2058    {
2059        const uint32_t mb_width = pParam->mb_width;
2060        const uint32_t mb_height = pParam->mb_height;
2061            const int32_t edged_width = pParam->edged_width;
2062    
2063            int32_t i,j;
2064    
2065            int32_t f_sad16;
2066            int32_t b_sad16;
2067            int32_t i_sad16;
2068            int32_t d_sad16;
2069            int32_t best_sad;
2070    
2071            VECTOR pmv_dontcare;
2072    
2073            // note: i==horizontal, j==vertical
2074        for (j = 0; j < mb_height; j++)
2075            {
2076                    for (i = 0; i < mb_width; i++)
2077                    {
2078                            MACROBLOCK *mb = &frame->mbs[i + j*mb_width];
2079                            const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];
2080                            const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];
2081    
2082                            if (b_mb->mode == MODE_INTER
2083                                    && b_mb->cbp == 0
2084                                    && b_mb->mvs[0].x == 0
2085                                    && b_mb->mvs[0].y == 0)
2086                            {
2087                                    mb->mode = MB_IGNORE;
2088                                    mb->mvs[0].x = 0;
2089                                    mb->mvs[0].y = 0;
2090                                    mb->b_mvs[0].x = 0;
2091                                    mb->b_mvs[0].y = 0;
2092                                    continue;
2093                            }
2094    
2095    
2096                            // forward search
2097                            f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2098                                                    &frame->image,
2099                                                    i, j,
2100                                                    frame->motion_flags,  frame->quant, frame->fcode,
2101                                                    pParam,
2102                                                    f_mbs,
2103                                                    &mb->mvs[0], &pmv_dontcare);    // ignore pmv
2104    
2105                            // backward search
2106                            b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2107                                                    &frame->image,
2108                                                    i, j,
2109                                                    frame->motion_flags,  frame->quant, frame->bcode,
2110                                                    pParam,
2111                                                    b_mbs,
2112                                                    &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv
2113    
2114                            // interpolate search (simple, but effective)
2115                            i_sad16 = sad16bi_c(
2116                                            frame->image.y + i*16 + j*16*edged_width,
2117                                            get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2118                                                    i, j, 16, mb->mvs[0].x, mb->mvs[0].y, edged_width),
2119                                            get_ref(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2120                                                    i, j, 16, mb->b_mvs[0].x, mb->b_mvs[0].x, edged_width),
2121                                            edged_width);
2122    
2123                            // TODO: direct search
2124                            // predictor + range of [-32,32]
2125                            d_sad16 = 65535;
2126    
2127    
2128                            if (f_sad16 < b_sad16)
2129                            {
2130                                    best_sad = f_sad16;
2131                                    mb->mode = MB_FORWARD;
2132                            }
2133                            else
2134                            {
2135                                    best_sad = b_sad16;
2136                                    mb->mode = MB_BACKWARD;
2137                            }
2138    
2139                            if (i_sad16 < best_sad)
2140                            {
2141                                    best_sad = i_sad16;
2142                                    mb->mode = MB_INTERPOLATE;
2143                            }
2144    
2145                            if (d_sad16 < best_sad)
2146                            {
2147                                    best_sad = d_sad16;
2148                                    mb->mode = MB_DIRECT;
2149                            }
2150    
2151                    }
2152            }
2153    }
2154    
2155    */

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

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