[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 115, Thu Apr 11 10:18:40 2002 UTC revision 370, Mon Aug 12 10:07:16 2002 UTC
# Line 1  Line 1 
1  /**************************************************************************  /**************************************************************************
2   *   *
3     *      XVID MPEG-4 VIDEO CODEC
4     *      motion estimation
5     *
6     *      This program is an implementation of a part of one or more MPEG-4
7     *      Video tools as specified in ISO/IEC 14496-2 standard.  Those intending
8     *      to use this software module in hardware or software products are
9     *      advised that its use may infringe existing patents or copyrights, and
10     *      any such use would be at such party's own risk.  The original
11     *      developer of this software module and his/her company, and subsequent
12     *      editors and their companies, will have no liability for use of this
13     *      software or modifications or derivatives thereof.
14     *
15     *      This program is free software; you can redistribute it and/or modify
16     *      it under the terms of the GNU General Public License as published by
17     *      the Free Software Foundation; either version 2 of the License, or
18     *      (at your option) any later version.
19     *
20     *      This program is distributed in the hope that it will be useful,
21     *      but WITHOUT ANY WARRANTY; without even the implied warranty of
22     *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23     *      GNU General Public License for more details.
24     *
25     *      You should have received a copy of the GNU General Public License
26     *      along with this program; if not, write to the Free Software
27     *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28     *
29     *************************************************************************/
30    
31    /**************************************************************************
32     *
33   *  Modifications:   *  Modifications:
34   *   *
35     *      01.05.2002      updated MotionEstimationBVOP
36     *      25.04.2002 partial prevMB conversion
37     *  22.04.2002 remove some compile warning by chenm001 <chenm001@163.com>
38     *  14.04.2002 added MotionEstimationBVOP()
39   *  02.04.2002 add EPZS(^2) as ME algorithm, use PMV_USESQUARES to choose between   *  02.04.2002 add EPZS(^2) as ME algorithm, use PMV_USESQUARES to choose between
40   *             EPZS and EPZS^2   *             EPZS and EPZS^2
41   *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop   *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop
# Line 40  Line 74 
74  #include "../prediction/mbprediction.h"  #include "../prediction/mbprediction.h"
75  #include "../global.h"  #include "../global.h"
76  #include "../utils/timer.h"  #include "../utils/timer.h"
77    #include "motion.h"
78  #include "sad.h"  #include "sad.h"
79    
 // very large value  
 #define MV_MAX_ERROR    (4096 * 256)  
   
 // stop search if sdelta < THRESHOLD  
 #define MV16_THRESHOLD  192  
 #define MV8_THRESHOLD   56  
   
 /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */  
 /* nb  = vop pixels * 2^(bpp-8) */  
 #define MV16_00_BIAS    (128+1)  
   
 /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */  
 #define INTER_BIAS      512  
   
 /* Parameters which control inter/inter4v decision */  
 #define IMV16X16                        5  
   
 /* vector map (vlc delta size) smoother parameters */  
 #define NEIGH_TEND_16X16        2  
 #define NEIGH_TEND_8X8          2  
   
   
 // fast ((A)/2)*2  
 #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)  
   
   
 #define MIN(X, Y) ((X)<(Y)?(X):(Y))  
 #define MAX(X, Y) ((X)>(Y)?(X):(Y))  
 #define ABS(X)    (((X)>0)?(X):-(X))  
 #define SIGN(X)   (((X)>0)?1:-1)  
   
 int32_t PMVfastSearch16(  
                                         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,  
                                         const MBParam * const pParam,  
                                         MACROBLOCK * const pMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
 int32_t EPZSSearch16(  
                                         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,  
                                         const MBParam * const pParam,  
                                         MACROBLOCK * const pMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
   
 int32_t PMVfastSearch8(  
                                         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 int start_x, int start_y,  
                                         const uint32_t MotionFlags,  
                                         const MBParam * const pParam,  
                                         MACROBLOCK * const pMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
 int32_t EPZSSearch8(  
                                         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 int start_x, int start_y,  
                                         const uint32_t MotionFlags,  
                                         const MBParam * const pParam,  
                                         MACROBLOCK * const pMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
80    
 typedef int32_t (MainSearch16Func)(  
         const uint8_t * const pRef,  
         const uint8_t * const pRefH,  
         const uint8_t * const pRefV,  
         const uint8_t * const pRefHV,  
         const uint8_t * const cur,  
         const int x, const int y,  
         int32_t startx, int32_t starty,  
         int32_t iMinSAD,  
         VECTOR * const currMV,  
         const VECTOR * const pmv,  
         const int32_t min_dx, const int32_t max_dx,  
         const int32_t min_dy, const int32_t max_dy,  
         const int32_t iEdgedWidth,  
         const int32_t iDiamondSize,  
         const int32_t iFcode,  
         const int32_t iQuant,  
         int iFound);  
81    
82  typedef MainSearch16Func* MainSearch16FuncPtr;  static int32_t lambda_vec16[32] =       /* rounded values for lambda param for weight of motion bits as in modified H.26L */
83    { 0, (int) (1.00235 + 0.5), (int) (1.15582 + 0.5), (int) (1.31976 + 0.5),
84                    (int) (1.49591 + 0.5), (int) (1.68601 + 0.5),
85            (int) (1.89187 + 0.5), (int) (2.11542 + 0.5), (int) (2.35878 + 0.5),
86                    (int) (2.62429 + 0.5), (int) (2.91455 + 0.5),
87            (int) (3.23253 + 0.5), (int) (3.58158 + 0.5), (int) (3.96555 + 0.5),
88                    (int) (4.38887 + 0.5), (int) (4.85673 + 0.5),
89            (int) (5.37519 + 0.5), (int) (5.95144 + 0.5), (int) (6.59408 + 0.5),
90                    (int) (7.31349 + 0.5), (int) (8.12242 + 0.5),
91            (int) (9.03669 + 0.5), (int) (10.0763 + 0.5), (int) (11.2669 + 0.5),
92                    (int) (12.6426 + 0.5), (int) (14.2493 + 0.5),
93            (int) (16.1512 + 0.5), (int) (18.442 + 0.5), (int) (21.2656 + 0.5),
94                    (int) (24.8580 + 0.5), (int) (29.6436 + 0.5),
95            (int) (36.4949 + 0.5)
96    };
97    
98    static int32_t *lambda_vec8 = lambda_vec16;     /* same table for INTER and INTER4V for now */
99    
 typedef int32_t (MainSearch8Func)(  
         const uint8_t * const pRef,  
         const uint8_t * const pRefH,  
         const uint8_t * const pRefV,  
         const uint8_t * const pRefHV,  
         const uint8_t * const cur,  
         const int x, const int y,  
         int32_t startx, int32_t starty,  
         int32_t iMinSAD,  
         VECTOR * const currMV,  
         const VECTOR * const pmv,  
         const int32_t min_dx, const int32_t max_dx,  
         const int32_t min_dy, const int32_t max_dy,  
         const int32_t iEdgedWidth,  
         const int32_t iDiamondSize,  
         const int32_t iFcode,  
         const int32_t iQuant,  
         int iFound);  
100    
 typedef MainSearch8Func* MainSearch8FuncPtr;  
101    
102  // mv.length table  // mv.length table
103  static const uint32_t mvtab[33] = {  static const uint32_t mvtab[33] = {
# Line 181  Line 108 
108  };  };
109    
110    
111  static __inline uint32_t mv_bits(int32_t component, const uint32_t iFcode)  static __inline uint32_t
112    mv_bits(int32_t component,
113                    const uint32_t iFcode)
114  {  {
115      if (component == 0)      if (component == 0)
116                  return 1;                  return 1;
# Line 189  Line 118 
118      if (component < 0)      if (component < 0)
119                  component = -component;                  component = -component;
120    
121      if (iFcode == 1)          if (iFcode == 1) {
     {  
122                  if (component > 32)                  if (component > 32)
123                      component = 32;                      component = 32;
124    
# Line 207  Line 135 
135  }  }
136    
137    
138  static __inline uint32_t calc_delta_16(const int32_t dx, const int32_t dy, const uint32_t iFcode)  static __inline uint32_t
139  {  calc_delta_16(const int32_t dx,
140          return NEIGH_TEND_16X16 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));                            const int32_t dy,
141  }                            const uint32_t iFcode,
142                              const uint32_t iQuant)
143  static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode)  {
144            return NEIGH_TEND_16X16 * lambda_vec16[iQuant] * (mv_bits(dx, iFcode) +
145  {                                                                                                            mv_bits(dy, iFcode));
146      return NEIGH_TEND_8X8 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));  }
147  }  
148    static __inline uint32_t
149    calc_delta_8(const int32_t dx,
150                             const int32_t dy,
151                             const uint32_t iFcode,
152  /* calculate the min/max range (in halfpixels)                           const uint32_t iQuant)
153          relative to the _MACROBLOCK_ position  {
154  */          return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) +
155                                                                                                       mv_bits(dy, iFcode));
156  static void __inline get_range(  }
157          int32_t * const min_dx, int32_t * const max_dx,  
158          int32_t * const min_dy, int32_t * const max_dy,  bool
159          const uint32_t x, const uint32_t y,  MotionEstimation(MBParam * const pParam,
160          const uint32_t block_sz,                                        // block dimension, 8 or 16                                   FRAMEINFO * const current,
161          const uint32_t width, const uint32_t height,                                   FRAMEINFO * const reference,
         const uint32_t fcode)  
 {  
   
         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;  
         }  
   
 }  
   
   
 /* 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)  
 {  
   
         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;  
         }  
   
 }  
   
 #ifndef SEARCH16  
 #define SEARCH16        PMVfastSearch16  
 //#define SEARCH16      FullSearch16  
 //#define SEARCH16      EPZSSearch16  
 #endif  
   
 #ifndef SEARCH8  
 #define SEARCH8         PMVfastSearch8  
 //#define SEARCH8       EPZSSearch8  
 #endif  
   
 bool MotionEstimation(  
         MACROBLOCK * const pMBs,  
         MBParam * const pParam,  
         const IMAGE * const pRef,  
162          const IMAGE * const pRefH,          const IMAGE * const pRefH,
163          const IMAGE * const pRefV,          const IMAGE * const pRefV,
164          const IMAGE * const pRefHV,          const IMAGE * const pRefHV,
         IMAGE * const pCurrent,  
165          const uint32_t iLimit)          const uint32_t iLimit)
   
166  {  {
167          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
168          const uint32_t iHcount = pParam->mb_height;          const uint32_t iHcount = pParam->mb_height;
169            MACROBLOCK *const pMBs = current->mbs;
170            MACROBLOCK *const prevMBs = reference->mbs;
171            const IMAGE *const pCurrent = &current->image;
172            const IMAGE *const pRef = &reference->image;
173    
174            static const VECTOR zeroMV = { 0, 0 };
175            VECTOR predMV;
176    
177            int32_t x, y;
178            int32_t iIntra = 0;
179            VECTOR pmv;
180    
181          uint32_t i, j, iIntra = 0;          if (sadInit)
182                    (*sadInit) ();
         VECTOR mv16;  
         VECTOR pmv16;  
183    
184          int32_t sad8 = 0;          for (y = 0; y < iHcount; y++)   {
185          int32_t sad16;                  for (x = 0; x < iWcount; x ++)  {
         int32_t deviation;  
186    
187          if (sadInit);                          MACROBLOCK *const pMB = &pMBs[x + y * iWcount];
                 (*sadInit)();  
188    
189          // note: i==horizontal, j==vertical                          if (pMB->mode == MODE_NOT_CODED)
190          for (i = 0; i < iHcount; i++)                                  continue;
                 for (j = 0; j < iWcount; j++)  
                 {  
                         MACROBLOCK *pMB = &pMBs[j + i * iWcount];  
191    
192                          sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                          predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
                                          j, i, pParam->motion_flags,  
                                          pParam, pMBs, &mv16, &pmv16);  
                         pMB->sad16=sad16;  
193    
194                            pMB->sad16 =
195                                    SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
196                                                     x, y, predMV.x, predMV.y, predMV.x, predMV.y,
197                                                     current->motion_flags, current->quant,
198                                                     current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,
199                                                     &pMB->pmvs[0]);
200    
201                          /* decide: MODE_INTER or MODE_INTRA                          if (0 < (pMB->sad16 - MV16_INTER_BIAS)) {
202                             if (dev_intra < sad_inter - 2 * nb) use_intra                                  int32_t deviation;
                         */  
203    
204                          deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width);                                  deviation =
205                                            dev16(pCurrent->y + x * 16 + y * 16 * pParam->edged_width,
206                                                      pParam->edged_width);
207    
208                          if (deviation < (sad16 - INTER_BIAS))                                  if (deviation < (pMB->sad16 - MV16_INTER_BIAS)) {
                         {  
209                                  pMB->mode = MODE_INTRA;                                  pMB->mode = MODE_INTRA;
210                                  pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;                                          pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
211                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;                                                  pMB->mvs[3] = zeroMV;
212                                            pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
213                                                    pMB->sad8[3] = 0;
214    
215                                  iIntra++;                                  iIntra++;
216                                  if(iIntra >= iLimit)                                  if(iIntra >= iLimit)
# Line 373  Line 218 
218    
219                                  continue;                                  continue;
220                          }                          }
   
                         if (pParam->global_flags & XVID_INTER4V)  
                         {  
                                 pMB->sad8[0] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                                        2 * j, 2 * i, mv16.x, mv16.y, pParam->motion_flags,  
                                                        pParam, pMBs, &pMB->mvs[0], &pMB->pmvs[0]);  
   
                                 pMB->sad8[1] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                                        2 * j + 1, 2 * i, mv16.x, mv16.y, pParam->motion_flags,  
                                                        pParam, pMBs, &pMB->mvs[1], &pMB->pmvs[1]);  
   
                                 pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                                        2 * j, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,  
                                                        pParam, pMBs, &pMB->mvs[2], &pMB->pmvs[2]);  
   
                                 pMB->sad8[3] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                                        2 * j + 1, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,  
                                                        pParam, pMBs, &pMB->mvs[3], &pMB->pmvs[3]);  
   
                                 sad8 = pMB->sad8[0] + pMB->sad8[1] + pMB->sad8[2] + pMB->sad8[3];  
221                          }                          }
222    
223                            pmv = pMB->pmvs[0];
224                            if (current->global_flags & XVID_INTER4V)
225                                    if ((!(current->global_flags & XVID_LUMIMASKING) ||
226                                             pMB->dquant == NO_CHANGE)) {
227                                            int32_t sad8 = IMV16X16 * current->quant;
228    
229                                            if (sad8 < pMB->sad16) {
230                                                    sad8 += pMB->sad8[0] =
231                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
232                                                                            pCurrent, 2 * x, 2 * y,
233                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
234                                                                            current->motion_flags,
235                                                                            current->quant, current->fcode, pParam,
236                                                                            pMBs, prevMBs, &pMB->mvs[0],
237                                                                            &pMB->pmvs[0]);
238                                            }
239                                            if (sad8 < pMB->sad16) {
240    
241                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 1);
242                                                    sad8 += pMB->sad8[1] =
243                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
244                                                                            pCurrent, 2 * x + 1, 2 * y,
245                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
246                                                                            current->motion_flags,
247                                                                            current->quant, current->fcode, pParam,
248                                                                            pMBs, prevMBs, &pMB->mvs[1],
249                                                                            &pMB->pmvs[1]);
250                                            }
251                                            if (sad8 < pMB->sad16) {
252                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 2);
253                                                    sad8 += pMB->sad8[2] =
254                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
255                                                                            pCurrent, 2 * x, 2 * y + 1,
256                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
257                                                                            current->motion_flags,
258                                                                            current->quant, current->fcode, pParam,
259                                                                            pMBs, prevMBs, &pMB->mvs[2],
260                                                                            &pMB->pmvs[2]);
261                                            }
262                                            if (sad8 < pMB->sad16) {
263                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 3);
264                                                    sad8 += pMB->sad8[3] =
265                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
266                                                                            pCurrent, 2 * x + 1, 2 * y + 1,
267                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
268                                                                            current->motion_flags,
269                                                                            current->quant, current->fcode, pParam,
270                                                                            pMBs, prevMBs,
271                                                                            &pMB->mvs[3],
272                                                                            &pMB->pmvs[3]);
273                                            }
274    
275                          /* decide: MODE_INTER or MODE_INTER4V                          /* decide: MODE_INTER or MODE_INTER4V
276                             mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v                                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
277                          */                          */
278    
279                          if (pMB->dquant == NO_CHANGE) {                                          if (sad8 < pMB->sad16) {
                                 if (((pParam->global_flags & XVID_INTER4V)==0) ||  
                                     (sad16 < (sad8 + (int32_t)(IMV16X16 * pParam->quant)))) {  
   
                                         sad8 = sad16;  
                                         pMB->mode = MODE_INTER;  
                                         pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;  
                                         pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;  
                                         pMB->pmvs[0].x = pmv16.x;  
                                         pMB->pmvs[0].y = pmv16.y;  
                                 }  
                                 else  
280                                          pMB->mode = MODE_INTER4V;                                          pMB->mode = MODE_INTER4V;
281                                                    pMB->sad8[0] *= 4;
282                                                    pMB->sad8[1] *= 4;
283                                                    pMB->sad8[2] *= 4;
284                                                    pMB->sad8[3] *= 4;
285                                                    continue;
286                          }                          }
287                          else  
288                          {                                  }
289                                  sad8 = sad16;  
290                                  pMB->mode = MODE_INTER;                                  pMB->mode = MODE_INTER;
291                                  pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;                          pMB->pmvs[0] = pmv;     /* pMB->pmvs[1] = pMB->pmvs[2] = pMB->pmvs[3]  are not needed for INTER */
292                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
293                                  pMB->pmvs[0].x = pmv16.x;                          pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =
294                                  pMB->pmvs[0].y = pmv16.y;                                  pMB->sad16;
295                          }                          }
296                  }                  }
297    
298          return 0;          return 0;
299  }  }
300    
 #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )  
   
 #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )  
   
301    
302  #define CHECK_MV16_ZERO {\  #define CHECK_MV16_ZERO {\
303    if ( (0 <= max_dx) && (0 >= min_dx) \    if ( (0 <= max_dx) && (0 >= min_dx) \
304      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
305    { \    { \
306      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); \
307      iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16(-center_x, -center_y, (uint8_t)iFcode, iQuant);\
     if (iSAD <= iQuant * 96)    \  
         iSAD -= MV16_00_BIAS; \  
308      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
309      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
310  }  }
311    
312  #define NOCHECK_MV16_CANDIDATE(X,Y) { \  #define NOCHECK_MV16_CANDIDATE(X,Y) { \
313      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); \
314      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
315      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
316      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
317  }  }
# Line 457  Line 321 
321      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
322    { \    { \
323      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); \
324      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
325      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
326      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
327  }  }
# Line 467  Line 331 
331      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
332    { \    { \
333      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); \
334      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
335      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
336      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
337  }  }
# Line 477  Line 341 
341      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
342    { \    { \
343      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); \
344      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
345      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
346      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
347  }  }
# Line 485  Line 349 
349    
350  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
351    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); \
352    iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\    iSAD += calc_delta_8(-center_x, -center_y, (uint8_t)iFcode, iQuant);\
353    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
354    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
355  }  }
# Line 493  Line 357 
357  #define NOCHECK_MV8_CANDIDATE(X,Y) \  #define NOCHECK_MV8_CANDIDATE(X,Y) \
358    { \    { \
359      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); \
360      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
361      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
362      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
363  }  }
# Line 503  Line 367 
367      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
368    { \    { \
369      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); \
370      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
371      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
372      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
373  }  }
# Line 513  Line 377 
377      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
378    { \    { \
379      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); \
380      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
381      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
382      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
383  }  }
# Line 523  Line 387 
387      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
388    { \    { \
389      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); \
390      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
391      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
392      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
393  }  }
# Line 538  Line 402 
402                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
403                                          const int x, const int y,                                          const int x, const int y,
404                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
405                                            const uint32_t iQuant,
406                                            const uint32_t iFcode,
407                                          MBParam * const pParam,                                          MBParam * const pParam,
408                                          MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
409                                            const MACROBLOCK * const prevMBs,
410                                          VECTOR * const currMV,                                          VECTOR * const currMV,
411                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
412  {  {
413          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
         const int32_t iQuant = pParam->quant;  
414          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
415          int32_t iSAD;          int32_t iSAD;
416          int32_t pred_x,pred_y;          VECTOR pred;
417    
418          get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);  
419            pred = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
420    
421          iSAD = sad16( cur,          iSAD = sad16( cur,
422                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),
# Line 559  Line 426 
426    
427          currMV->x = 0;          currMV->x = 0;
428          currMV->y = 0;          currMV->y = 0;
429          currPMV->x = -pred_x;          currPMV->x = -pred.x;
430          currPMV->y = -pred_y;          currPMV->y = -pred.y;
431    
432          return iSAD;          return iSAD;
433    
434  }  }
435  */  */
436    
437  int32_t Diamond16_MainSearch(  int32_t
438          const uint8_t * const pRef,  Diamond16_MainSearch(const uint8_t * const pRef,
439          const uint8_t * const pRefH,          const uint8_t * const pRefH,
440          const uint8_t * const pRefV,          const uint8_t * const pRefV,
441          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
442          const uint8_t * const cur,          const uint8_t * const cur,
443          const int x, const int y,                                           const int x,
444          int32_t startx, int32_t starty,                                           const int y,
445          int32_t iMinSAD,                                     const int start_x,
446                                       const int start_y,
447                                       int iMinSAD,
448          VECTOR * const currMV,          VECTOR * const currMV,
449          const VECTOR * const pmv,                                     const int center_x,
450          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
451          const int32_t min_dy, const int32_t max_dy,                                           const int32_t min_dx,
452                                             const int32_t max_dx,
453                                             const int32_t min_dy,
454                                             const int32_t max_dy,
455          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
456          const int32_t iDiamondSize,          const int32_t iDiamondSize,
457          const int32_t iFcode,          const int32_t iFcode,
# Line 589  Line 461 
461  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
462    
463          int32_t iDirection=0;          int32_t iDirection=0;
464            int32_t iDirectionBackup;
465          int32_t iSAD;          int32_t iSAD;
466          VECTOR backupMV;          VECTOR backupMV;
467          backupMV.x = startx;  
468          backupMV.y = starty;          backupMV.x = start_x;
469            backupMV.y = start_y;
470    
471  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
472    
# Line 601  Line 475 
475          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
476          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
477    
478          if (iDirection)          if (iDirection) {
479                  while (!iFound)                  while (!iFound) {
                 {  
480                          iFound = 1;                          iFound = 1;
481                          backupMV=*currMV;                          backupMV=*currMV;
482                            iDirectionBackup = iDirection;
483    
484                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
485                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
486                          if ( iDirection != 1)                                                                                     backupMV.y, 1);
487                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
488                          if ( iDirection != 4)                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
489                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                     backupMV.y, 2);
490                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
491                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
492                                                                                       backupMV.y - iDiamondSize, 3);
493                            if (iDirectionBackup != 3)
494                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
495                                                                                       backupMV.y + iDiamondSize, 4);
496                  }                  }
497          else          } else {
498          {                  currMV->x = start_x;
499                  currMV->x = startx;                  currMV->y = start_y;
                 currMV->y = starty;  
500          }          }
501          return iMinSAD;          return iMinSAD;
502  }  }
503    
504  int32_t Square16_MainSearch(  int32_t
505                                          const uint8_t * const pRef,  Square16_MainSearch(const uint8_t * const pRef,
506                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
507                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
508                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
509                                          const uint8_t * const cur,                                          const uint8_t * const cur,
510                                          const int x, const int y,                                          const int x,
511                                          int32_t startx, int32_t starty,                                          const int y,
512                                          int32_t iMinSAD,                                     const int start_x,
513                                       const int start_y,
514                                       int iMinSAD,
515                                          VECTOR * const currMV,                                          VECTOR * const currMV,
516                                          const VECTOR * const pmv,                                     const int center_x,
517                                          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
518                                          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
519                                            const int32_t max_dx,
520                                            const int32_t min_dy,
521                                            const int32_t max_dy,
522                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
523                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
524                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 648  Line 530 
530          int32_t iDirection=0;          int32_t iDirection=0;
531          int32_t iSAD;          int32_t iSAD;
532          VECTOR backupMV;          VECTOR backupMV;
533          backupMV.x = startx;  
534          backupMV.y = starty;          backupMV.x = start_x;
535            backupMV.y = start_y;
536    
537  /* It's one search with full square pattern, and new parts for all following diamonds */  /* It's one search with full square pattern, and new parts for all following diamonds */
538    
# Line 664  Line 547 
547          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
548          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
549    
550          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
551          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                           backupMV.y - iDiamondSize, 5);
552          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
553          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                                           backupMV.y + iDiamondSize, 6);
554            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
555                                                             backupMV.y - iDiamondSize, 7);
556            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
557                                                             backupMV.y + iDiamondSize, 8);
558    
559    
560          if (iDirection)          if (iDirection) {
561                  while (!iFound)                  while (!iFound) {
                 {  
562                          iFound = 1;                          iFound = 1;
563                          backupMV=*currMV;                          backupMV=*currMV;
564    
565                          switch (iDirection)                          switch (iDirection) {
                         {  
566                                  case 1:                                  case 1:
567                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
568                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                     backupMV.y, 1);
569                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
570                                                                                     backupMV.y - iDiamondSize, 5);
571                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
572                                                                                     backupMV.y - iDiamondSize, 7);
573                                          break;                                          break;
574                                  case 2:                                  case 2:
575                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
576                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   2);
577                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
578                                                                                     backupMV.y + iDiamondSize, 6);
579                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
580                                                                                     backupMV.y + iDiamondSize, 8);
581                                          break;                                          break;
582    
583                                  case 3:                                  case 3:
584                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
585                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
586                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
587                                                                                     backupMV.y - iDiamondSize, 7);
588                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
589                                                                                     backupMV.y + iDiamondSize, 8);
590                                          break;                                          break;
591    
592                                  case 4:                                  case 4:
593                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
594                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
595                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
596                                                                                     backupMV.y - iDiamondSize, 5);
597                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
598                                                                                     backupMV.y + iDiamondSize, 6);
599                                          break;                                          break;
600    
601                                  case 5:                                  case 5:
602                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
603                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   1);
604                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
605                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   3);
606                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
607                                                                                     backupMV.y - iDiamondSize, 5);
608                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
609                                                                                     backupMV.y + iDiamondSize, 6);
610                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
611                                                                                     backupMV.y - iDiamondSize, 7);
612                                          break;                                          break;
613    
614                                  case 6:                                  case 6:
615                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
616                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   2);
617                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
618                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
619                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);  
620                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
621                                                                                     backupMV.y - iDiamondSize, 5);
622                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
623                                                                                     backupMV.y + iDiamondSize, 6);
624                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
625                                                                                     backupMV.y + iDiamondSize, 8);
626    
627                                          break;                                          break;
628    
629                                  case 7:                                  case 7:
630                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
631                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                     backupMV.y, 1);
632                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
633                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
634                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
635                                                                                     backupMV.y - iDiamondSize, 5);
636                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
637                                                                                     backupMV.y - iDiamondSize, 7);
638                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
639                                                                                     backupMV.y + iDiamondSize, 8);
640                                          break;                                          break;
641    
642                                  case 8:                                  case 8:
643                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
644                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
645                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
646                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
647                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
648                                                                                     backupMV.y + iDiamondSize, 6);
649                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
650                                                                                     backupMV.y - iDiamondSize, 7);
651                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
652                                                                                     backupMV.y + iDiamondSize, 8);
653                                          break;                                          break;
654                          default:                          default:
655                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
656                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                                                                   1);
657                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
658                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
659                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
660                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
661                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
662                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
663                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);  
664                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
665                                                                                     backupMV.y - iDiamondSize, 5);
666                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
667                                                                                     backupMV.y + iDiamondSize, 6);
668                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
669                                                                                     backupMV.y - iDiamondSize, 7);
670                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
671                                                                                     backupMV.y + iDiamondSize, 8);
672                                          break;                                          break;
673                          }                          }
674                  }                  }
675          else          } else {
676                  {                  currMV->x = start_x;
677                          currMV->x = startx;                  currMV->y = start_y;
                         currMV->y = starty;  
678                  }                  }
679          return iMinSAD;          return iMinSAD;
680  }  }
681    
682    
683  int32_t Full16_MainSearch(  int32_t
684                                          const uint8_t * const pRef,  Full16_MainSearch(const uint8_t * const pRef,
685                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
686                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
687                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
688                                          const uint8_t * const cur,                                          const uint8_t * const cur,
689                                          const int x, const int y,                                    const int x,
690                                          int32_t startx, int32_t starty,                                    const int y,
691                                          int32_t iMinSAD,                                     const int start_x,
692                                       const int start_y,
693                                       int iMinSAD,
694                                          VECTOR * const currMV,                                          VECTOR * const currMV,
695                                          const VECTOR * const pmv,                                     const int center_x,
696                                          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
697                                          const int32_t min_dy, const int32_t max_dy,                                    const int32_t min_dx,
698                                      const int32_t max_dx,
699                                      const int32_t min_dy,
700                                      const int32_t max_dy,
701                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
702                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
703                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 778  Line 707 
707          int32_t iSAD;          int32_t iSAD;
708          int32_t dx,dy;          int32_t dx,dy;
709          VECTOR backupMV;          VECTOR backupMV;
710          backupMV.x = startx;  
711          backupMV.y = starty;          backupMV.x = start_x;
712            backupMV.y = start_y;
713    
714          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
715                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
# Line 788  Line 718 
718          return iMinSAD;          return iMinSAD;
719  }  }
720    
721  int32_t Full8_MainSearch(  int32_t
722                                          const uint8_t * const pRef,  AdvDiamond16_MainSearch(const uint8_t * const pRef,
723                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
724                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
725                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
726                                          const uint8_t * const cur,                                          const uint8_t * const cur,
727                                          const int x, const int y,                                                  const int x,
728                                          int32_t startx, int32_t starty,                                                  const int y,
729                                          int32_t iMinSAD,                                             int start_x,
730                                               int start_y,
731                                               int iMinSAD,
732                                          VECTOR * const currMV,                                          VECTOR * const currMV,
733                                          const VECTOR * const pmv,                                             const int center_x,
734                                          const int32_t min_dx, const int32_t max_dx,                                             const int center_y,
735                                          const int32_t min_dy, const int32_t max_dy,                                                  const int32_t min_dx,
736                                                    const int32_t max_dx,
737                                                    const int32_t min_dy,
738                                                    const int32_t max_dy,
739                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
740                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
741                                          const int32_t iFcode,                                          const int32_t iFcode,
742                                          const int32_t iQuant,                                          const int32_t iQuant,
743                                          int iFound)                                                  int iDirection)
744  {  {
745    
746          int32_t iSAD;          int32_t iSAD;
         int32_t dx,dy;  
         VECTOR backupMV;  
         backupMV.x = startx;  
         backupMV.y = starty;  
747    
748          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
                 for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)  
                         NOCHECK_MV8_CANDIDATE(dx,dy);  
749    
750          return iMinSAD;          if (iDirection) {
751  }                  CHECK_MV16_CANDIDATE(start_x - iDiamondSize, start_y);
752                    CHECK_MV16_CANDIDATE(start_x + iDiamondSize, start_y);
753                    CHECK_MV16_CANDIDATE(start_x, start_y - iDiamondSize);
754                    CHECK_MV16_CANDIDATE(start_x, start_y + iDiamondSize);
755            } else {
756                    int bDirection = 1 + 2 + 4 + 8;
757    
758                    do {
759                            iDirection = 0;
760                            if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
761                                    CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
762    
763                            if (bDirection & 2)
764                                    CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
765    
766  int32_t Halfpel16_Refine(                          if (bDirection & 4)
767          const uint8_t * const pRef,                                  CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
         const uint8_t * const pRefH,  
         const uint8_t * const pRefV,  
         const uint8_t * const pRefHV,  
         const uint8_t * const cur,  
         const int x, const int y,  
         VECTOR * const currMV,  
         int32_t iMinSAD,  
         const VECTOR * const pmv,  
         const int32_t min_dx, const int32_t max_dx,  
         const int32_t min_dy, const int32_t max_dy,  
         const int32_t iFcode,  
         const int32_t iQuant,  
         const int32_t iEdgedWidth)  
 {  
 /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  
768    
769          int32_t iSAD;                          if (bDirection & 8)
770          VECTOR backupMV = *currMV;                                  CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
771    
772          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y-1);                          /* now we're doing diagonal checks near our candidate */
         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);  
773    
774          return iMinSAD;                          if (iDirection)         //checking if anything found
775                            {
776                                    bDirection = iDirection;
777                                    iDirection = 0;
778                                    start_x = currMV->x;
779                                    start_y = currMV->y;
780                                    if (bDirection & 3)     //our candidate is left or right
781                                    {
782                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
783                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
784                                    } else                  // what remains here is up or down
785                                    {
786                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
787                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
788  }  }
789    
790  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)                                  if (iDirection) {
791                                            bDirection += iDirection;
792                                            start_x = currMV->x;
793  int32_t PMVfastSearch16(                                          start_y = currMV->y;
794                                          const uint8_t * const pRef,                                  }
795                                          const uint8_t * const pRefH,                          } else                          //about to quit, eh? not so fast....
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const uint32_t MotionFlags,  
                                         const MBParam * const pParam,  
                                         MACROBLOCK * const pMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV)  
796  {  {
797          const uint32_t iWcount = pParam->mb_width;                                  switch (bDirection) {
798          const int32_t iFcode = pParam->fixed_code;                                  case 2:
799          const int32_t iQuant = pParam->quant;                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
800          const int32_t iWidth = pParam->width;                                                                                           start_y - iDiamondSize, 2 + 4);
801          const int32_t iHeight = pParam->height;                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
802          const int32_t iEdgedWidth = pParam->edged_width;                                                                                           start_y + iDiamondSize, 2 + 8);
803                                            break;
804          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;                                  case 1:
805    
806                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
807                                                                                             start_y - iDiamondSize, 1 + 4);
808                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
809                                                                                             start_y + iDiamondSize, 1 + 8);
810                                            break;
811                                    case 2 + 4:
812                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
813                                                                                             start_y - iDiamondSize, 1 + 4);
814                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
815                                                                                             start_y - iDiamondSize, 2 + 4);
816                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
817                                                                                             start_y + iDiamondSize, 2 + 8);
818                                            break;
819                                    case 4:
820                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
821                                                                                             start_y - iDiamondSize, 2 + 4);
822                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
823                                                                                             start_y - iDiamondSize, 1 + 4);
824                                            break;
825                                    case 8:
826                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
827                                                                                             start_y + iDiamondSize, 2 + 8);
828                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
829                                                                                             start_y + iDiamondSize, 1 + 8);
830                                            break;
831                                    case 1 + 4:
832                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
833                                                                                             start_y + iDiamondSize, 1 + 8);
834                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
835                                                                                             start_y - iDiamondSize, 1 + 4);
836                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
837                                                                                             start_y - iDiamondSize, 2 + 4);
838                                            break;
839                                    case 2 + 8:
840                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
841                                                                                             start_y - iDiamondSize, 1 + 4);
842                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
843                                                                                             start_y + iDiamondSize, 1 + 8);
844                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
845                                                                                             start_y + iDiamondSize, 2 + 8);
846                                            break;
847                                    case 1 + 8:
848                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
849                                                                                             start_y - iDiamondSize, 2 + 4);
850                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
851                                                                                             start_y + iDiamondSize, 2 + 8);
852                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
853                                                                                             start_y + iDiamondSize, 1 + 8);
854                                            break;
855                                    default:                //1+2+4+8 == we didn't find anything at all
856                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
857                                                                                             start_y - iDiamondSize, 1 + 4);
858                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
859                                                                                             start_y + iDiamondSize, 1 + 8);
860                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
861                                                                                             start_y - iDiamondSize, 2 + 4);
862                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
863                                                                                             start_y + iDiamondSize, 2 + 8);
864                                            break;
865                                    }
866                                    if (!iDirection)
867                                            break;          //ok, the end. really
868                                    else {
869                                            bDirection = iDirection;
870                                            start_x = currMV->x;
871                                            start_y = currMV->y;
872                                    }
873                            }
874                    }
875                    while (1);                              //forever
876            }
877            return iMinSAD;
878    }
879    
880    #define CHECK_MV16_F_INTERPOL(X,Y) { \
881      if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
882        && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
883      { \
884        iSAD = sad16bi( cur, \
885                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
886                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
887                            iEdgedWidth); \
888        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
889        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
890        if (iSAD < iMinSAD) \
891        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); } } \
892    }
893    
894    #define CHECK_MV16_F_INTERPOL_FOUND(X,Y) { \
895      if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
896        && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
897      { \
898        iSAD = sad16bi( cur, \
899                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
900                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
901                            iEdgedWidth); \
902        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
903        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
904        if (iSAD < iMinSAD) \
905        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); iFound=0;} } \
906    }
907    
908    #define CHECK_MV16_B_INTERPOL(X,Y) { \
909      if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
910        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
911      { \
912        iSAD = sad16bi( cur, \
913                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
914                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
915                            iEdgedWidth); \
916        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
917        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
918        if (iSAD < iMinSAD) \
919        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); } } \
920    }
921    
922    #define CHECK_MV16_B_INTERPOL_FOUND(X,Y) { \
923      if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
924        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
925      { \
926        iSAD = sad16bi( cur, \
927                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
928                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
929                            iEdgedWidth); \
930        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
931        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
932        if (iSAD < iMinSAD) \
933        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); iFound=0;} } \
934    }
935    
936    int32_t
937    Diamond16_InterpolMainSearch(
938                                            const uint8_t * const f_pRef,
939                                             const uint8_t * const f_pRefH,
940                                             const uint8_t * const f_pRefV,
941                                             const uint8_t * const f_pRefHV,
942    
943                                             const uint8_t * const cur,
944    
945                                            const uint8_t * const b_pRef,
946                                             const uint8_t * const b_pRefH,
947                                             const uint8_t * const b_pRefV,
948                                             const uint8_t * const b_pRefHV,
949    
950                                             const int x,
951                                             const int y,
952    
953                                       const int f_start_x,
954                                       const int f_start_y,
955                                       const int b_start_x,
956                                       const int b_start_y,
957    
958                                       int iMinSAD,
959                                       VECTOR * const f_currMV,
960                                       VECTOR * const b_currMV,
961    
962                                       const int f_center_x,
963                                       const int f_center_y,
964                                       const int b_center_x,
965                                       const int b_center_y,
966    
967                                        const int32_t f_min_dx,
968                                            const int32_t f_max_dx,
969                                            const int32_t f_min_dy,
970                                            const int32_t f_max_dy,
971    
972                                        const int32_t b_min_dx,
973                                            const int32_t b_max_dx,
974                                            const int32_t b_min_dy,
975                                            const int32_t b_max_dy,
976    
977                                            const int32_t iEdgedWidth,
978                                            const int32_t iDiamondSize,
979    
980                                            const int32_t f_iFcode,
981                                            const int32_t b_iFcode,
982    
983                                            const int32_t iQuant,
984                                            int iFound)
985    {
986    /* Do a diamond search around given starting point, return SAD of best */
987    
988            int32_t iSAD;
989    
990            VECTOR f_backupMV;
991            VECTOR b_backupMV;
992    
993            f_currMV->x = f_start_x;
994            f_currMV->y = f_start_y;
995            b_currMV->x = b_start_x;
996            b_currMV->y = b_start_y;
997    
998            do
999            {
1000                    iFound = 1;
1001    
1002                    f_backupMV = *f_currMV;
1003    
1004                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x - iDiamondSize, f_backupMV.y);
1005                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x + iDiamondSize, f_backupMV.y);
1006                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y - iDiamondSize);
1007                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y + iDiamondSize);
1008    
1009                    b_backupMV = *b_currMV;
1010    
1011                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x - iDiamondSize, b_backupMV.y);
1012                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x + iDiamondSize, b_backupMV.y);
1013                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y - iDiamondSize);
1014                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y + iDiamondSize);
1015    
1016            } while (!iFound);
1017    
1018            return iMinSAD;
1019    }
1020    
1021    /* Sorry, these MACROS really got too large... I'll turn them into function soon! */
1022    
1023    #define CHECK_MV16_DIRECT_FOUND(X,Y) \
1024            if ( (X)>=(-32) && (X)<=(31) && ((Y)>=-32) && ((Y)<=31) ) \
1025            { int k;\
1026            VECTOR mvs,b_mvs;       \
1027            iSAD = 0;\
1028            for (k = 0; k < 4; k++) {       \
1029                                            mvs.x = (int32_t) ((TRB * directmv[k].x) / TRD + (X));          \
1030                        b_mvs.x = (int32_t) (((X) == 0)                                                     \
1031                                                                                    ? ((TRB - TRD) * directmv[k].x) / TRD   \
1032                                                : mvs.x - directmv[k].x);                           \
1033                                                                                                                                                                    \
1034                        mvs.y = (int32_t) ((TRB * directmv[k].y) / TRD + (Y));              \
1035                            b_mvs.y = (int32_t) (((Y) == 0)                                                         \
1036                                                                                    ? ((TRB - TRD) * directmv[k].y) / TRD   \
1037                                                : mvs.y - directmv[k].y);                           \
1038                                                                                                                                                                    \
1039      if ( (mvs.x <= max_dx) && (mvs.x >= min_dx) \
1040        && (mvs.y <= max_dy) && (mvs.y >= min_dy)  \
1041            && (b_mvs.x <= max_dx) && (b_mvs.x >= min_dx)  \
1042        && (b_mvs.y <= max_dy) && (b_mvs.y >= min_dy) ) { \
1043                iSAD += sad8bi( cur + 8*(k&1) + 8*(k>>1)*iEdgedWidth,                                                                                                       \
1044                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \
1045                                            mvs.x, mvs.y, iEdgedWidth),                                                             \
1046                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \
1047                                            b_mvs.x, b_mvs.y, iEdgedWidth),                                                         \
1048                            iEdgedWidth); \
1049                    }       \
1050            else    \
1051                    iSAD = 65535;   \
1052            } \
1053            iSAD += calc_delta_16((X),(Y), 1, iQuant);\
1054            if (iSAD < iMinSAD) \
1055                {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iFound=0; } \
1056    }
1057    
1058    
1059    
1060    int32_t
1061    Diamond16_DirectMainSearch(
1062                                            const uint8_t * const f_pRef,
1063                                            const uint8_t * const f_pRefH,
1064                                            const uint8_t * const f_pRefV,
1065                                            const uint8_t * const f_pRefHV,
1066    
1067                                            const uint8_t * const cur,
1068    
1069                                            const uint8_t * const b_pRef,
1070                                            const uint8_t * const b_pRefH,
1071                                            const uint8_t * const b_pRefV,
1072                                            const uint8_t * const b_pRefHV,
1073    
1074                                            const int x,
1075                                            const int y,
1076    
1077                                            const int TRB,
1078                                            const int TRD,
1079    
1080                                        const int start_x,
1081                                        const int start_y,
1082    
1083                                        int iMinSAD,
1084                                        VECTOR * const currMV,
1085                                            const VECTOR * const directmv,
1086    
1087                                        const int32_t min_dx,
1088                                            const int32_t max_dx,
1089                                            const int32_t min_dy,
1090                                            const int32_t max_dy,
1091    
1092                                            const int32_t iEdgedWidth,
1093                                            const int32_t iDiamondSize,
1094    
1095                                            const int32_t iQuant,
1096                                            int iFound)
1097    {
1098    /* Do a diamond search around given starting point, return SAD of best */
1099    
1100            int32_t iSAD;
1101    
1102            VECTOR backupMV;
1103    
1104            currMV->x = start_x;
1105            currMV->y = start_y;
1106    
1107    /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1108    
1109            do
1110            {
1111                    iFound = 1;
1112    
1113                    backupMV = *currMV;
1114    
1115                    CHECK_MV16_DIRECT_FOUND(backupMV.x - iDiamondSize, backupMV.y);
1116                    CHECK_MV16_DIRECT_FOUND(backupMV.x + iDiamondSize, backupMV.y);
1117                    CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y - iDiamondSize);
1118                    CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y + iDiamondSize);
1119    
1120            } while (!iFound);
1121    
1122            return iMinSAD;
1123    }
1124    
1125    
1126    int32_t
1127    AdvDiamond8_MainSearch(const uint8_t * const pRef,
1128                                               const uint8_t * const pRefH,
1129                                               const uint8_t * const pRefV,
1130                                               const uint8_t * const pRefHV,
1131                                               const uint8_t * const cur,
1132                                               const int x,
1133                                               const int y,
1134                                               int start_x,
1135                                               int start_y,
1136                                               int iMinSAD,
1137                                               VECTOR * const currMV,
1138                                               const int center_x,
1139                                               const int center_y,
1140                                               const int32_t min_dx,
1141                                               const int32_t max_dx,
1142                                               const int32_t min_dy,
1143                                               const int32_t max_dy,
1144                                               const int32_t iEdgedWidth,
1145                                               const int32_t iDiamondSize,
1146                                               const int32_t iFcode,
1147                                               const int32_t iQuant,
1148                                               int iDirection)
1149    {
1150    
1151            int32_t iSAD;
1152    
1153    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
1154    
1155            if (iDirection) {
1156                    CHECK_MV8_CANDIDATE(start_x - iDiamondSize, start_y);
1157                    CHECK_MV8_CANDIDATE(start_x + iDiamondSize, start_y);
1158                    CHECK_MV8_CANDIDATE(start_x, start_y - iDiamondSize);
1159                    CHECK_MV8_CANDIDATE(start_x, start_y + iDiamondSize);
1160            } else {
1161                    int bDirection = 1 + 2 + 4 + 8;
1162    
1163                    do {
1164                            iDirection = 0;
1165                            if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
1166                                    CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1167    
1168                            if (bDirection & 2)
1169                                    CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1170    
1171                            if (bDirection & 4)
1172                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1173    
1174                            if (bDirection & 8)
1175                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1176    
1177                            /* now we're doing diagonal checks near our candidate */
1178    
1179                            if (iDirection)         //checking if anything found
1180                            {
1181                                    bDirection = iDirection;
1182                                    iDirection = 0;
1183                                    start_x = currMV->x;
1184                                    start_y = currMV->y;
1185                                    if (bDirection & 3)     //our candidate is left or right
1186                                    {
1187                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1188                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1189                                    } else                  // what remains here is up or down
1190                                    {
1191                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1192                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1193                                    }
1194    
1195                                    if (iDirection) {
1196                                            bDirection += iDirection;
1197                                            start_x = currMV->x;
1198                                            start_y = currMV->y;
1199                                    }
1200                            } else                          //about to quit, eh? not so fast....
1201                            {
1202                                    switch (bDirection) {
1203                                    case 2:
1204                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1205                                                                                            start_y - iDiamondSize, 2 + 4);
1206                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1207                                                                                            start_y + iDiamondSize, 2 + 8);
1208                                            break;
1209                                    case 1:
1210                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1211                                                                                            start_y - iDiamondSize, 1 + 4);
1212                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1213                                                                                            start_y + iDiamondSize, 1 + 8);
1214                                            break;
1215                                    case 2 + 4:
1216                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1217                                                                                            start_y - iDiamondSize, 1 + 4);
1218                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1219                                                                                            start_y - iDiamondSize, 2 + 4);
1220                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1221                                                                                            start_y + iDiamondSize, 2 + 8);
1222                                            break;
1223                                    case 4:
1224                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1225                                                                                            start_y - iDiamondSize, 2 + 4);
1226                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1227                                                                                            start_y - iDiamondSize, 1 + 4);
1228                                            break;
1229                                    case 8:
1230                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1231                                                                                            start_y + iDiamondSize, 2 + 8);
1232                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1233                                                                                            start_y + iDiamondSize, 1 + 8);
1234                                            break;
1235                                    case 1 + 4:
1236                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1237                                                                                            start_y + iDiamondSize, 1 + 8);
1238                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1239                                                                                            start_y - iDiamondSize, 1 + 4);
1240                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1241                                                                                            start_y - iDiamondSize, 2 + 4);
1242                                            break;
1243                                    case 2 + 8:
1244                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1245                                                                                            start_y - iDiamondSize, 1 + 4);
1246                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1247                                                                                            start_y + iDiamondSize, 1 + 8);
1248                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1249                                                                                            start_y + iDiamondSize, 2 + 8);
1250                                            break;
1251                                    case 1 + 8:
1252                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1253                                                                                            start_y - iDiamondSize, 2 + 4);
1254                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1255                                                                                            start_y + iDiamondSize, 2 + 8);
1256                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1257                                                                                            start_y + iDiamondSize, 1 + 8);
1258                                            break;
1259                                    default:                //1+2+4+8 == we didn't find anything at all
1260                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1261                                                                                            start_y - iDiamondSize, 1 + 4);
1262                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1263                                                                                            start_y + iDiamondSize, 1 + 8);
1264                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1265                                                                                            start_y - iDiamondSize, 2 + 4);
1266                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1267                                                                                            start_y + iDiamondSize, 2 + 8);
1268                                            break;
1269                                    }
1270                                    if (!(iDirection))
1271                                            break;          //ok, the end. really
1272                                    else {
1273                                            bDirection = iDirection;
1274                                            start_x = currMV->x;
1275                                            start_y = currMV->y;
1276                                    }
1277                            }
1278                    }
1279                    while (1);                              //forever
1280            }
1281            return iMinSAD;
1282    }
1283    
1284    
1285    int32_t
1286    Full8_MainSearch(const uint8_t * const pRef,
1287                                     const uint8_t * const pRefH,
1288                                     const uint8_t * const pRefV,
1289                                     const uint8_t * const pRefHV,
1290                                     const uint8_t * const cur,
1291                                     const int x,
1292                                     const int y,
1293                               const int start_x,
1294                               const int start_y,
1295                               int iMinSAD,
1296                               VECTOR * const currMV,
1297                               const int center_x,
1298                               const int center_y,
1299                                     const int32_t min_dx,
1300                                     const int32_t max_dx,
1301                                     const int32_t min_dy,
1302                                     const int32_t max_dy,
1303                                     const int32_t iEdgedWidth,
1304                                     const int32_t iDiamondSize,
1305                                     const int32_t iFcode,
1306                                     const int32_t iQuant,
1307                                     int iFound)
1308    {
1309            int32_t iSAD;
1310            int32_t dx, dy;
1311            VECTOR backupMV;
1312    
1313            backupMV.x = start_x;
1314            backupMV.y = start_y;
1315    
1316            for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
1317                    for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
1318                            NOCHECK_MV8_CANDIDATE(dx, dy);
1319    
1320            return iMinSAD;
1321    }
1322    
1323    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1324    
1325    int32_t
1326    Halfpel16_Refine(const uint8_t * const pRef,
1327                                     const uint8_t * const pRefH,
1328                                     const uint8_t * const pRefV,
1329                                     const uint8_t * const pRefHV,
1330                                     const uint8_t * const cur,
1331                                     const int x,
1332                                     const int y,
1333                                     VECTOR * const currMV,
1334                                     int32_t iMinSAD,
1335                               const int center_x,
1336                               const int center_y,
1337                                     const int32_t min_dx,
1338                                     const int32_t max_dx,
1339                                     const int32_t min_dy,
1340                                     const int32_t max_dy,
1341                                     const int32_t iFcode,
1342                                     const int32_t iQuant,
1343                                     const int32_t iEdgedWidth)
1344    {
1345    /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
1346    
1347            int32_t iSAD;
1348            VECTOR backupMV = *currMV;
1349    
1350            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y - 1);
1351            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y - 1);
1352            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y - 1);
1353            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y);
1354            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y);
1355            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y + 1);
1356            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y + 1);
1357            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y + 1);
1358    
1359            return iMinSAD;
1360    }
1361    
1362    #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1363    
1364    
1365    
1366    int32_t
1367    PMVfastSearch16(const uint8_t * const pRef,
1368                                    const uint8_t * const pRefH,
1369                                    const uint8_t * const pRefV,
1370                                    const uint8_t * const pRefHV,
1371                                    const IMAGE * const pCur,
1372                                    const int x,
1373                                    const int y,
1374                                    const int start_x,      /* start is searched first, so it should contain the most */
1375                                    const int start_y,  /* likely motion vector for this block */
1376                                    const int center_x,     /* center is from where length of MVs is measured */
1377                                    const int center_y,
1378                                    const uint32_t MotionFlags,
1379                                    const uint32_t iQuant,
1380                                    const uint32_t iFcode,
1381                                    const MBParam * const pParam,
1382                                    const MACROBLOCK * const pMBs,
1383                                    const MACROBLOCK * const prevMBs,
1384                                    VECTOR * const currMV,
1385                                    VECTOR * const currPMV)
1386    {
1387            const uint32_t iWcount = pParam->mb_width;
1388            const int32_t iWidth = pParam->width;
1389            const int32_t iHeight = pParam->height;
1390            const int32_t iEdgedWidth = pParam->edged_width;
1391    
1392            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
1393    
1394          int32_t iDiamondSize;          int32_t iDiamondSize;
1395    
# Line 895  Line 1406 
1406          VECTOR pmv[4];          VECTOR pmv[4];
1407          int32_t psad[4];          int32_t psad[4];
1408    
1409          MACROBLOCK * const pMB = pMBs + x + y * iWcount;          MainSearch16FuncPtr MainSearchPtr;
1410    
1411            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
1412    
1413          static int32_t threshA,threshB;          int32_t threshA, threshB;
1414          int32_t bPredEq;          int32_t bPredEq;
1415          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1416    
1417  /* Get maximum range */  /* Get maximum range */
1418          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
1419                    x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
1420    
1421  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1422    
1423          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
1424          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1425          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1426          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1427          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1428          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
   
1429    
1430          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1431            //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1432            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1433    
1434          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1435                  threshA =  512;                  threshA =  512;
1436                  threshB = 1024;                  threshB = 1024;
1437            } else {
         }  
         else  
         {  
1438                  threshA = psad[0];                  threshA = psad[0];
1439                  threshB = threshA+256;                  threshB = threshA+256;
1440                  if (threshA< 512) threshA =  512;                  if (threshA < 512)
1441                  if (threshA>1024) threshA = 1024;                          threshA = 512;
1442                  if (threshB>1792) threshB = 1792;                  if (threshA > 1024)
1443                            threshA = 1024;
1444                    if (threshB > 1792)
1445                            threshB = 1792;
1446          }          }
1447    
1448          iFound=0;          iFound=0;
1449    
 /* 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;  
   
1450  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1451     MinSAD=SAD     MinSAD=SAD
1452     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 961  Line 1454 
1454     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
1455  */  */
1456    
1457            currMV->x = start_x;
1458            currMV->y = start_y;
1459    
1460  // Prepare for main loop          if (!(MotionFlags & PMV_HALFPEL16)) {   /* This should NOT be necessary! */
   
         *currMV=pmv[0];         /* current best := prediction */  
         if (!(MotionFlags & PMV_HALFPEL16 ))  
         {       /* This should NOT be necessary! */  
1461                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1462                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
1463          }          }
1464    
1465          if (currMV->x > max_dx)          if (currMV->x > max_dx) {
         {  
1466                  currMV->x=max_dx;                  currMV->x=max_dx;
1467          }          }
1468          if (currMV->x < min_dx)          if (currMV->x < min_dx) {
         {  
1469                  currMV->x=min_dx;                  currMV->x=min_dx;
1470          }          }
1471          if (currMV->y > max_dy)          if (currMV->y > max_dy) {
         {  
1472                  currMV->y=max_dy;                  currMV->y=max_dy;
1473          }          }
1474          if (currMV->y < min_dy)          if (currMV->y < min_dy) {
         {  
1475                  currMV->y=min_dy;                  currMV->y=min_dy;
1476          }          }
1477    
1478          iMinSAD = sad16( cur,          iMinSAD =
1479                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1480                           iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1481          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1482            iMinSAD +=
1483          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
1484          {                                            (uint8_t) iFcode, iQuant);
1485    
1486            if ((iMinSAD < 256) ||
1487                    ((MVequal(*currMV, prevMB->mvs[0])) &&
1488                     ((int32_t) iMinSAD < prevMB->sad16))) {
1489                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
1490                    {
1491                            if (!MVzero(*currMV)) {
1492                                    iMinSAD += MV16_00_BIAS;
1493                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
1494                                    iMinSAD -= MV16_00_BIAS;
1495                            }
1496                    }
1497    
1498                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1499                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
# Line 1002  Line 1501 
1501                          goto PMVfast16_Terminate_with_Refine;                          goto PMVfast16_Terminate_with_Refine;
1502          }          }
1503    
1504    
1505    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1506       vector of the median.
1507       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1508    */
1509    
1510            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[0])))
1511                    iFound = 2;
1512    
1513    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1514       Otherwise select large Diamond Search.
1515    */
1516    
1517            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
1518                    iDiamondSize = 1;               // halfpel!
1519            else
1520                    iDiamondSize = 2;               // halfpel!
1521    
1522            if (!(MotionFlags & PMV_HALFPELDIAMOND16))
1523                    iDiamondSize *= 2;
1524    
1525  /*  /*
1526     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.
1527     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1528     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1529     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1530  */  */
1531    
1532  // (0,0) is always possible  // (0,0) is always possible
1533    
1534            if (!MVzero(pmv[0]))
1535          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1536    
1537  // previous frame MV is always possible  // previous frame MV is always possible
1538          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);  
1539            if (!MVzero(prevMB->mvs[0]))
1540                    if (!MVequal(prevMB->mvs[0], pmv[0]))
1541                            CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
1542    
1543  // left neighbour, if allowed  // left neighbour, if allowed
1544          if (x != 0)  
1545          {          if (!MVzero(pmv[1]))
1546                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!MVequal(pmv[1], prevMB->mvs[0]))
1547                  {       pmv[1].x = EVEN(pmv[1].x);                          if (!MVequal(pmv[1], pmv[0])) {
1548                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1549                                            pmv[1].x = EVEN(pmv[1].x);
1550                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1551                  }                  }
1552    
1553                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1554          }          }
   
1555  // top neighbour, if allowed  // top neighbour, if allowed
1556          if (y != 0)          if (!MVzero(pmv[2]))
1557          {                  if (!MVequal(pmv[2], prevMB->mvs[0]))
1558                  if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!MVequal(pmv[2], pmv[0]))
1559                  {       pmv[2].x = EVEN(pmv[2].x);                                  if (!MVequal(pmv[2], pmv[1])) {
1560                                            if (!(MotionFlags & PMV_HALFPEL16)) {
1561                                                    pmv[2].x = EVEN(pmv[2].x);
1562                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
1563                  }                  }
1564                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1565    
1566  // top right neighbour, if allowed  // top right neighbour, if allowed
1567                  if (x != (iWcount-1))                                          if (!MVzero(pmv[3]))
1568                  {                                                  if (!MVequal(pmv[3], prevMB->mvs[0]))
1569                          if (!(MotionFlags & PMV_HALFPEL16 ))                                                          if (!MVequal(pmv[3], pmv[0]))
1570                          {       pmv[3].x = EVEN(pmv[3].x);                                                                  if (!MVequal(pmv[3], pmv[1]))
1571                                                                            if (!MVequal(pmv[3], pmv[2])) {
1572                                                                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1573                                                                                            pmv[3].x = EVEN(pmv[3].x);
1574                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1575                          }                          }
1576                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                  CHECK_MV16_CANDIDATE(pmv[3].x,
1577                                                                                                                             pmv[3].y);
1578                  }                  }
1579          }          }
1580    
1581            if ((MVzero(*currMV)) &&
1582                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1583                    iMinSAD -= MV16_00_BIAS;
1584    
1585    
1586  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1587     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.
1588  */  */
1589    
1590          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )          if ((iMinSAD <= threshA) ||
1591          {                  (MVequal(*currMV, prevMB->mvs[0]) &&
1592                     ((int32_t) iMinSAD < prevMB->sad16))) {
1593                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1594                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
1595                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1069  Line 1607 
1607     Refine by using small diamond and goto step 10.     Refine by using small diamond and goto step 10.
1608  */  */
1609    
1610            if (MotionFlags & PMV_USESQUARES16)
1611                    MainSearchPtr = Square16_MainSearch;
1612            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
1613                    MainSearchPtr = AdvDiamond16_MainSearch;
1614            else
1615                    MainSearchPtr = Diamond16_MainSearch;
1616    
1617          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1618    
1619    
1620  /* 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 */
1621          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1622                                            x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1623                                            currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->x, currMV->y, iMinSAD, &newMV, center_x, center_y,
1624                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dx, max_dx,
1625                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1626                                                      iQuant, iFound);
1627    
1628          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1629                  *currMV = newMV;                  *currMV = newMV;
1630                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1631          }          }
1632    
1633          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
1634  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1635    
1636                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1637                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1638                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1639                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    center_x, center_y, iMinSAD, &newMV, center_x, center_y,
1640                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1641                                                                      iDiamondSize, iFcode, iQuant, iFound);
1642    
1643                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1644                          *currMV = newMV;                          *currMV = newMV;
1645                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1646                  }                  }
1647                  }                  }
1648    
1649                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1650                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1651                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1652                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y,
1653                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy,
1654                                                                      iEdgedWidth, iDiamondSize, iFcode,
1655                                                                      iQuant, iFound);
1656    
1657                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1658                          *currMV = newMV;                          *currMV = newMV;
1659                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1660                  }                  }
# Line 1120  Line 1667 
1667    
1668  PMVfast16_Terminate_with_Refine:  PMVfast16_Terminate_with_Refine:
1669          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1670                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1671                                    x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1672                                    currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1673                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1674    
1675  PMVfast16_Terminate_without_Refine:  PMVfast16_Terminate_without_Refine:
1676          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
1677          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
1678          return iMinSAD;          return iMinSAD;
1679  }  }
1680    
# Line 1136  Line 1683 
1683    
1684    
1685    
1686  int32_t Diamond8_MainSearch(  int32_t
1687          const uint8_t * const pRef,  Diamond8_MainSearch(const uint8_t * const pRef,
1688          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1689          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1690          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1691          const uint8_t * const cur,          const uint8_t * const cur,
1692          const int x, const int y,                                          const int x,
1693          int32_t startx, int32_t starty,                                          const int y,
1694                                            int32_t start_x,
1695                                            int32_t start_y,
1696          int32_t iMinSAD,          int32_t iMinSAD,
1697          VECTOR * const currMV,          VECTOR * const currMV,
1698          const VECTOR * const pmv,                                     const int center_x,
1699          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
1700          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
1701                                            const int32_t max_dx,
1702                                            const int32_t min_dy,
1703                                            const int32_t max_dy,
1704          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
1705          const int32_t iDiamondSize,          const int32_t iDiamondSize,
1706          const int32_t iFcode,          const int32_t iFcode,
# Line 1158  Line 1710 
1710  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
1711    
1712          int32_t iDirection=0;          int32_t iDirection=0;
1713            int32_t iDirectionBackup;
1714          int32_t iSAD;          int32_t iSAD;
1715          VECTOR backupMV;          VECTOR backupMV;
1716          backupMV.x = startx;  
1717          backupMV.y = starty;          backupMV.x = start_x;
1718            backupMV.y = start_y;
1719    
1720  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1721    
# Line 1170  Line 1724 
1724          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
1725          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1726    
1727          if (iDirection)          if (iDirection) {
1728                  while (!iFound)                  while (!iFound) {
                 {  
1729                          iFound = 1;                          iFound = 1;
1730                          backupMV=*currMV;       // since iDirection!=0, this is well defined!                          backupMV=*currMV;       // since iDirection!=0, this is well defined!
1731                            iDirectionBackup = iDirection;
1732    
1733                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
1734                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1735                          if ( iDirection != 1)                                                                                    backupMV.y, 1);
1736                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
1737                          if ( iDirection != 4)                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1738                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                    backupMV.y, 2);
1739                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
1740                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1741                                                                                      backupMV.y - iDiamondSize, 3);
1742                            if (iDirectionBackup != 3)
1743                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1744                                                                                      backupMV.y + iDiamondSize, 4);
1745                  }                  }
1746          else          } else {
1747                    currMV->x = start_x;
1748                    currMV->y = start_y;
1749            }
1750            return iMinSAD;
1751    }
1752    
1753    
1754    
1755    
1756    int32_t
1757    Square8_MainSearch(const uint8_t * const pRef,
1758                                            const uint8_t * const pRefH,
1759                                            const uint8_t * const pRefV,
1760                                            const uint8_t * const pRefHV,
1761                                            const uint8_t * const cur,
1762                                            const int x,
1763                                            const int y,
1764                                            int32_t start_x,
1765                                            int32_t start_y,
1766                                            int32_t iMinSAD,
1767                                            VECTOR * const currMV,
1768                                       const int center_x,
1769                                       const int center_y,
1770                                            const int32_t min_dx,
1771                                            const int32_t max_dx,
1772                                            const int32_t min_dy,
1773                                            const int32_t max_dy,
1774                                            const int32_t iEdgedWidth,
1775                                            const int32_t iDiamondSize,
1776                                            const int32_t iFcode,
1777                                            const int32_t iQuant,
1778                                            int iFound)
1779          {          {
1780                  currMV->x = startx;  /* Do a square search around given starting point, return SAD of best */
1781                  currMV->y = starty;  
1782            int32_t iDirection = 0;
1783            int32_t iSAD;
1784            VECTOR backupMV;
1785    
1786            backupMV.x = start_x;
1787            backupMV.y = start_y;
1788    
1789    /* It's one search with full square pattern, and new parts for all following diamonds */
1790    
1791    /*   new direction are extra, so 1-4 is normal diamond
1792          537
1793          1*2
1794          648
1795    */
1796    
1797            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1798            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1799            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1800            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1801    
1802            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1803                                                             backupMV.y - iDiamondSize, 5);
1804            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1805                                                             backupMV.y + iDiamondSize, 6);
1806            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1807                                                             backupMV.y - iDiamondSize, 7);
1808            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1809                                                             backupMV.y + iDiamondSize, 8);
1810    
1811    
1812            if (iDirection) {
1813                    while (!iFound) {
1814                            iFound = 1;
1815                            backupMV = *currMV;
1816    
1817                            switch (iDirection) {
1818                            case 1:
1819                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1820                                                                                       backupMV.y, 1);
1821                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1822                                                                                     backupMV.y - iDiamondSize, 5);
1823                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1824                                                                                     backupMV.y - iDiamondSize, 7);
1825                                    break;
1826                            case 2:
1827                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1828                                                                                     2);
1829                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1830                                                                                     backupMV.y + iDiamondSize, 6);
1831                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1832                                                                                     backupMV.y + iDiamondSize, 8);
1833                                    break;
1834    
1835                            case 3:
1836                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1837                                                                                     4);
1838                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1839                                                                                     backupMV.y - iDiamondSize, 7);
1840                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1841                                                                                     backupMV.y + iDiamondSize, 8);
1842                                    break;
1843    
1844                            case 4:
1845                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1846                                                                                     3);
1847                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1848                                                                                     backupMV.y - iDiamondSize, 5);
1849                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1850                                                                                     backupMV.y + iDiamondSize, 6);
1851                                    break;
1852    
1853                            case 5:
1854                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1855                                                                                     1);
1856                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1857                                                                                     3);
1858                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1859                                                                                     backupMV.y - iDiamondSize, 5);
1860                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1861                                                                                     backupMV.y + iDiamondSize, 6);
1862                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1863                                                                                     backupMV.y - iDiamondSize, 7);
1864                                    break;
1865    
1866                            case 6:
1867                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1868                                                                                     2);
1869                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1870                                                                                     3);
1871    
1872                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1873                                                                                     backupMV.y - iDiamondSize, 5);
1874                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1875                                                                                     backupMV.y + iDiamondSize, 6);
1876                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1877                                                                                     backupMV.y + iDiamondSize, 8);
1878    
1879                                    break;
1880    
1881                            case 7:
1882                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1883                                                                                       backupMV.y, 1);
1884                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1885                                                                                     4);
1886                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1887                                                                                     backupMV.y - iDiamondSize, 5);
1888                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1889                                                                                     backupMV.y - iDiamondSize, 7);
1890                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1891                                                                                     backupMV.y + iDiamondSize, 8);
1892                                    break;
1893    
1894                            case 8:
1895                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1896                                                                                     2);
1897                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1898                                                                                     4);
1899                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1900                                                                                     backupMV.y + iDiamondSize, 6);
1901                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1902                                                                                     backupMV.y - iDiamondSize, 7);
1903                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1904                                                                                     backupMV.y + iDiamondSize, 8);
1905                                    break;
1906                            default:
1907                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1908                                                                                     1);
1909                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1910                                                                                     2);
1911                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1912                                                                                     3);
1913                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1914                                                                                     4);
1915    
1916                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1917                                                                                     backupMV.y - iDiamondSize, 5);
1918                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1919                                                                                     backupMV.y + iDiamondSize, 6);
1920                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1921                                                                                     backupMV.y - iDiamondSize, 7);
1922                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1923                                                                                     backupMV.y + iDiamondSize, 8);
1924                                    break;
1925                            }
1926                    }
1927            } else {
1928                    currMV->x = start_x;
1929                    currMV->y = start_y;
1930          }          }
1931          return iMinSAD;          return iMinSAD;
1932  }  }
1933    
1934  int32_t Halfpel8_Refine(  
1935          const uint8_t * const pRef,  
1936    
1937    
1938    int32_t
1939    Halfpel8_Refine_c(const uint8_t * const pRef,
1940          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1941          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1942          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1943          const uint8_t * const cur,          const uint8_t * const cur,
1944          const int x, const int y,                                  const int x,
1945                                    const int y,
1946          VECTOR * const currMV,          VECTOR * const currMV,
1947          int32_t iMinSAD,          int32_t iMinSAD,
1948          const VECTOR * const pmv,                             const int center_x,
1949          const int32_t min_dx, const int32_t max_dx,                             const int center_y,
1950          const int32_t min_dy, const int32_t max_dy,                                  const int32_t min_dx,
1951                                    const int32_t max_dx,
1952                                    const int32_t min_dy,
1953                                    const int32_t max_dy,
1954          const int32_t iFcode,          const int32_t iFcode,
1955          const int32_t iQuant,          const int32_t iQuant,
1956          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 1229  Line 1975 
1975    
1976  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1977    
1978  int32_t PMVfastSearch8(  int32_t
1979                                          const uint8_t * const pRef,  PMVfastSearch8(const uint8_t * const pRef,
1980                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1981                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1982                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1983                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1984                                          const int x, const int y,                             const int x,
1985                                          const int start_x, int start_y,                             const int y,
1986                               const int start_x,
1987                               const int start_y,
1988                                    const int center_x,
1989                                    const int center_y,
1990                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1991                               const uint32_t iQuant,
1992                               const uint32_t iFcode,
1993                                          const MBParam * const pParam,                                          const MBParam * const pParam,
1994                                          MACROBLOCK * const pMBs,                             const MACROBLOCK * const pMBs,
1995                               const MACROBLOCK * const prevMBs,
1996                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1997                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
1998  {  {
1999          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;  
2000          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
2001          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
2002          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 1264  Line 2014 
2014          int32_t psad[4];          int32_t psad[4];
2015          VECTOR newMV;          VECTOR newMV;
2016          VECTOR backupMV;          VECTOR backupMV;
2017            VECTOR startMV;
2018    
2019          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2020            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
2021    
2022          static int32_t threshA,threshB;           int32_t threshA, threshB;
2023          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
2024          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
2025    
2026          int32_t iSubBlock = ((y&1)<<1) + (x&1);          int32_t iSubBlock = (y & 1) + (y & 1) + (x & 1);
2027    
2028  /* Get maximum range */          MainSearch8FuncPtr MainSearchPtr;
         get_range(&min_dx, &max_dx, &min_dy, &max_dy,  
                   x, y, 8, iWidth, iHeight, iFcode);  
2029    
2030  /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */          /* Init variables */
2031            startMV.x = start_x;
2032            startMV.y = start_y;
2033    
2034          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          /* Get maximum range */
2035          { min_dx = EVEN(min_dx);          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2036                              iFcode);
2037    
2038            if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
2039                    min_dx = EVEN(min_dx);
2040          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
2041          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
2042          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
2043          }               /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          }
   
2044    
2045          bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
2046            //bPredEq = get_pmvdata(pMBs, (x >> 1), (y >> 1), iWcount, iSubBlock, pmv, psad);
2047            bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
2048    
2049          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
2050                  threshA =  512/4;                  threshA =  512/4;
2051                  threshB = 1024/4;                  threshB = 1024/4;
2052    
2053          }          } else {
2054          else                  threshA = psad[0] / 4;  /* good estimate? */
2055          {                  threshB = threshA + 256 / 4;
2056                  threshA = psad[0]/4;                    /* good estimate */                  if (threshA < 512 / 4)
2057                  threshB = threshA+256/4;                          threshA = 512 / 4;
2058                  if (threshA< 512/4) threshA =  512/4;                  if (threshA > 1024 / 4)
2059                  if (threshA>1024/4) threshA = 1024/4;                          threshA = 1024 / 4;
2060                  if (threshB>1792/4) threshB = 1792/4;                  if (threshB > 1792 / 4)
2061          }                          threshB = 1792 / 4;
2062            }
         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[iSubBlock]) ) )  
                 iFound=2;  
   
 /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  
    Otherwise select large Diamond Search.  
 */  
   
         if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536/4) || (bPredEq) )  
                 iDiamondSize=1; // 1 halfpel!  
         else  
                 iDiamondSize=2; // 2 halfpel = 1 full pixel!  
2063    
2064          if (!(MotionFlags & PMV_HALFPELDIAMOND8) )          iFound = 0;
                 iDiamondSize*=2;  
2065    
2066  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2067     MinSAD=SAD     MinSAD=SAD
# Line 1336  Line 2073 
2073    
2074  // Prepare for main loop  // Prepare for main loop
2075    
2076          currMV->x=start_x;              /* start with mv16 */    if (MotionFlags & PMV_USESQUARES8)
2077          currMV->y=start_y;        MainSearchPtr = Square8_MainSearch;
2078      else
2079    
2080            if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2081                    MainSearchPtr = AdvDiamond8_MainSearch;
2082            else
2083                    MainSearchPtr = Diamond8_MainSearch;
2084    
         iMinSAD = sad8( cur,  
                         get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),  
                         iEdgedWidth);  
         iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode) * iQuant;  
2085    
2086          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          *currMV = startMV;
2087          {  
2088            iMinSAD =
2089                    sad8(cur,
2090                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2091                                                    iEdgedWidth), iEdgedWidth);
2092            iMinSAD +=
2093                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2094                                             (uint8_t) iFcode, iQuant);
2095    
2096            if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))
2097                                                                    && ((int32_t) iMinSAD <
2098                                                                            prevMB->sad8[iSubBlock]))) {
2099                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2100                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2101                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
2102                          goto PMVfast8_Terminate_with_Refine;                          goto PMVfast8_Terminate_with_Refine;
2103          }          }
2104    
2105    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2106       vector of the median.
2107       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2108    */
2109    
2110            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[iSubBlock])))
2111                    iFound = 2;
2112    
2113    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2114       Otherwise select large Diamond Search.
2115    */
2116    
2117            if ((!MVzero(pmv[0])) || (threshB < 1536 / 4) || (bPredEq))
2118                    iDiamondSize = 1;               // 1 halfpel!
2119            else
2120                    iDiamondSize = 2;               // 2 halfpel = 1 full pixel!
2121    
2122            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2123                    iDiamondSize *= 2;
2124    
2125    
2126  /*  /*
2127     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.
2128     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
2129     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
2130     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
2131  */  */
2132    
2133  // the prediction might be even better than mv16  // the median prediction might be even better than mv16
         CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);  
2134    
2135  // (0,0) is always possible          if (!MVequal(pmv[0], startMV))
2136                    CHECK_MV8_CANDIDATE(center_x, center_y);
2137    
2138    // (0,0) if needed
2139            if (!MVzero(pmv[0]))
2140                    if (!MVzero(startMV))
2141          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
2142    
2143  // previous frame MV is always possible  // previous frame MV if needed
2144          CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);          if (!MVzero(prevMB->mvs[iSubBlock]))
2145                    if (!MVequal(prevMB->mvs[iSubBlock], startMV))
2146                            if (!MVequal(prevMB->mvs[iSubBlock], pmv[0]))
2147                                    CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,
2148                                                                            prevMB->mvs[iSubBlock].y);
2149    
2150            if ((iMinSAD <= threshA) ||
2151                    (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2152                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2153                    if (MotionFlags & PMV_QUICKSTOP16)
2154                            goto PMVfast8_Terminate_without_Refine;
2155                    if (MotionFlags & PMV_EARLYSTOP16)
2156                            goto PMVfast8_Terminate_with_Refine;
2157            }
2158    
2159  // left neighbour, if allowed  // left neighbour, if allowed and needed
2160          if (psad[1] != MV_MAX_ERROR)          if (!MVzero(pmv[1]))
2161          {                  if (!MVequal(pmv[1], startMV))
2162                  if (!(MotionFlags & PMV_HALFPEL8 ))                          if (!MVequal(pmv[1], prevMB->mvs[iSubBlock]))
2163                  {       pmv[1].x = EVEN(pmv[1].x);                                  if (!MVequal(pmv[1], pmv[0])) {
2164                                            if (!(MotionFlags & PMV_HALFPEL8)) {
2165                                                    pmv[1].x = EVEN(pmv[1].x);
2166                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
2167                  }                  }
2168                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
2169          }          }
2170    // top neighbour, if allowed and needed
2171  // top neighbour, if allowed          if (!MVzero(pmv[2]))
2172          if (psad[2] != MV_MAX_ERROR)                  if (!MVequal(pmv[2], startMV))
2173          {                          if (!MVequal(pmv[2], prevMB->mvs[iSubBlock]))
2174                  if (!(MotionFlags & PMV_HALFPEL8 ))                                  if (!MVequal(pmv[2], pmv[0]))
2175                  {       pmv[2].x = EVEN(pmv[2].x);                                          if (!MVequal(pmv[2], pmv[1])) {
2176                                                    if (!(MotionFlags & PMV_HALFPEL8)) {
2177                                                            pmv[2].x = EVEN(pmv[2].x);
2178                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
2179                  }                  }
2180                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
2181    
2182  // top right neighbour, if allowed  // top right neighbour, if allowed and needed
2183                  if (psad[3] != MV_MAX_ERROR)                                                  if (!MVzero(pmv[3]))
2184                  {                                                          if (!MVequal(pmv[3], startMV))
2185                          if (!(MotionFlags & PMV_HALFPEL8 ))                                                                  if (!MVequal(pmv[3], prevMB->mvs[iSubBlock]))
2186                          {       pmv[3].x = EVEN(pmv[3].x);                                                                          if (!MVequal(pmv[3], pmv[0]))
2187                                                                                    if (!MVequal(pmv[3], pmv[1]))
2188                                                                                            if (!MVequal(pmv[3], pmv[2])) {
2189                                                                                                    if (!
2190                                                                                                            (MotionFlags &
2191                                                                                                             PMV_HALFPEL8)) {
2192                                                                                                            pmv[3].x = EVEN(pmv[3].x);
2193                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
2194                          }                          }
2195                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                                  CHECK_MV8_CANDIDATE(pmv[3].x,
2196                                                                                                                                            pmv[3].y);
2197                  }                  }
2198          }          }
2199    
2200            if ((MVzero(*currMV)) &&
2201                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2202                    iMinSAD -= MV8_00_BIAS;
2203    
2204    
2205  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
2206     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.
2207  */  */
2208    
2209          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
2210          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2211                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2212                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2213                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2214                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1424  Line 2228 
2228          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2229    
2230  /* 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 */
2231          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2232                                           x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2233                                           currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2234                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2235                                                      iQuant, iFound);
2236    
2237          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2238                  *currMV = newMV;                  *currMV = newMV;
2239                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2240          }          }
2241    
2242          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2243  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
2244    
2245                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2246                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2247                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2248                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2249                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2250                                                                      iDiamondSize, iFcode, iQuant, iFound);
2251    
2252                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2253                          *currMV = newMV;                          *currMV = newMV;
2254                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2255                  }                  }
2256                  }                  }
2257    
2258                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2259                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2260                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2261                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2262                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2263                                                                      iQuant, iFound);
2264    
2265                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2266                          *currMV = newMV;                          *currMV = newMV;
2267                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2268                  }                  }
# Line 1472  Line 2275 
2275    
2276  PMVfast8_Terminate_with_Refine:  PMVfast8_Terminate_with_Refine:
2277          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2278                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2279                                                   x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2280                                                   currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2281                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2282    
2283    
2284  PMVfast8_Terminate_without_Refine:  PMVfast8_Terminate_without_Refine:
2285          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2286          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2287    
2288          return iMinSAD;          return iMinSAD;
2289  }  }
2290    
2291  int32_t EPZSSearch16(  int32_t
2292                                          const uint8_t * const pRef,  EPZSSearch16(const uint8_t * const pRef,
2293                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2294                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2295                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2296                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2297                                          const int x, const int y,                           const int x,
2298                             const int y,
2299                            const int start_x,
2300                            const int start_y,
2301                            const int center_x,
2302                            const int center_y,
2303                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2304                             const uint32_t iQuant,
2305                             const uint32_t iFcode,
2306                                          const MBParam * const pParam,                                          const MBParam * const pParam,
2307                                          MACROBLOCK * const pMBs,                           const MACROBLOCK * const pMBs,
2308                             const MACROBLOCK * const prevMBs,
2309                                          VECTOR * const currMV,                                          VECTOR * const currMV,
2310                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
2311  {  {
2312          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
2313          const uint32_t iHcount = pParam->mb_height;          const uint32_t iHcount = pParam->mb_height;
         const int32_t iFcode = pParam->fixed_code;  
         const int32_t iQuant = pParam->quant;  
2314    
2315          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
2316          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
# Line 1521  Line 2330 
2330          int32_t psad[8];          int32_t psad[8];
2331    
2332          static MACROBLOCK * oldMBs = NULL;          static MACROBLOCK * oldMBs = NULL;
2333          MACROBLOCK * const pMB = pMBs + x + y * iWcount;  
2334    //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
2335            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2336          MACROBLOCK * oldMB = NULL;          MACROBLOCK * oldMB = NULL;
2337    
2338          static int32_t thresh2;           int32_t thresh2;
2339          int32_t bPredEq;          int32_t bPredEq;
2340          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2341    
2342          MainSearch16FuncPtr EPZSMainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
2343    
2344          if (oldMBs == NULL)          if (oldMBs == NULL) {
2345          {       oldMBs = (MACROBLOCK*) calloc(1,iWcount*iHcount*sizeof(MACROBLOCK));                  oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
2346                  fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));  //      fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
2347          }          }
2348          oldMB = oldMBs + x + y * iWcount;          oldMB = oldMBs + x + y * iWcount;
2349    
2350  /* Get maximum range */  /* Get maximum range */
2351          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2352                          x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
   
 /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  
2353    
2354          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
2355          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2356            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2357            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2358            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2359          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2360            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2361          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
2362            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2363    
2364  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2365          MinSAD=SAD          MinSAD=SAD
# Line 1560  Line 2370 
2370    
2371  // Prepare for main loop  // Prepare for main loop
2372    
2373          *currMV=pmv[0];         /* current best := median prediction */          currMV->x = start_x;
2374          if (!(MotionFlags & PMV_HALFPEL16))          currMV->y = start_y;
2375          {  
2376            if (!(MotionFlags & PMV_HALFPEL16)) {
2377                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2378                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2379          }          }
# Line 1578  Line 2389 
2389    
2390  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2391    
2392          iMinSAD = sad16( cur,          iMinSAD =
2393                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
2394                  iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2395          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2396            iMinSAD +=
2397                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2398                                              (uint8_t) iFcode, iQuant);
2399    
2400  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2401          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )          if ((iMinSAD < 256) ||
2402                  {                  ((MVequal(*currMV, prevMB->mvs[0])) &&
2403                     ((int32_t) iMinSAD < prevMB->sad16))) {
2404                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2405                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2406                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1595  Line 2410 
2410  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2411    
2412  // previous frame MV  // previous frame MV
2413          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
2414    
2415  // set threshhold based on Min of Prediction and SAD of collocated block  // set threshhold based on Min of Prediction and SAD of collocated block
2416  // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want  // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
2417    
2418          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
2419                  thresh2 =  512;                  thresh2 =  512;
2420          }          } else {
         else  
         {  
2421  /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */  /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */
2422    
2423                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
# Line 1617  Line 2429 
2429    
2430    
2431  // left neighbour, if allowed  // left neighbour, if allowed
2432          if (x != 0)          if (x != 0) {
2433          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2434                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2435                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2436                  }                  }
2437                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
2438          }          }
   
2439  // top neighbour, if allowed  // top neighbour, if allowed
2440            if (y != 0) {
2441                    if (!(MotionFlags & PMV_HALFPEL16)) {
2442                            pmv[2].x = EVEN(pmv[2].x);
2443                            pmv[2].y = EVEN(pmv[2].y);
2444                    }
2445                    CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
2446    
2447    // top right neighbour, if allowed
2448                    if ((uint32_t) x != (iWcount - 1)) {
2449                            if (!(MotionFlags & PMV_HALFPEL16)) {
2450                                    pmv[3].x = EVEN(pmv[3].x);
2451                                    pmv[3].y = EVEN(pmv[3].y);
2452                            }
2453                            CHECK_MV16_CANDIDATE(pmv[3].x, pmv[3].y);
2454                    }
2455            }
2456    
2457    /* Terminate if MinSAD <= T_2
2458       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
2459    */
2460    
2461            if ((iMinSAD <= thresh2)
2462                    || (MVequal(*currMV, prevMB->mvs[0]) &&
2463                            ((int32_t) iMinSAD <= prevMB->sad16))) {
2464                    if (MotionFlags & PMV_QUICKSTOP16)
2465                            goto EPZS16_Terminate_without_Refine;
2466                    if (MotionFlags & PMV_EARLYSTOP16)
2467                            goto EPZS16_Terminate_with_Refine;
2468            }
2469    
2470    /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
2471    
2472            backupMV = prevMB->mvs[0];      // collocated MV
2473            backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x);     // acceleration X
2474            backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y);     // acceleration Y
2475    
2476            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y);
2477    
2478    // left neighbour
2479            if (x != 0)
2480                    CHECK_MV16_CANDIDATE((prevMB - 1)->mvs[0].x, (prevMB - 1)->mvs[0].y);
2481    
2482    // top neighbour
2483          if (y != 0)          if (y != 0)
2484                    CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,
2485                                                             (prevMB - iWcount)->mvs[0].y);
2486    
2487    // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
2488    
2489            if ((uint32_t) x != iWcount - 1)
2490                    CHECK_MV16_CANDIDATE((prevMB + 1)->mvs[0].x, (prevMB + 1)->mvs[0].y);
2491    
2492    // bottom neighbour, dito
2493            if ((uint32_t) y != iHcount - 1)
2494                    CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,
2495                                                             (prevMB + iWcount)->mvs[0].y);
2496    
2497    /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
2498            if (iMinSAD <= thresh2) {
2499                    if (MotionFlags & PMV_QUICKSTOP16)
2500                            goto EPZS16_Terminate_without_Refine;
2501                    if (MotionFlags & PMV_EARLYSTOP16)
2502                            goto EPZS16_Terminate_with_Refine;
2503            }
2504    
2505    /************ (if Diamond Search)  **************/
2506    
2507            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2508    
2509            if (MotionFlags & PMV_USESQUARES16)
2510                    MainSearchPtr = Square16_MainSearch;
2511            else
2512             if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2513                    MainSearchPtr = AdvDiamond16_MainSearch;
2514            else
2515                    MainSearchPtr = Diamond16_MainSearch;
2516    
2517    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2518    
2519            iSAD =
2520                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2521                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2522                                                      min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2523    
2524            if (iSAD < iMinSAD) {
2525                    *currMV = newMV;
2526                    iMinSAD = iSAD;
2527            }
2528    
2529    
2530            if (MotionFlags & PMV_EXTSEARCH16) {
2531    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2532    
2533                    if (!(MVequal(pmv[0], backupMV))) {
2534                            iSAD =
2535                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2536                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2537                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2538                                                                      2, iFcode, iQuant, 0);
2539                    }
2540    
2541                    if (iSAD < iMinSAD) {
2542                            *currMV = newMV;
2543                            iMinSAD = iSAD;
2544                    }
2545    
2546                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2547                            iSAD =
2548                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2549                                                                      iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2550                                                                      max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2551    
2552                            if (iSAD < iMinSAD) {
2553                                    *currMV = newMV;
2554                                    iMinSAD = iSAD;
2555                            }
2556                    }
2557            }
2558    
2559    /***************        Choose best MV found     **************/
2560    
2561      EPZS16_Terminate_with_Refine:
2562            if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
2563                    iMinSAD =
2564                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2565                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2566                                                             iFcode, iQuant, iEdgedWidth);
2567    
2568      EPZS16_Terminate_without_Refine:
2569    
2570            *oldMB = *prevMB;
2571    
2572            currPMV->x = currMV->x - center_x;
2573            currPMV->y = currMV->y - center_y;
2574            return iMinSAD;
2575    }
2576    
2577    
2578    int32_t
2579    EPZSSearch8(const uint8_t * const pRef,
2580                            const uint8_t * const pRefH,
2581                            const uint8_t * const pRefV,
2582                            const uint8_t * const pRefHV,
2583                            const IMAGE * const pCur,
2584                            const int x,
2585                            const int y,
2586                            const int start_x,
2587                            const int start_y,
2588                            const int center_x,
2589                            const int center_y,
2590                            const uint32_t MotionFlags,
2591                            const uint32_t iQuant,
2592                            const uint32_t iFcode,
2593                            const MBParam * const pParam,
2594                            const MACROBLOCK * const pMBs,
2595                            const MACROBLOCK * const prevMBs,
2596                            VECTOR * const currMV,
2597                            VECTOR * const currPMV)
2598          {          {
2599                  if (!(MotionFlags & PMV_HALFPEL16 ))  /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
2600                  {       pmv[2].x = EVEN(pmv[2].x);  
2601            const uint32_t iWcount = pParam->mb_width;
2602            const int32_t iWidth = pParam->width;
2603            const int32_t iHeight = pParam->height;
2604            const int32_t iEdgedWidth = pParam->edged_width;
2605    
2606            const uint8_t *cur = pCur->y + x * 8 + y * 8 * iEdgedWidth;
2607    
2608            int32_t iDiamondSize = 1;
2609    
2610            int32_t min_dx;
2611            int32_t max_dx;
2612            int32_t min_dy;
2613            int32_t max_dy;
2614    
2615            VECTOR newMV;
2616            VECTOR backupMV;
2617    
2618            VECTOR pmv[4];
2619            int32_t psad[8];
2620    
2621            const int32_t iSubBlock = ((y & 1) << 1) + (x & 1);
2622    
2623    //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2624            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
2625    
2626            int32_t bPredEq;
2627            int32_t iMinSAD, iSAD = 9999;
2628    
2629            MainSearch8FuncPtr MainSearchPtr;
2630    
2631    /* Get maximum range */
2632            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2633                              iFcode);
2634    
2635    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2636    
2637            if (!(MotionFlags & PMV_HALFPEL8)) {
2638                    min_dx = EVEN(min_dx);
2639                    max_dx = EVEN(max_dx);
2640                    min_dy = EVEN(min_dy);
2641                    max_dy = EVEN(max_dy);
2642            }
2643            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2644            //bPredEq = get_pmvdata(pMBs, x >> 1, y >> 1, iWcount, iSubBlock, pmv[0].x, pmv[0].y, psad);
2645            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2646    
2647    
2648    /* Step 4: Calculate SAD around the Median prediction.
2649            MinSAD=SAD
2650            If Motion Vector equal to Previous frame motion vector
2651                    and MinSAD<PrevFrmSAD goto Step 10.
2652            If SAD<=256 goto Step 10.
2653    */
2654    
2655    // Prepare for main loop
2656    
2657    
2658            if (!(MotionFlags & PMV_HALFPEL8)) {
2659                    currMV->x = EVEN(currMV->x);
2660                    currMV->y = EVEN(currMV->y);
2661            }
2662    
2663            if (currMV->x > max_dx)
2664                    currMV->x = max_dx;
2665            if (currMV->x < min_dx)
2666                    currMV->x = min_dx;
2667            if (currMV->y > max_dy)
2668                    currMV->y = max_dy;
2669            if (currMV->y < min_dy)
2670                    currMV->y = min_dy;
2671    
2672    /***************** This is predictor SET A: only median prediction ******************/
2673    
2674    
2675            iMinSAD =
2676                    sad8(cur,
2677                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2678                                                    iEdgedWidth), iEdgedWidth);
2679            iMinSAD +=
2680                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2681                                             (uint8_t) iFcode, iQuant);
2682    
2683    
2684    // thresh1 is fixed to 256
2685            if (iMinSAD < 256 / 4) {
2686                    if (MotionFlags & PMV_QUICKSTOP8)
2687                            goto EPZS8_Terminate_without_Refine;
2688                    if (MotionFlags & PMV_EARLYSTOP8)
2689                            goto EPZS8_Terminate_with_Refine;
2690            }
2691    
2692    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2693    
2694    
2695    // MV=(0,0) is often a good choice
2696            CHECK_MV8_ZERO;
2697    
2698    // previous frame MV
2699            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x, prevMB->mvs[iSubBlock].y);
2700    
2701    // left neighbour, if allowed
2702            if (psad[1] != MV_MAX_ERROR) {
2703                    if (!(MotionFlags & PMV_HALFPEL8)) {
2704                            pmv[1].x = EVEN(pmv[1].x);
2705                            pmv[1].y = EVEN(pmv[1].y);
2706                    }
2707                    CHECK_MV8_CANDIDATE(pmv[1].x, pmv[1].y);
2708            }
2709    // top neighbour, if allowed
2710            if (psad[2] != MV_MAX_ERROR) {
2711                    if (!(MotionFlags & PMV_HALFPEL8)) {
2712                            pmv[2].x = EVEN(pmv[2].x);
2713                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2714                  }                  }
2715                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x, pmv[2].y);
2716    
2717  // top right neighbour, if allowed  // top right neighbour, if allowed
2718                  if (x != (iWcount-1))                  if (psad[3] != MV_MAX_ERROR) {
2719                  {                          if (!(MotionFlags & PMV_HALFPEL8)) {
2720                          if (!(MotionFlags & PMV_HALFPEL16 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2721                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2722                          }                          }
2723                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV8_CANDIDATE(pmv[3].x, pmv[3].y);
2724                  }                  }
2725          }          }
2726    
2727    /*  // this bias is zero anyway, at the moment!
2728    
2729            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
2730                    iMinSAD -= MV8_00_BIAS;
2731    
2732    */
2733    
2734  /* Terminate if MinSAD <= T_2  /* Terminate if MinSAD <= T_2
2735     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
2736  */  */
2737    
2738          if ( (iMinSAD <= thresh2)          if (iMinSAD < 512 / 4) {        /* T_2 == 512/4 hardcoded */
2739                  || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD <= pMB->sad16) ) )                  if (MotionFlags & PMV_QUICKSTOP8)
2740                  {                          goto EPZS8_Terminate_without_Refine;
2741                          if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_EARLYSTOP8)
2742                                  goto EPZS16_Terminate_without_Refine;                          goto EPZS8_Terminate_with_Refine;
                         if (MotionFlags & PMV_EARLYSTOP16)  
                                 goto EPZS16_Terminate_with_Refine;  
2743                  }                  }
2744    
2745  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/  /************ (Diamond Search)  **************/
   
         backupMV = pMB->mvs[0];                 // last MV  
         backupMV.x += (pMB->mvs[0].x - oldMB->mvs[0].x );       // acceleration X  
         backupMV.y += (pMB->mvs[0].y - oldMB->mvs[0].y );       // acceleration Y  
   
         CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);  
   
 // left neighbour  
         if (x != 0)  
                 CHECK_MV16_CANDIDATE((oldMB-1)->mvs[0].x,oldMB->mvs[0].y);  
   
 // top neighbour  
         if (y != 0)  
                 CHECK_MV16_CANDIDATE((oldMB-iWcount)->mvs[0].x,oldMB->mvs[0].y);  
   
 // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs  
   
         if (x != iWcount-1)  
                 CHECK_MV16_CANDIDATE((pMB+1)->mvs[0].x,oldMB->mvs[0].y);  
2746    
2747  // bottom neighbour, dito          backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
         if (y != iHcount-1)  
                 CHECK_MV16_CANDIDATE((pMB+iWcount)->mvs[0].x,oldMB->mvs[0].y);  
2748    
2749  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */          if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2750          if (iMinSAD <= thresh2)                  iDiamondSize *= 2;
                 {  
                         if (MotionFlags & PMV_QUICKSTOP16)  
                                 goto EPZS16_Terminate_without_Refine;  
                         if (MotionFlags & PMV_EARLYSTOP16)  
                                 goto EPZS16_Terminate_with_Refine;  
                 }  
2751    
2752  /************ (if Diamond Search)  **************/  /* default: use best prediction as starting point for one call of EPZS_MainSearch */
2753    
2754          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */  // there is no EPZS^2 for inter4v at the moment
2755    
2756  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */    if (MotionFlags & PMV_USESQUARES8)
2757          MainSearchPtr = Square8_MainSearch;
2758      else
2759    
2760          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2761                  EPZSMainSearchPtr = Square16_MainSearch;                  MainSearchPtr = AdvDiamond8_MainSearch;
2762          else          else
2763                  EPZSMainSearchPtr = Diamond16_MainSearch;                  MainSearchPtr = Diamond8_MainSearch;
2764    
2765          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2766                          x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2767                          currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2768                          2, iFcode, iQuant, 0);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2769                                                      iQuant, 0);
2770    
2771          if (iSAD < iMinSAD)  
2772          {          if (iSAD < iMinSAD) {
2773                  *currMV = newMV;                  *currMV = newMV;
2774                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2775          }          }
2776    
2777            if (MotionFlags & PMV_EXTSEARCH8) {
         if (MotionFlags & PMV_EXTSEARCH16)  
         {  
2778  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2779    
2780                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2781                  {                          iSAD =
2782                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2783                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2784                                  pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2785                                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, 0);
                 }  
2786    
2787                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2788                          *currMV = newMV;                          *currMV = newMV;
2789                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2790                  }                  }
2791                    }
2792    
2793                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2794                  {                          iSAD =
2795                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2796                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2797                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2798                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, /*iDiamondSize*/ 2, iFcode, iQuant, 0);                                                                    iQuant, 0);
2799    
2800                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2801                                  *currMV = newMV;                                  *currMV = newMV;
2802                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2803                          }                          }
# Line 1751  Line 2806 
2806    
2807  /***************        Choose best MV found     **************/  /***************        Choose best MV found     **************/
2808    
2809  EPZS16_Terminate_with_Refine:    EPZS8_Terminate_with_Refine:
2810          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step
2811                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2812                                  x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2813                                  currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2814                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
   
 EPZS16_Terminate_without_Refine:  
2815    
2816          *oldMB = *pMB;    EPZS8_Terminate_without_Refine:
2817    
2818          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2819          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2820          return iMinSAD;          return iMinSAD;
2821  }  }
2822    
2823    
2824  int32_t EPZSSearch8(  
2825                                          const uint8_t * const pRef,  int32_t
2826    PMVfastIntSearch16(const uint8_t * const pRef,
2827                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2828                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2829                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2830                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2831                                          const int x, const int y,                                  const int x,
2832                                          const int start_x, const int start_y,                                  const int y,
2833                                    const int start_x,              /* start should be most likely vector */
2834                                    const int start_y,
2835                                    const int center_x,             /* center is from where length of MVs is measured */
2836                                    const int center_y,
2837                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2838                                    const uint32_t iQuant,
2839                                    const uint32_t iFcode,
2840                                          const MBParam * const pParam,                                          const MBParam * const pParam,
2841                                          MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
2842                                    const MACROBLOCK * const prevMBs,
2843                                          VECTOR * const currMV,                                          VECTOR * const currMV,
2844                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
2845  {  {
2846          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;  
   
2847          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
2848          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
2849          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
2850    
2851          const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;          const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
2852            const VECTOR zeroMV = { 0, 0 };
2853    
2854          int32_t iDiamondSize=1;          int32_t iDiamondSize;
2855    
2856          int32_t min_dx;          int32_t min_dx;
2857          int32_t max_dx;          int32_t max_dx;
2858          int32_t min_dy;          int32_t min_dy;
2859          int32_t max_dy;          int32_t max_dy;
2860    
2861            int32_t iFound;
2862    
2863          VECTOR newMV;          VECTOR newMV;
2864          VECTOR backupMV;          VECTOR backupMV;
2865    
2866          VECTOR pmv[4];          VECTOR pmv[4];
2867          int32_t psad[8];          int32_t psad[4];
2868    
2869          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);          MainSearch16FuncPtr MainSearchPtr;
2870    
2871          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2872            MACROBLOCK *const pMB = pMBs + x + y * iWcount;
2873    
2874            int32_t threshA, threshB;
2875          int32_t bPredEq;          int32_t bPredEq;
2876          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD, iSAD;
2877    
         MainSearch8FuncPtr EPZSMainSearchPtr;  
2878    
2879  /* Get maximum range */  /* Get maximum range */
2880          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2881                          x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2882    
2883  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2884    
2885          if (!(MotionFlags & PMV_HALFPEL8 ))          if ((x == 0) && (y == 0)) {
2886          { min_dx = EVEN(min_dx);                  threshA = 512;
2887            max_dx = EVEN(max_dx);                  threshB = 1024;
2888            min_dy = EVEN(min_dy);  
2889            max_dy = EVEN(max_dy);                  bPredEq = 0;
2890          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */                  psad[0] = psad[1] = psad[2] = psad[3] = 0;
2891                    *currMV = pmv[0] = pmv[1] = pmv[2] = pmv[3] = zeroMV;
2892    
2893            } else {
2894    
2895                    bPredEq = get_ipmvdata(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2896    
2897                    threshA = psad[0];
2898                    threshB = threshA + 256;
2899                    if (threshA < 512)
2900                            threshA = 512;
2901                    if (threshA > 1024)
2902                            threshA = 1024;
2903                    if (threshB > 1792)
2904                            threshB = 1792;
2905    
2906          bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);                  *currMV = pmv[0];                       /* current best := prediction */
2907            }
2908    
2909            iFound = 0;
2910    
2911  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2912          MinSAD=SAD          MinSAD=SAD
# Line 1837  Line 2915 
2915          If SAD<=256 goto Step 10.          If SAD<=256 goto Step 10.
2916  */  */
2917    
2918  // Prepare for main loop          if (currMV->x > max_dx) {
2919                    currMV->x = EVEN(max_dx);
2920            }
2921            if (currMV->x < min_dx) {
2922                    currMV->x = EVEN(min_dx);
2923            }
2924            if (currMV->y > max_dy) {
2925                    currMV->y = EVEN(max_dy);
2926            }
2927            if (currMV->y < min_dy) {
2928                    currMV->y = EVEN(min_dy);
2929            }
2930    
2931            iMinSAD =
2932                    sad16(cur,
2933                              get_iref_mv(pRef, x, y, 16, currMV,
2934                                                     iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2935            iMinSAD +=
2936                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2937                                              (uint8_t) iFcode, iQuant);
2938    
2939            if ((iMinSAD < 256) ||
2940                    ((MVequal(*currMV, prevMB->i_mvs[0])) &&
2941                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2942                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
2943                    {
2944                            if (!MVzero(*currMV)) {
2945                                    iMinSAD += MV16_00_BIAS;
2946                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
2947                                    iMinSAD -= MV16_00_BIAS;
2948                            }
2949                    }
2950    
2951          if (!(MotionFlags & PMV_HALFPEL8))                  if (MotionFlags & PMV_EARLYSTOP16)
2952          {                          goto PMVfastInt16_Terminate_with_Refine;
                 currMV->x = EVEN(currMV->x);  
                 currMV->y = EVEN(currMV->y);  
2953          }          }
2954    
         if (currMV->x > max_dx)  
                 currMV->x=max_dx;  
         if (currMV->x < min_dx)  
                 currMV->x=min_dx;  
         if (currMV->y > max_dy)  
                 currMV->y=max_dy;  
         if (currMV->y < min_dy)  
                 currMV->y=min_dy;  
2955    
2956  /***************** This is predictor SET A: only median prediction ******************/  /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2957       vector of the median.
2958       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2959    */
2960    
2961            if ((bPredEq) && (MVequal(pmv[0], prevMB->i_mvs[0])))
2962                    iFound = 2;
2963    
2964          iMinSAD = sad8( cur,  /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2965                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),     Otherwise select large Diamond Search.
2966                  iEdgedWidth);  */
         iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;  
2967    
2968            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
2969                    iDiamondSize = 2;               // halfpel units!
2970            else
2971                    iDiamondSize = 4;               // halfpel units!
2972    
2973  // thresh1 is fixed to 256  /*
2974          if (iMinSAD < 256/4 )     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
2975                  {     Also calculate (0,0) but do not subtract offset.
2976                          if (MotionFlags & PMV_QUICKSTOP8)     Let MinSAD be the smallest SAD up to this point.
2977                                  goto EPZS8_Terminate_without_Refine;     If MV is (0,0) subtract offset.
2978                          if (MotionFlags & PMV_EARLYSTOP8)  */
                                 goto EPZS8_Terminate_with_Refine;  
                 }  
2979    
2980  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  // (0,0) is often a good choice
2981    
2982  // previous frame MV          if (!MVzero(pmv[0]))
2983          CHECK_MV8_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);                  CHECK_MV16_ZERO;
2984    
2985  // MV=(0,0) is often a good choice  // previous frame MV is always possible
2986    
2987          CHECK_MV8_ZERO;          if (!MVzero(prevMB->i_mvs[0]))
2988                    if (!MVequal(prevMB->i_mvs[0], pmv[0]))
2989                            CHECK_MV16_CANDIDATE(prevMB->i_mvs[0].x, prevMB->i_mvs[0].y);
2990    
2991  /* Terminate if MinSAD <= T_2  // left neighbour, if allowed
2992     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]  
2993            if (!MVzero(pmv[1]))
2994                    if (!MVequal(pmv[1], prevMB->i_mvs[0]))
2995                            if (!MVequal(pmv[1], pmv[0]))
2996                                    CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
2997    
2998    // top neighbour, if allowed
2999            if (!MVzero(pmv[2]))
3000                    if (!MVequal(pmv[2], prevMB->i_mvs[0]))
3001                            if (!MVequal(pmv[2], pmv[0]))
3002                                    if (!MVequal(pmv[2], pmv[1]))
3003                                            CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
3004    
3005    // top right neighbour, if allowed
3006                                            if (!MVzero(pmv[3]))
3007                                                    if (!MVequal(pmv[3], prevMB->i_mvs[0]))
3008                                                            if (!MVequal(pmv[3], pmv[0]))
3009                                                                    if (!MVequal(pmv[3], pmv[1]))
3010                                                                            if (!MVequal(pmv[3], pmv[2]))
3011                                                                                    CHECK_MV16_CANDIDATE(pmv[3].x,
3012                                                                                                                             pmv[3].y);
3013    
3014            if ((MVzero(*currMV)) &&
3015                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
3016                    iMinSAD -= MV16_00_BIAS;
3017    
3018    
3019    /* Step 6: If MinSAD <= thresa goto Step 10.
3020       If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
3021  */  */
3022    
3023          if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */          if ((iMinSAD <= threshA) ||
3024                  {                  (MVequal(*currMV, prevMB->i_mvs[0]) &&
3025                          if (MotionFlags & PMV_QUICKSTOP8)                   ((int32_t) iMinSAD < prevMB->i_sad16))) {
3026                                  goto EPZS8_Terminate_without_Refine;  
3027                          if (MotionFlags & PMV_EARLYSTOP8)                  if (MotionFlags & PMV_EARLYSTOP16)
3028                                  goto EPZS8_Terminate_with_Refine;                          goto PMVfastInt16_Terminate_with_Refine;
3029                  }                  }
3030    
 /************ (if Diamond Search)  **************/  
3031    
3032          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */  /************ (Diamond Search)  **************/
3033    /*
3034       Step 7: Perform Diamond search, with either the small or large diamond.
3035       If Found=2 only examine one Diamond pattern, and afterwards goto step 10
3036       Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
3037       If center then goto step 10.
3038       Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
3039       Refine by using small diamond and goto step 10.
3040    */
3041    
3042          if (!(MotionFlags & PMV_HALFPELDIAMOND8))          if (MotionFlags & PMV_USESQUARES16)
3043                  iDiamondSize *= 2;                  MainSearchPtr = Square16_MainSearch;
3044            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
3045                    MainSearchPtr = AdvDiamond16_MainSearch;
3046            else
3047                    MainSearchPtr = Diamond16_MainSearch;
3048    
3049  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */          backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
3050    
 //      if (MotionFlags & PMV_USESQUARES8)  
 //              EPZSMainSearchPtr = Square8_MainSearch;  
 //      else  
                 EPZSMainSearchPtr = Diamond8_MainSearch;  
   
         iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,  
                 x, y,  
                 currMV->x, currMV->y, iMinSAD, &newMV,  
                 pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,  
                 iDiamondSize, iFcode, iQuant, 00);  
3051    
3052    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
3053            iSAD =
3054                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
3055                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
3056                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
3057                                                      iQuant, iFound);
3058    
3059          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
3060                  *currMV = newMV;                  *currMV = newMV;
3061                  iMinSAD = iSAD;                  iMinSAD = iSAD;
3062          }          }
3063    
3064          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH16) {
3065          {  /* extended: search (up to) two more times: orignal prediction and (0,0) */
 /* extended mode: search (up to) two more times: orignal prediction and (0,0) */  
3066    
3067                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
3068                  {                          iSAD =
3069                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
3070                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
3071                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
3072                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, iFound);
3073    
3074                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
3075                                  *currMV = newMV;                                  *currMV = newMV;
3076                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
3077                          }                          }
3078                  }                  }
3079    
3080                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
3081                  {                          iSAD =
3082                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
3083                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
3084                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
3085                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iQuant, iFound);
3086    
3087                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
3088                                  *currMV = newMV;                                  *currMV = newMV;
3089                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
3090                          }                          }
3091                  }                  }
3092          }          }
3093    
3094  /***************        Choose best MV found     **************/  /*
3095       Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.
3096    */
3097    
3098  EPZS8_Terminate_with_Refine:  PMVfastInt16_Terminate_with_Refine:
         if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step  
                 iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,  
                                 x, y,  
                                 currMV, iMinSAD,  
                                 pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);  
3099    
3100  EPZS8_Terminate_without_Refine:          pMB->i_mvs[0] = pMB->i_mvs[1] = pMB->i_mvs[2] = pMB->i_mvs[3] = pMB->i_mv16 = *currMV;
3101            pMB->i_sad8[0] = pMB->i_sad8[1] = pMB->i_sad8[2] = pMB->i_sad8[3] = pMB->i_sad16 = iMinSAD;
3102    
3103          currPMV->x = currMV->x - pmv[0].x;          if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
3104          currPMV->y = currMV->y - pmv[0].y;                  iMinSAD =
3105                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
3106                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
3107                                                             iFcode, iQuant, iEdgedWidth);
3108    
3109            pmv[0] = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          // get _REAL_ prediction (halfpel possible)
3110    
3111    PMVfastInt16_Terminate_without_Refine:
3112            currPMV->x = currMV->x - center_x;
3113            currPMV->y = currMV->y - center_y;
3114          return iMinSAD;          return iMinSAD;
3115  }  }
3116    
3117    
3118    
3119    /* ***********************************************************
3120            bvop motion estimation
3121    ***************************************************************/
3122    
3123    void
3124    MotionEstimationBVOP(MBParam * const pParam,
3125                                             FRAMEINFO * const frame,
3126                                             const int32_t time_bp,
3127                                             const int32_t time_pp,
3128                                             // forward (past) reference
3129                                             const MACROBLOCK * const f_mbs,
3130                                             const IMAGE * const f_ref,
3131                                             const IMAGE * const f_refH,
3132                                             const IMAGE * const f_refV,
3133                                             const IMAGE * const f_refHV,
3134                                             // backward (future) reference
3135                                             const MACROBLOCK * const b_mbs,
3136                                             const IMAGE * const b_ref,
3137                                             const IMAGE * const b_refH,
3138                                             const IMAGE * const b_refV,
3139                                             const IMAGE * const b_refHV)
3140    {
3141            const int mb_width = pParam->mb_width;
3142            const int mb_height = pParam->mb_height;
3143            const int edged_width = pParam->edged_width;
3144    
3145            const int32_t iWidth = pParam->width;
3146            const int32_t iHeight = pParam->height;
3147    
3148            int i, j, k;
3149    
3150            static const VECTOR zeroMV={0,0};
3151    
3152            int f_sad16;    /* forward (as usual) search */
3153            int b_sad16;    /* backward (only in b-frames) search */
3154            int i_sad16;    /* interpolated (both direction, b-frames only) */
3155            int d_sad16;    /* direct mode (assume almost linear motion) */
3156    
3157            int best_sad;
3158    
3159            VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/
3160            VECTOR f_interpolMV, b_interpolMV;
3161            VECTOR pmv_dontcare;
3162    
3163            int min_dx, max_dx, min_dy, max_dy;
3164            int f_min_dx, f_max_dx, f_min_dy, f_max_dy;
3165            int b_min_dx, b_max_dx, b_min_dy, b_max_dy;
3166    
3167            int f_count=0;
3168            int b_count=0;
3169            int i_count=0;
3170            int d_count=0;
3171    
3172            const int64_t TRB = (int32_t)time_pp - (int32_t)time_bp;
3173        const int64_t TRD = (int32_t)time_pp;
3174    
3175            // fprintf(stderr,"TRB = %lld  TRD = %lld  time_bp =%d time_pp =%d\n\n",TRB,TRD,time_bp,time_pp);
3176            // note: i==horizontal, j==vertical
3177            for (j = 0; j < mb_height; j++) {
3178    
3179                    f_predMV = zeroMV;      /* prediction is reset at left boundary */
3180                    b_predMV = zeroMV;
3181    
3182                    for (i = 0; i < mb_width; i++) {
3183                            MACROBLOCK *mb = &frame->mbs[i + j * mb_width];
3184                            const MACROBLOCK *f_mb = &f_mbs[i + j * mb_width];
3185                            const MACROBLOCK *b_mb = &b_mbs[i + j * mb_width];
3186    
3187                            mb->deltamv=zeroMV;
3188    
3189    /* special case, if collocated block is SKIPed: encoding is forward (0,0), cpb=0 without further ado */
3190    
3191                            if (b_mb->mode == MODE_INTER && b_mb->cbp == 0 &&
3192                                    b_mb->mvs[0].x == 0 && b_mb->mvs[0].y == 0) {
3193                                    mb->mode = MODE_NOT_CODED;
3194                                    mb->b_mvs[0] = mb->mvs[0] = zeroMV;
3195                                    continue;
3196                            }
3197    
3198                            if (b_mb->mode == MODE_INTER4V)
3199                            {
3200                                    d_sad16 = 0;
3201                            /* same method of scaling as in decoder.c, so we copy from there */
3202                        for (k = 0; k < 4; k++) {
3203    
3204                                            mb->directmv[k] = b_mb->mvs[k];
3205    
3206                                            mb->mvs[k].x = (int32_t) ((TRB * mb->directmv[k].x) / TRD + mb->deltamv.x);
3207                        mb->b_mvs[k].x = (int32_t) ((mb->deltamv.x == 0)
3208                                                                                    ? ((TRB - TRD) * mb->directmv[k].x) / TRD
3209                                                : mb->mvs[k].x - mb->directmv[k].x);
3210    
3211                        mb->mvs[k].y = (int32_t) ((TRB * mb->directmv[k].y) / TRD + mb->deltamv.y);
3212                            mb->b_mvs[k].y = (int32_t) ((mb->deltamv.y == 0)
3213                                                                                    ? ((TRB - TRD) * mb->directmv[k].y) / TRD
3214                                                : mb->mvs[k].y - mb->directmv[k].y);
3215    
3216                                            d_sad16 +=
3217                                                    sad8bi(frame->image.y + (2*i+(k&1))*8 + (2*j+(k>>1))*8*edged_width,
3218                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3219                                                                    (2*i+(k&1)), (2*j+(k>>1)), 8, &mb->mvs[k], edged_width),
3220                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3221                                                                    (2*i+(k&1)), (2*j+(k>>1)), 8, &mb->b_mvs[k], edged_width),
3222                                                      edged_width);
3223                                    }
3224                            }
3225                            else
3226                            {
3227                                    mb->directmv[3] = mb->directmv[2] = mb->directmv[1] =
3228                                            mb->directmv[0] = b_mb->mvs[0];
3229    
3230                                    mb->mvs[0].x = (int32_t) ((TRB * mb->directmv[0].x) / TRD + mb->deltamv.x);
3231                        mb->b_mvs[0].x = (int32_t) ((mb->deltamv.x == 0)
3232                                                                            ? ((TRB - TRD) * mb->directmv[0].x) / TRD
3233                                        : mb->mvs[0].x - mb->directmv[0].x);
3234    
3235                        mb->mvs[0].y = (int32_t) ((TRB * mb->directmv[0].y) / TRD + mb->deltamv.y);
3236                    mb->b_mvs[0].y = (int32_t) ((mb->directmv[0].y == 0)
3237                                                                            ? ((TRB - TRD) * mb->directmv[0].y) / TRD
3238                                        : mb->mvs[0].y - mb->directmv[0].y);
3239    
3240                                    d_sad16 = sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,
3241                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3242                                                                    i, j, 16, &mb->mvs[0], edged_width),
3243                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3244                                                                    i, j, 16, &mb->b_mvs[0], edged_width),
3245                                                      edged_width);
3246    
3247                }
3248                        d_sad16 += calc_delta_16(mb->deltamv.x, mb->deltamv.y, 1, frame->quant);
3249    
3250                            // forward search
3251                            f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3252                                                    &frame->image, i, j,
3253                                                    mb->mvs[0].x, mb->mvs[0].y,                     /* start point f_directMV */
3254                                                    f_predMV.x, f_predMV.y,                         /* center is f-prediction */
3255                                                    frame->motion_flags,
3256                                                    frame->quant, frame->fcode, pParam,
3257                                                    f_mbs, f_mbs,
3258                                                    &mb->mvs[0], &pmv_dontcare);
3259    
3260    
3261                            // backward search
3262                            b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3263                                                    &frame->image, i, j,
3264                                                    mb->b_mvs[0].x, mb->b_mvs[0].y,         /* start point b_directMV */
3265                                                    b_predMV.x, b_predMV.y,                         /* center is b-prediction */
3266                                                    frame->motion_flags,
3267                                                    frame->quant, frame->bcode, pParam,
3268                                                    b_mbs, b_mbs,
3269                                                    &mb->b_mvs[0], &pmv_dontcare);
3270    
3271                            i_sad16 =
3272                                    sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,
3273                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3274                                                                    i, j, 16, &mb->mvs[0], edged_width),
3275                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3276                                                                    i, j, 16, &mb->b_mvs[0], edged_width),
3277                                                      edged_width);
3278                        i_sad16 += calc_delta_16(mb->mvs[0].x-f_predMV.x, mb->mvs[0].y-f_predMV.y,
3279                                                                    frame->fcode, frame->quant);
3280                        i_sad16 += calc_delta_16(mb->b_mvs[0].x-b_predMV.x, mb->b_mvs[0].y-b_predMV.y,
3281                                                                    frame->bcode, frame->quant);
3282    
3283                            get_range(&f_min_dx, &f_max_dx, &f_min_dy, &f_max_dy, i, j, 16, iWidth, iHeight,
3284                              frame->fcode);
3285                            get_range(&b_min_dx, &b_max_dx, &b_min_dy, &b_max_dy, i, j, 16, iWidth, iHeight,
3286                              frame->bcode);
3287    
3288    /* Interpolated MC motion vector search, this is tedious and more complicated because there are
3289       two values for everything, always one for backward and one for forward ME. Still, we don't gain
3290       much from this search, maybe it should simply be skipped and simply current i_sad16 value used
3291       as "optimal". */
3292    
3293                            i_sad16 = Diamond16_InterpolMainSearch(
3294                                                    f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3295                                                    frame->image.y + i * 16 + j * 16 * edged_width,
3296                                                    b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3297                                                    i, j,
3298                                                    mb->mvs[0].x, mb->mvs[0].y,
3299                                                    mb->b_mvs[0].x, mb->b_mvs[0].y,
3300                                                    i_sad16,
3301                                                    &f_interpolMV, &b_interpolMV,
3302                                                    f_predMV.x, f_predMV.y, b_predMV.x, b_predMV.y,
3303                                                    f_min_dx, f_max_dx, f_min_dy, f_max_dy,
3304                                                    b_min_dx, b_max_dx, b_min_dy, b_max_dy,
3305                                                    edged_width,  2,
3306                                                    frame->fcode, frame->bcode,frame->quant,0);
3307    
3308                            i_sad16 = Diamond16_InterpolMainSearch(
3309                                                    f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3310                                                    frame->image.y + i * 16 + j * 16 * edged_width,
3311                                                    b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3312                                                    i, j,
3313                                                    f_interpolMV.x, f_interpolMV.y,
3314                                                    b_interpolMV.x, b_interpolMV.y,
3315                                                    i_sad16,
3316                                                    &f_interpolMV, &b_interpolMV,
3317                                                    f_predMV.x, f_predMV.y, b_predMV.x, b_predMV.y,
3318                                                    f_min_dx, f_max_dx, f_min_dy, f_max_dy,
3319                                                    b_min_dx, b_max_dx, b_min_dy, b_max_dy,
3320                                                    edged_width,  1,
3321                                                    frame->fcode, frame->bcode,frame->quant,0);             // equiv to halfpel refine
3322    
3323    
3324    /*  DIRECT MODE DELTA VECTOR SEARCH.
3325        This has to be made more effective, but at the moment I'm happy it's running at all */
3326    
3327    /* There are two range restrictions for direct mode: deltaMV is limited to [-32,31] in halfpel units, and
3328       absolute vector must not lie outside of image dimensions. Constraint one is dealt with by CHECK_MV16_DIRECT
3329       and for constraint two we need distance to boundary. This is done by get_range very large fcode (hack!) */
3330    
3331                            get_range(&min_dx, &max_dx, &min_dy, &max_dy, i, j, 16, iWidth, iHeight, 19);
3332    
3333                            d_sad16 = Diamond16_DirectMainSearch(
3334                                                    f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3335                                                    frame->image.y + i*16 + j*16*edged_width,
3336                                                    b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3337                                                    i, j,
3338                                                    TRB,TRD,
3339                                                    0,0,
3340                                                    d_sad16,
3341                                                    &mb->deltamv,
3342                                                    mb->directmv, // this has to be pre-initialized with b_mb->mvs[]
3343                                            min_dx, max_dx, min_dy, max_dy,
3344                                                    edged_width, 2, frame->quant, 0);
3345    
3346                            d_sad16 = Diamond16_DirectMainSearch(
3347                                                    f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3348                                                    frame->image.y + i*16 + j*16*edged_width,
3349                                                    b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3350                                                    i, j,
3351                                                    TRB,TRD,
3352                                                    mb->deltamv.x, mb->deltamv.y,
3353                                                    d_sad16,
3354                                                    &mb->deltamv,
3355                                                    mb->directmv, // this has to be pre-initialized with b_mb->mvs[]
3356                                            min_dx, max_dx, min_dy, max_dy,
3357                                                    edged_width, 1, frame->quant, 0);               // equiv to halfpel refine
3358    
3359    
3360    //                      i_sad16 = 65535;                /* remove the comment to disable any of the MODEs */
3361    //                      f_sad16 = 65535;
3362    //                      b_sad16 = 65535;
3363    //                      d_sad16 = 65535;
3364    
3365                            if (f_sad16 < b_sad16) {
3366                                    best_sad = f_sad16;
3367                                    mb->mode = MODE_FORWARD;
3368                            } else {
3369                                    best_sad = b_sad16;
3370                                    mb->mode = MODE_BACKWARD;
3371                            }
3372    
3373                            if (i_sad16 < best_sad) {
3374                                    best_sad = i_sad16;
3375                                    mb->mode = MODE_INTERPOLATE;
3376                            }
3377    
3378                            if (d_sad16 < best_sad) {
3379    
3380                                    if (b_mb->mode == MODE_INTER4V)
3381                                    {
3382    
3383                                    /* how to calc vectors is defined in standard. mvs[] and b_mvs[] are only for motion compensation */
3384                                    /* for the bitstream, the value mb->deltamv is read directly */
3385    
3386                                for (k = 0; k < 4; k++) {
3387    
3388                                                    mb->mvs[k].x = (int32_t) ((TRB * mb->directmv[k].x) / TRD + mb->deltamv.x);
3389                                mb->b_mvs[k].x = (int32_t) ((mb->deltamv.x == 0)
3390                                                                                            ? ((TRB - TRD) * mb->directmv[k].x) / TRD
3391                                                        : mb->mvs[k].x - mb->directmv[k].x);
3392    
3393                                mb->mvs[k].y = (int32_t) ((TRB * mb->directmv[k].y) / TRD + mb->deltamv.y);
3394                            mb->b_mvs[k].y = (int32_t) ((mb->deltamv.y == 0)
3395                                                                                            ? ((TRB - TRD) * mb->directmv[k].y) / TRD
3396                                                : mb->mvs[k].y - mb->directmv[k].y);
3397                                            }
3398                                    }
3399                                    else
3400                                    {
3401                                            mb->mvs[0].x = (int32_t) ((TRB * mb->directmv[0].x) / TRD + mb->deltamv.x);
3402    
3403                        mb->b_mvs[0].x = (int32_t) ((mb->deltamv.x == 0)
3404                                                                                    ? ((TRB - TRD) * mb->directmv[0].x) / TRD
3405                                            : mb->mvs[0].x - mb->directmv[0].x);
3406    
3407                                mb->mvs[0].y = (int32_t) ((TRB * mb->directmv[0].y) / TRD + mb->deltamv.y);
3408    
3409                            mb->b_mvs[0].y = (int32_t) ((mb->deltamv.y == 0)
3410                                                                                    ? ((TRB - TRD) * mb->directmv[0].y) / TRD
3411                                                : mb->mvs[0].y - mb->directmv[0].y);
3412    
3413                                            mb->mvs[3] = mb->mvs[2] = mb->mvs[1] = mb->mvs[0];
3414                                            mb->b_mvs[3] = mb->b_mvs[2] = mb->b_mvs[1] = mb->b_mvs[0];
3415                    }
3416    
3417                                    best_sad = d_sad16;
3418                                    mb->mode = MODE_DIRECT;
3419                            }
3420    
3421                            switch (mb->mode)
3422                            {
3423                                    case MODE_FORWARD:
3424                                            f_count++;
3425                                            f_predMV = mb->mvs[0];
3426                                            break;
3427                                    case MODE_BACKWARD:
3428                                            b_count++;
3429                                            b_predMV = mb->b_mvs[0];
3430    
3431                                            break;
3432                                    case MODE_INTERPOLATE:
3433                                            i_count++;
3434                                            mb->mvs[0] = f_interpolMV;
3435                                            mb->b_mvs[0] = b_interpolMV;
3436                                            f_predMV = mb->mvs[0];
3437                                            b_predMV = mb->b_mvs[0];
3438                                            break;
3439                                    case MODE_DIRECT:
3440                                            d_count++;
3441                                            break;
3442                                    default:
3443                                            break;
3444                            }
3445    
3446                    }
3447            }
3448    
3449    #ifdef _DEBUG_BFRAME_STAT
3450            fprintf(stderr,"B-Stat: F: %04d   B: %04d   I: %04d  D: %04d\n",
3451                                    f_count,b_count,i_count,d_count);
3452    #endif
3453    
3454    }

Legend:
Removed from v.115  
changed lines
  Added in v.370

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