[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 345, Sat Jul 27 23:47:01 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)
   
         VECTOR mv16;  
         VECTOR pmv16;  
   
         int32_t sad8 = 0;  
         int32_t sad16;  
         int32_t deviation;  
   
         if (sadInit);  
182                  (*sadInit)();                  (*sadInit)();
183    
184          // note: i==horizontal, j==vertical          for (y = 0; y < iHcount; y++)   {
185          for (i = 0; i < iHcount; i++)                  for (x = 0; x < iWcount; x ++)  {
                 for (j = 0; j < iWcount; j++)  
                 {  
                         MACROBLOCK *pMB = &pMBs[j + i * iWcount];  
186    
187                          sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                          MACROBLOCK *const pMB = &pMBs[x + y * iWcount];
                                          j, i, pParam->motion_flags,  
                                          pParam, pMBs, &mv16, &pmv16);  
                         pMB->sad16=sad16;  
188    
189                            predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
190    
191                          /* decide: MODE_INTER or MODE_INTRA                          pMB->sad16 =
192                             if (dev_intra < sad_inter - 2 * nb) use_intra                                  SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
193                          */                                                   x, y, predMV.x, predMV.y, predMV.x, predMV.y,
194                                                     current->motion_flags, current->quant,
195                                                     current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,
196                                                     &pMB->pmvs[0]);
197    
198                          deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width);                          if (0 < (pMB->sad16 - MV16_INTER_BIAS)) {
199                                    int32_t deviation;
200    
201                          if (deviation < (sad16 - INTER_BIAS))                                  deviation =
202                          {                                          dev16(pCurrent->y + x * 16 + y * 16 * pParam->edged_width,
203                                                      pParam->edged_width);
204    
205                                    if (deviation < (pMB->sad16 - MV16_INTER_BIAS)) {
206                                  pMB->mode = MODE_INTRA;                                  pMB->mode = MODE_INTRA;
207                                  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] =
208                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;                                                  pMB->mvs[3] = zeroMV;
209                                            pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
210                                                    pMB->sad8[3] = 0;
211    
212                                  iIntra++;                                  iIntra++;
213                                  if(iIntra >= iLimit)                                  if(iIntra >= iLimit)
# Line 373  Line 215 
215    
216                                  continue;                                  continue;
217                          }                          }
   
                         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];  
218                          }                          }
219    
220                            pmv = pMB->pmvs[0];
221                            if (current->global_flags & XVID_INTER4V)
222                                    if ((!(current->global_flags & XVID_LUMIMASKING) ||
223                                             pMB->dquant == NO_CHANGE)) {
224                                            int32_t sad8 = IMV16X16 * current->quant;
225    
226                                            if (sad8 < pMB->sad16) {
227                                                    sad8 += pMB->sad8[0] =
228                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
229                                                                            pCurrent, 2 * x, 2 * y,
230                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
231                                                                            current->motion_flags,
232                                                                            current->quant, current->fcode, pParam,
233                                                                            pMBs, prevMBs, &pMB->mvs[0],
234                                                                            &pMB->pmvs[0]);
235                                            }
236                                            if (sad8 < pMB->sad16) {
237    
238                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 1);
239                                                    sad8 += pMB->sad8[1] =
240                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
241                                                                            pCurrent, 2 * x + 1, 2 * y,
242                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
243                                                                            current->motion_flags,
244                                                                            current->quant, current->fcode, pParam,
245                                                                            pMBs, prevMBs, &pMB->mvs[1],
246                                                                            &pMB->pmvs[1]);
247                                            }
248                                            if (sad8 < pMB->sad16) {
249                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 2);
250                                                    sad8 += pMB->sad8[2] =
251                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
252                                                                            pCurrent, 2 * x, 2 * y + 1,
253                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
254                                                                            current->motion_flags,
255                                                                            current->quant, current->fcode, pParam,
256                                                                            pMBs, prevMBs, &pMB->mvs[2],
257                                                                            &pMB->pmvs[2]);
258                                            }
259                                            if (sad8 < pMB->sad16) {
260                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 3);
261                                                    sad8 += pMB->sad8[3] =
262                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
263                                                                            pCurrent, 2 * x + 1, 2 * y + 1,
264                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
265                                                                            current->motion_flags,
266                                                                            current->quant, current->fcode, pParam,
267                                                                            pMBs, prevMBs,
268                                                                            &pMB->mvs[3],
269                                                                            &pMB->pmvs[3]);
270                                            }
271    
272                          /* decide: MODE_INTER or MODE_INTER4V                          /* decide: MODE_INTER or MODE_INTER4V
273                             mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v                                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
274                          */                          */
275    
276                          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  
277                                          pMB->mode = MODE_INTER4V;                                          pMB->mode = MODE_INTER4V;
278                                                    pMB->sad8[0] *= 4;
279                                                    pMB->sad8[1] *= 4;
280                                                    pMB->sad8[2] *= 4;
281                                                    pMB->sad8[3] *= 4;
282                                                    continue;
283                          }                          }
284                          else  
285                          {                                  }
286                                  sad8 = sad16;  
287                                  pMB->mode = MODE_INTER;                                  pMB->mode = MODE_INTER;
288                                  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 */
289                                  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;
290                                  pMB->pmvs[0].x = pmv16.x;                          pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =
291                                  pMB->pmvs[0].y = pmv16.y;                                  pMB->sad16;
292                          }                          }
293                  }                  }
294    
295          return 0;          return 0;
296  }  }
297    
 #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )  
   
 #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )  
   
298    
299  #define CHECK_MV16_ZERO {\  #define CHECK_MV16_ZERO {\
300    if ( (0 <= max_dx) && (0 >= min_dx) \    if ( (0 <= max_dx) && (0 >= min_dx) \
301      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
302    { \    { \
303      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); \
304      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; \  
305      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
306      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
307  }  }
308    
309  #define NOCHECK_MV16_CANDIDATE(X,Y) { \  #define NOCHECK_MV16_CANDIDATE(X,Y) { \
310      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); \
311      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);\
312      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
313      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
314  }  }
# Line 457  Line 318 
318      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
319    { \    { \
320      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); \
321      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);\
322      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
323      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
324  }  }
# Line 467  Line 328 
328      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
329    { \    { \
330      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); \
331      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);\
332      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
333      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
334  }  }
# Line 477  Line 338 
338      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
339    { \    { \
340      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); \
341      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);\
342      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
343      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
344  }  }
# Line 485  Line 346 
346    
347  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
348    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); \
349    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);\
350    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
351    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
352  }  }
# Line 493  Line 354 
354  #define NOCHECK_MV8_CANDIDATE(X,Y) \  #define NOCHECK_MV8_CANDIDATE(X,Y) \
355    { \    { \
356      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); \
357      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);\
358      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
359      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
360  }  }
# Line 503  Line 364 
364      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
365    { \    { \
366      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); \
367      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);\
368      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
369      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
370  }  }
# Line 513  Line 374 
374      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
375    { \    { \
376      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); \
377      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);\
378      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
379      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
380  }  }
# Line 523  Line 384 
384      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
385    { \    { \
386      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); \
387      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);\
388      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
389      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
390  }  }
# Line 538  Line 399 
399                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
400                                          const int x, const int y,                                          const int x, const int y,
401                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
402                                            const uint32_t iQuant,
403                                            const uint32_t iFcode,
404                                          MBParam * const pParam,                                          MBParam * const pParam,
405                                          MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
406                                            const MACROBLOCK * const prevMBs,
407                                          VECTOR * const currMV,                                          VECTOR * const currMV,
408                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
409  {  {
410          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
         const int32_t iQuant = pParam->quant;  
411          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
412          int32_t iSAD;          int32_t iSAD;
413          int32_t pred_x,pred_y;          VECTOR pred;
414    
415          get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);  
416            pred = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
417    
418          iSAD = sad16( cur,          iSAD = sad16( cur,
419                  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 423 
423    
424          currMV->x = 0;          currMV->x = 0;
425          currMV->y = 0;          currMV->y = 0;
426          currPMV->x = -pred_x;          currPMV->x = -pred.x;
427          currPMV->y = -pred_y;          currPMV->y = -pred.y;
428    
429          return iSAD;          return iSAD;
430    
431  }  }
432  */  */
433    
434  int32_t Diamond16_MainSearch(  int32_t
435          const uint8_t * const pRef,  Diamond16_MainSearch(const uint8_t * const pRef,
436          const uint8_t * const pRefH,          const uint8_t * const pRefH,
437          const uint8_t * const pRefV,          const uint8_t * const pRefV,
438          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
439          const uint8_t * const cur,          const uint8_t * const cur,
440          const int x, const int y,                                           const int x,
441          int32_t startx, int32_t starty,                                           const int y,
442          int32_t iMinSAD,                                     const int start_x,
443                                       const int start_y,
444                                       int iMinSAD,
445          VECTOR * const currMV,          VECTOR * const currMV,
446          const VECTOR * const pmv,                                     const int center_x,
447          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
448          const int32_t min_dy, const int32_t max_dy,                                           const int32_t min_dx,
449                                             const int32_t max_dx,
450                                             const int32_t min_dy,
451                                             const int32_t max_dy,
452          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
453          const int32_t iDiamondSize,          const int32_t iDiamondSize,
454          const int32_t iFcode,          const int32_t iFcode,
# Line 589  Line 458 
458  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
459    
460          int32_t iDirection=0;          int32_t iDirection=0;
461            int32_t iDirectionBackup;
462          int32_t iSAD;          int32_t iSAD;
463          VECTOR backupMV;          VECTOR backupMV;
464          backupMV.x = startx;  
465          backupMV.y = starty;          backupMV.x = start_x;
466            backupMV.y = start_y;
467    
468  /* 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 */
469    
# Line 601  Line 472 
472          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
473          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
474    
475          if (iDirection)          if (iDirection) {
476                  while (!iFound)                  while (!iFound) {
                 {  
477                          iFound = 1;                          iFound = 1;
478                          backupMV=*currMV;                          backupMV=*currMV;
479                            iDirectionBackup = iDirection;
480    
481                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
482                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
483                          if ( iDirection != 1)                                                                                     backupMV.y, 1);
484                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
485                          if ( iDirection != 4)                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
486                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                     backupMV.y, 2);
487                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
488                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
489                                                                                       backupMV.y - iDiamondSize, 3);
490                            if (iDirectionBackup != 3)
491                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
492                                                                                       backupMV.y + iDiamondSize, 4);
493                  }                  }
494          else          } else {
495          {                  currMV->x = start_x;
496                  currMV->x = startx;                  currMV->y = start_y;
                 currMV->y = starty;  
497          }          }
498          return iMinSAD;          return iMinSAD;
499  }  }
500    
501  int32_t Square16_MainSearch(  int32_t
502                                          const uint8_t * const pRef,  Square16_MainSearch(const uint8_t * const pRef,
503                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
504                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
505                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
506                                          const uint8_t * const cur,                                          const uint8_t * const cur,
507                                          const int x, const int y,                                          const int x,
508                                          int32_t startx, int32_t starty,                                          const int y,
509                                          int32_t iMinSAD,                                     const int start_x,
510                                       const int start_y,
511                                       int iMinSAD,
512                                          VECTOR * const currMV,                                          VECTOR * const currMV,
513                                          const VECTOR * const pmv,                                     const int center_x,
514                                          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
515                                          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
516                                            const int32_t max_dx,
517                                            const int32_t min_dy,
518                                            const int32_t max_dy,
519                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
520                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
521                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 648  Line 527 
527          int32_t iDirection=0;          int32_t iDirection=0;
528          int32_t iSAD;          int32_t iSAD;
529          VECTOR backupMV;          VECTOR backupMV;
530          backupMV.x = startx;  
531          backupMV.y = starty;          backupMV.x = start_x;
532            backupMV.y = start_y;
533    
534  /* 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 */
535    
# Line 664  Line 544 
544          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
545          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
546    
547          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
548          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                           backupMV.y - iDiamondSize, 5);
549          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
550          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                                           backupMV.y + iDiamondSize, 6);
551            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
552                                                             backupMV.y - iDiamondSize, 7);
553            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
554                                                             backupMV.y + iDiamondSize, 8);
555    
556    
557          if (iDirection)          if (iDirection) {
558                  while (!iFound)                  while (!iFound) {
                 {  
559                          iFound = 1;                          iFound = 1;
560                          backupMV=*currMV;                          backupMV=*currMV;
561    
562                          switch (iDirection)                          switch (iDirection) {
                         {  
563                                  case 1:                                  case 1:
564                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
565                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                     backupMV.y, 1);
566                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
567                                                                                     backupMV.y - iDiamondSize, 5);
568                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
569                                                                                     backupMV.y - iDiamondSize, 7);
570                                          break;                                          break;
571                                  case 2:                                  case 2:
572                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
573                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   2);
574                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
575                                                                                     backupMV.y + iDiamondSize, 6);
576                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
577                                                                                     backupMV.y + iDiamondSize, 8);
578                                          break;                                          break;
579    
580                                  case 3:                                  case 3:
581                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
582                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
583                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
584                                                                                     backupMV.y - iDiamondSize, 7);
585                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
586                                                                                     backupMV.y + iDiamondSize, 8);
587                                          break;                                          break;
588    
589                                  case 4:                                  case 4:
590                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
591                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
592                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
593                                                                                     backupMV.y - iDiamondSize, 5);
594                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
595                                                                                     backupMV.y + iDiamondSize, 6);
596                                          break;                                          break;
597    
598                                  case 5:                                  case 5:
599                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
600                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   1);
601                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
602                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   3);
603                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
604                                                                                     backupMV.y - iDiamondSize, 5);
605                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
606                                                                                     backupMV.y + iDiamondSize, 6);
607                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
608                                                                                     backupMV.y - iDiamondSize, 7);
609                                          break;                                          break;
610    
611                                  case 6:                                  case 6:
612                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
613                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   2);
614                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
615                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
616                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);  
617                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
618                                                                                     backupMV.y - iDiamondSize, 5);
619                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
620                                                                                     backupMV.y + iDiamondSize, 6);
621                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
622                                                                                     backupMV.y + iDiamondSize, 8);
623    
624                                          break;                                          break;
625    
626                                  case 7:                                  case 7:
627                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
628                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                     backupMV.y, 1);
629                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
630                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
631                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
632                                                                                     backupMV.y - iDiamondSize, 5);
633                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
634                                                                                     backupMV.y - iDiamondSize, 7);
635                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
636                                                                                     backupMV.y + iDiamondSize, 8);
637                                          break;                                          break;
638    
639                                  case 8:                                  case 8:
640                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
641                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
642                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
643                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
644                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
645                                                                                     backupMV.y + iDiamondSize, 6);
646                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
647                                                                                     backupMV.y - iDiamondSize, 7);
648                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
649                                                                                     backupMV.y + iDiamondSize, 8);
650                                          break;                                          break;
651                          default:                          default:
652                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
653                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                                                                   1);
654                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
655                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
656                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
657                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
658                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
659                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
660                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);  
661                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
662                                                                                     backupMV.y - iDiamondSize, 5);
663                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
664                                                                                     backupMV.y + iDiamondSize, 6);
665                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
666                                                                                     backupMV.y - iDiamondSize, 7);
667                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
668                                                                                     backupMV.y + iDiamondSize, 8);
669                                          break;                                          break;
670                          }                          }
671                  }                  }
672          else          } else {
673                  {                  currMV->x = start_x;
674                          currMV->x = startx;                  currMV->y = start_y;
                         currMV->y = starty;  
675                  }                  }
676          return iMinSAD;          return iMinSAD;
677  }  }
678    
679    
680  int32_t Full16_MainSearch(  int32_t
681                                          const uint8_t * const pRef,  Full16_MainSearch(const uint8_t * const pRef,
682                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
683                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
684                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
685                                          const uint8_t * const cur,                                          const uint8_t * const cur,
686                                          const int x, const int y,                                    const int x,
687                                          int32_t startx, int32_t starty,                                    const int y,
688                                          int32_t iMinSAD,                                     const int start_x,
689                                       const int start_y,
690                                       int iMinSAD,
691                                          VECTOR * const currMV,                                          VECTOR * const currMV,
692                                          const VECTOR * const pmv,                                     const int center_x,
693                                          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
694                                          const int32_t min_dy, const int32_t max_dy,                                    const int32_t min_dx,
695                                      const int32_t max_dx,
696                                      const int32_t min_dy,
697                                      const int32_t max_dy,
698                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
699                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
700                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 778  Line 704 
704          int32_t iSAD;          int32_t iSAD;
705          int32_t dx,dy;          int32_t dx,dy;
706          VECTOR backupMV;          VECTOR backupMV;
707          backupMV.x = startx;  
708          backupMV.y = starty;          backupMV.x = start_x;
709            backupMV.y = start_y;
710    
711          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
712                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
# Line 788  Line 715 
715          return iMinSAD;          return iMinSAD;
716  }  }
717    
718  int32_t Full8_MainSearch(  int32_t
719                                          const uint8_t * const pRef,  AdvDiamond16_MainSearch(const uint8_t * const pRef,
720                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
721                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
722                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
723                                          const uint8_t * const cur,                                          const uint8_t * const cur,
724                                          const int x, const int y,                                                  const int x,
725                                          int32_t startx, int32_t starty,                                                  const int y,
726                                          int32_t iMinSAD,                                             int start_x,
727                                               int start_y,
728                                               int iMinSAD,
729                                          VECTOR * const currMV,                                          VECTOR * const currMV,
730                                          const VECTOR * const pmv,                                             const int center_x,
731                                          const int32_t min_dx, const int32_t max_dx,                                             const int center_y,
732                                          const int32_t min_dy, const int32_t max_dy,                                                  const int32_t min_dx,
733                                                    const int32_t max_dx,
734                                                    const int32_t min_dy,
735                                                    const int32_t max_dy,
736                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
737                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
738                                          const int32_t iFcode,                                          const int32_t iFcode,
739                                          const int32_t iQuant,                                          const int32_t iQuant,
740                                          int iFound)                                                  int iDirection)
741  {  {
742    
743          int32_t iSAD;          int32_t iSAD;
         int32_t dx,dy;  
         VECTOR backupMV;  
         backupMV.x = startx;  
         backupMV.y = starty;  
744    
745          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);  
746    
747          return iMinSAD;          if (iDirection) {
748  }                  CHECK_MV16_CANDIDATE(start_x - iDiamondSize, start_y);
749                    CHECK_MV16_CANDIDATE(start_x + iDiamondSize, start_y);
750                    CHECK_MV16_CANDIDATE(start_x, start_y - iDiamondSize);
751                    CHECK_MV16_CANDIDATE(start_x, start_y + iDiamondSize);
752            } else {
753                    int bDirection = 1 + 2 + 4 + 8;
754    
755                    do {
756                            iDirection = 0;
757                            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)
758                                    CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
759    
760                            if (bDirection & 2)
761                                    CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
762    
763  int32_t Halfpel16_Refine(                          if (bDirection & 4)
764          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) */  
765    
766          int32_t iSAD;                          if (bDirection & 8)
767          VECTOR backupMV = *currMV;                                  CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
768    
769          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);  
770    
771          return iMinSAD;                          if (iDirection)         //checking if anything found
772                            {
773                                    bDirection = iDirection;
774                                    iDirection = 0;
775                                    start_x = currMV->x;
776                                    start_y = currMV->y;
777                                    if (bDirection & 3)     //our candidate is left or right
778                                    {
779                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
780                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
781                                    } else                  // what remains here is up or down
782                                    {
783                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
784                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
785  }  }
786    
787  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)                                  if (iDirection) {
788                                            bDirection += iDirection;
789                                            start_x = currMV->x;
790  int32_t PMVfastSearch16(                                          start_y = currMV->y;
791                                          const uint8_t * const pRef,                                  }
792                                          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)  
793  {  {
794          const uint32_t iWcount = pParam->mb_width;                                  switch (bDirection) {
795          const int32_t iFcode = pParam->fixed_code;                                  case 2:
796          const int32_t iQuant = pParam->quant;                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
797          const int32_t iWidth = pParam->width;                                                                                           start_y - iDiamondSize, 2 + 4);
798          const int32_t iHeight = pParam->height;                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
799                                                                                             start_y + iDiamondSize, 2 + 8);
800                                            break;
801                                    case 1:
802    
803                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
804                                                                                             start_y - iDiamondSize, 1 + 4);
805                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
806                                                                                             start_y + iDiamondSize, 1 + 8);
807                                            break;
808                                    case 2 + 4:
809                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
810                                                                                             start_y - iDiamondSize, 1 + 4);
811                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
812                                                                                             start_y - iDiamondSize, 2 + 4);
813                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
814                                                                                             start_y + iDiamondSize, 2 + 8);
815                                            break;
816                                    case 4:
817                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
818                                                                                             start_y - iDiamondSize, 2 + 4);
819                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
820                                                                                             start_y - iDiamondSize, 1 + 4);
821                                            break;
822                                    case 8:
823                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
824                                                                                             start_y + iDiamondSize, 2 + 8);
825                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
826                                                                                             start_y + iDiamondSize, 1 + 8);
827                                            break;
828                                    case 1 + 4:
829                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
830                                                                                             start_y + iDiamondSize, 1 + 8);
831                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
832                                                                                             start_y - iDiamondSize, 1 + 4);
833                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
834                                                                                             start_y - iDiamondSize, 2 + 4);
835                                            break;
836                                    case 2 + 8:
837                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
838                                                                                             start_y - iDiamondSize, 1 + 4);
839                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
840                                                                                             start_y + iDiamondSize, 1 + 8);
841                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
842                                                                                             start_y + iDiamondSize, 2 + 8);
843                                            break;
844                                    case 1 + 8:
845                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
846                                                                                             start_y - iDiamondSize, 2 + 4);
847                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
848                                                                                             start_y + iDiamondSize, 2 + 8);
849                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
850                                                                                             start_y + iDiamondSize, 1 + 8);
851                                            break;
852                                    default:                //1+2+4+8 == we didn't find anything at all
853                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
854                                                                                             start_y - iDiamondSize, 1 + 4);
855                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
856                                                                                             start_y + iDiamondSize, 1 + 8);
857                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
858                                                                                             start_y - iDiamondSize, 2 + 4);
859                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
860                                                                                             start_y + iDiamondSize, 2 + 8);
861                                            break;
862                                    }
863                                    if (!iDirection)
864                                            break;          //ok, the end. really
865                                    else {
866                                            bDirection = iDirection;
867                                            start_x = currMV->x;
868                                            start_y = currMV->y;
869                                    }
870                            }
871                    }
872                    while (1);                              //forever
873            }
874            return iMinSAD;
875    }
876    
877    
878    #define CHECK_MV16_F_INTERPOL(X,Y,BX,BY) { \
879      if ( ((X) <= max_dx) && ((X) >= min_dx) \
880        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
881      { \
882        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
883        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
884        if (iSAD < iMinSAD) \
885        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
886    }
887    
888    #define CHECK_MV16_F_INTERPOL_DIR(X,Y,BX,BY,D) { \
889      if ( ((X) <= max_dx) && ((X) >= min_dx) \
890        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
891      { \
892        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
893        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
894        if (iSAD < iMinSAD) \
895        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
896    }
897    
898    #define CHECK_MV16_F_INTERPOL_FOUND(X,Y,BX,BY,D) { \
899      if ( ((X) <= max_dx) && ((X) >= min_dx) \
900        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
901      { \
902        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
903        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
904        if (iSAD < iMinSAD) \
905        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
906    }
907    
908    
909    #define CHECK_MV16_B_INTERPOL(FX,FY,X,Y) { \
910      if ( ((X) <= max_dx) && ((X) >= min_dx) \
911        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
912      { \
913        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
914        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
915        if (iSAD < iMinSAD) \
916        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
917    }
918    
919    
920    #define CHECK_MV16_B_INTERPOL_DIR(FX,FY,X,Y,D) { \
921      if ( ((X) <= max_dx) && ((X) >= min_dx) \
922        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
923      { \
924        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
925        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
926        if (iSAD < iMinSAD) \
927        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
928    }
929    
930    
931    #define CHECK_MV16_B_INTERPOL_FOUND(FX,FY,X,Y,D) { \
932      if ( ((X) <= max_dx) && ((X) >= min_dx) \
933        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
934      { \
935        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
936        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
937        if (iSAD < iMinSAD) \
938        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
939    }
940    
941    
942    #if (0==1)
943    int32_t
944    Diamond16_InterpolMainSearch(
945                                            const uint8_t * const f_pRef,
946                                             const uint8_t * const f_pRefH,
947                                             const uint8_t * const f_pRefV,
948                                             const uint8_t * const f_pRefHV,
949                                             const uint8_t * const cur,
950    
951                                            const uint8_t * const b_pRef,
952                                             const uint8_t * const b_pRefH,
953                                             const uint8_t * const b_pRefV,
954                                             const uint8_t * const b_pRefHV,
955    
956                                             const int x,
957                                             const int y,
958    
959                                       const int f_start_x,
960                                       const int f_start_y,
961                                       const int b_start_x,
962                                       const int b_start_y,
963    
964                                       int iMinSAD,
965                                       VECTOR * const f_currMV,
966                                       VECTOR * const b_currMV,
967    
968                                       const int f_center_x,
969                                       const int f_center_y,
970                                       const int b_center_x,
971                                       const int b_center_y,
972    
973                                             const int32_t min_dx,
974                                             const int32_t max_dx,
975                                             const int32_t min_dy,
976                                             const int32_t max_dy,
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 f_iDirection = 0;
989            int32_t b_iDirection = 0;
990            int32_t iSAD;
991    
992            VECTOR f_backupMV;
993            VECTOR b_backupMV;
994    
995            f_backupMV.x = start_x;
996            f_backupMV.y = start_y;
997            b_backupMV.x = start_x;
998            b_backupMV.y = start_y;
999    
1000    /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1001    
1002            CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1003            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1004            CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1005            CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1006    
1007            if (iDirection)
1008                    while (!iFound) {
1009                            iFound = 1;
1010                            backupMV = *currMV;
1011    
1012                            if (iDirection != 2)
1013                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1014                                                                                       backupMV.y, 1);
1015                            if (iDirection != 1)
1016                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1017                                                                                       backupMV.y, 2);
1018                            if (iDirection != 4)
1019                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
1020                                                                                       backupMV.y - iDiamondSize, 3);
1021                            if (iDirection != 3)
1022                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
1023                                                                                       backupMV.y + iDiamondSize, 4);
1024            } else {
1025                    currMV->x = start_x;
1026                    currMV->y = start_y;
1027            }
1028            return iMinSAD;
1029    }
1030    #endif
1031    
1032    
1033    int32_t
1034    AdvDiamond8_MainSearch(const uint8_t * const pRef,
1035                                               const uint8_t * const pRefH,
1036                                               const uint8_t * const pRefV,
1037                                               const uint8_t * const pRefHV,
1038                                               const uint8_t * const cur,
1039                                               const int x,
1040                                               const int y,
1041                                               int start_x,
1042                                               int start_y,
1043                                               int iMinSAD,
1044                                               VECTOR * const currMV,
1045                                               const int center_x,
1046                                               const int center_y,
1047                                               const int32_t min_dx,
1048                                               const int32_t max_dx,
1049                                               const int32_t min_dy,
1050                                               const int32_t max_dy,
1051                                               const int32_t iEdgedWidth,
1052                                               const int32_t iDiamondSize,
1053                                               const int32_t iFcode,
1054                                               const int32_t iQuant,
1055                                               int iDirection)
1056    {
1057    
1058            int32_t iSAD;
1059    
1060    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
1061    
1062            if (iDirection) {
1063                    CHECK_MV8_CANDIDATE(start_x - iDiamondSize, start_y);
1064                    CHECK_MV8_CANDIDATE(start_x + iDiamondSize, start_y);
1065                    CHECK_MV8_CANDIDATE(start_x, start_y - iDiamondSize);
1066                    CHECK_MV8_CANDIDATE(start_x, start_y + iDiamondSize);
1067            } else {
1068                    int bDirection = 1 + 2 + 4 + 8;
1069    
1070                    do {
1071                            iDirection = 0;
1072                            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)
1073                                    CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1074    
1075                            if (bDirection & 2)
1076                                    CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1077    
1078                            if (bDirection & 4)
1079                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1080    
1081                            if (bDirection & 8)
1082                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1083    
1084                            /* now we're doing diagonal checks near our candidate */
1085    
1086                            if (iDirection)         //checking if anything found
1087                            {
1088                                    bDirection = iDirection;
1089                                    iDirection = 0;
1090                                    start_x = currMV->x;
1091                                    start_y = currMV->y;
1092                                    if (bDirection & 3)     //our candidate is left or right
1093                                    {
1094                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1095                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1096                                    } else                  // what remains here is up or down
1097                                    {
1098                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1099                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1100                                    }
1101    
1102                                    if (iDirection) {
1103                                            bDirection += iDirection;
1104                                            start_x = currMV->x;
1105                                            start_y = currMV->y;
1106                                    }
1107                            } else                          //about to quit, eh? not so fast....
1108                            {
1109                                    switch (bDirection) {
1110                                    case 2:
1111                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1112                                                                                            start_y - iDiamondSize, 2 + 4);
1113                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1114                                                                                            start_y + iDiamondSize, 2 + 8);
1115                                            break;
1116                                    case 1:
1117                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1118                                                                                            start_y - iDiamondSize, 1 + 4);
1119                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1120                                                                                            start_y + iDiamondSize, 1 + 8);
1121                                            break;
1122                                    case 2 + 4:
1123                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1124                                                                                            start_y - iDiamondSize, 1 + 4);
1125                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1126                                                                                            start_y - iDiamondSize, 2 + 4);
1127                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1128                                                                                            start_y + iDiamondSize, 2 + 8);
1129                                            break;
1130                                    case 4:
1131                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1132                                                                                            start_y - iDiamondSize, 2 + 4);
1133                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1134                                                                                            start_y - iDiamondSize, 1 + 4);
1135                                            break;
1136                                    case 8:
1137                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1138                                                                                            start_y + iDiamondSize, 2 + 8);
1139                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1140                                                                                            start_y + iDiamondSize, 1 + 8);
1141                                            break;
1142                                    case 1 + 4:
1143                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1144                                                                                            start_y + iDiamondSize, 1 + 8);
1145                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1146                                                                                            start_y - iDiamondSize, 1 + 4);
1147                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1148                                                                                            start_y - iDiamondSize, 2 + 4);
1149                                            break;
1150                                    case 2 + 8:
1151                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1152                                                                                            start_y - iDiamondSize, 1 + 4);
1153                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1154                                                                                            start_y + iDiamondSize, 1 + 8);
1155                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1156                                                                                            start_y + iDiamondSize, 2 + 8);
1157                                            break;
1158                                    case 1 + 8:
1159                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1160                                                                                            start_y - iDiamondSize, 2 + 4);
1161                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1162                                                                                            start_y + iDiamondSize, 2 + 8);
1163                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1164                                                                                            start_y + iDiamondSize, 1 + 8);
1165                                            break;
1166                                    default:                //1+2+4+8 == we didn't find anything at all
1167                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1168                                                                                            start_y - iDiamondSize, 1 + 4);
1169                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1170                                                                                            start_y + iDiamondSize, 1 + 8);
1171                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1172                                                                                            start_y - iDiamondSize, 2 + 4);
1173                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1174                                                                                            start_y + iDiamondSize, 2 + 8);
1175                                            break;
1176                                    }
1177                                    if (!(iDirection))
1178                                            break;          //ok, the end. really
1179                                    else {
1180                                            bDirection = iDirection;
1181                                            start_x = currMV->x;
1182                                            start_y = currMV->y;
1183                                    }
1184                            }
1185                    }
1186                    while (1);                              //forever
1187            }
1188            return iMinSAD;
1189    }
1190    
1191    
1192    int32_t
1193    Full8_MainSearch(const uint8_t * const pRef,
1194                                     const uint8_t * const pRefH,
1195                                     const uint8_t * const pRefV,
1196                                     const uint8_t * const pRefHV,
1197                                     const uint8_t * const cur,
1198                                     const int x,
1199                                     const int y,
1200                               const int start_x,
1201                               const int start_y,
1202                               int iMinSAD,
1203                               VECTOR * const currMV,
1204                               const int center_x,
1205                               const int center_y,
1206                                     const int32_t min_dx,
1207                                     const int32_t max_dx,
1208                                     const int32_t min_dy,
1209                                     const int32_t max_dy,
1210                                     const int32_t iEdgedWidth,
1211                                     const int32_t iDiamondSize,
1212                                     const int32_t iFcode,
1213                                     const int32_t iQuant,
1214                                     int iFound)
1215    {
1216            int32_t iSAD;
1217            int32_t dx, dy;
1218            VECTOR backupMV;
1219    
1220            backupMV.x = start_x;
1221            backupMV.y = start_y;
1222    
1223            for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
1224                    for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
1225                            NOCHECK_MV8_CANDIDATE(dx, dy);
1226    
1227            return iMinSAD;
1228    }
1229    
1230    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1231    
1232    int32_t
1233    Halfpel16_Refine(const uint8_t * const pRef,
1234                                     const uint8_t * const pRefH,
1235                                     const uint8_t * const pRefV,
1236                                     const uint8_t * const pRefHV,
1237                                     const uint8_t * const cur,
1238                                     const int x,
1239                                     const int y,
1240                                     VECTOR * const currMV,
1241                                     int32_t iMinSAD,
1242                               const int center_x,
1243                               const int center_y,
1244                                     const int32_t min_dx,
1245                                     const int32_t max_dx,
1246                                     const int32_t min_dy,
1247                                     const int32_t max_dy,
1248                                     const int32_t iFcode,
1249                                     const int32_t iQuant,
1250                                     const int32_t iEdgedWidth)
1251    {
1252    /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
1253    
1254            int32_t iSAD;
1255            VECTOR backupMV = *currMV;
1256    
1257            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y - 1);
1258            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y - 1);
1259            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y - 1);
1260            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y);
1261            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y);
1262            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y + 1);
1263            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y + 1);
1264            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y + 1);
1265    
1266            return iMinSAD;
1267    }
1268    
1269    #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1270    
1271    
1272    
1273    int32_t
1274    PMVfastSearch16(const uint8_t * const pRef,
1275                                    const uint8_t * const pRefH,
1276                                    const uint8_t * const pRefV,
1277                                    const uint8_t * const pRefHV,
1278                                    const IMAGE * const pCur,
1279                                    const int x,
1280                                    const int y,
1281                                    const int start_x,
1282                                    const int start_y,
1283                                    const int center_x,
1284                                    const int center_y,
1285                                    const uint32_t MotionFlags,
1286                                    const uint32_t iQuant,
1287                                    const uint32_t iFcode,
1288                                    const MBParam * const pParam,
1289                                    const MACROBLOCK * const pMBs,
1290                                    const MACROBLOCK * const prevMBs,
1291                                    VECTOR * const currMV,
1292                                    VECTOR * const currPMV)
1293    {
1294            const uint32_t iWcount = pParam->mb_width;
1295            const int32_t iWidth = pParam->width;
1296            const int32_t iHeight = pParam->height;
1297          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
1298    
1299          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
# Line 895  Line 1313 
1313          VECTOR pmv[4];          VECTOR pmv[4];
1314          int32_t psad[4];          int32_t psad[4];
1315    
1316          MACROBLOCK * const pMB = pMBs + x + y * iWcount;          MainSearch16FuncPtr MainSearchPtr;
1317    
1318            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
1319    
1320          static int32_t threshA,threshB;          int32_t threshA, threshB;
1321          int32_t bPredEq;          int32_t bPredEq;
1322          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1323    
1324  /* Get maximum range */  /* Get maximum range */
1325          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,
1326                    x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
1327    
1328  /* 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 */
1329    
1330          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
1331          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1332          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1333          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1334          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1335          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
   
1336    
1337          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1338            //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1339            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1340    
1341          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1342                  threshA =  512;                  threshA =  512;
1343                  threshB = 1024;                  threshB = 1024;
1344            } else {
         }  
         else  
         {  
1345                  threshA = psad[0];                  threshA = psad[0];
1346                  threshB = threshA+256;                  threshB = threshA+256;
1347                  if (threshA< 512) threshA =  512;                  if (threshA < 512)
1348                  if (threshA>1024) threshA = 1024;                          threshA = 512;
1349                  if (threshB>1792) threshB = 1792;                  if (threshA > 1024)
1350                            threshA = 1024;
1351                    if (threshB > 1792)
1352                            threshB = 1792;
1353          }          }
1354    
1355          iFound=0;          iFound=0;
1356    
 /* 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;  
   
1357  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1358     MinSAD=SAD     MinSAD=SAD
1359     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 961  Line 1361 
1361     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
1362  */  */
1363    
1364            currMV->x = start_x;
1365            currMV->y = start_y;
1366    
1367  // 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! */  
1368                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1369                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
1370          }          }
1371    
1372          if (currMV->x > max_dx)          if (currMV->x > max_dx) {
         {  
1373                  currMV->x=max_dx;                  currMV->x=max_dx;
1374          }          }
1375          if (currMV->x < min_dx)          if (currMV->x < min_dx) {
         {  
1376                  currMV->x=min_dx;                  currMV->x=min_dx;
1377          }          }
1378          if (currMV->y > max_dy)          if (currMV->y > max_dy) {
         {  
1379                  currMV->y=max_dy;                  currMV->y=max_dy;
1380          }          }
1381          if (currMV->y < min_dy)          if (currMV->y < min_dy) {
         {  
1382                  currMV->y=min_dy;                  currMV->y=min_dy;
1383          }          }
1384    
1385          iMinSAD = sad16( cur,          iMinSAD =
1386                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1387                           iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1388          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1389            iMinSAD +=
1390          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
1391          {                                            (uint8_t) iFcode, iQuant);
1392    
1393            if ((iMinSAD < 256) ||
1394                    ((MVequal(*currMV, prevMB->mvs[0])) &&
1395                     ((int32_t) iMinSAD < prevMB->sad16))) {
1396                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
1397                    {
1398                            if (!MVzero(*currMV)) {
1399                                    iMinSAD += MV16_00_BIAS;
1400                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
1401                                    iMinSAD -= MV16_00_BIAS;
1402                            }
1403                    }
1404    
1405                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1406                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
# Line 1002  Line 1408 
1408                          goto PMVfast16_Terminate_with_Refine;                          goto PMVfast16_Terminate_with_Refine;
1409          }          }
1410    
1411    
1412    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1413       vector of the median.
1414       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1415    */
1416    
1417            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[0])))
1418                    iFound = 2;
1419    
1420    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1421       Otherwise select large Diamond Search.
1422    */
1423    
1424            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
1425                    iDiamondSize = 1;               // halfpel!
1426            else
1427                    iDiamondSize = 2;               // halfpel!
1428    
1429            if (!(MotionFlags & PMV_HALFPELDIAMOND16))
1430                    iDiamondSize *= 2;
1431    
1432  /*  /*
1433     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.
1434     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1435     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1436     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1437  */  */
1438    
1439  // (0,0) is always possible  // (0,0) is always possible
1440    
1441            if (!MVzero(pmv[0]))
1442          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1443    
1444  // previous frame MV is always possible  // previous frame MV is always possible
1445          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);  
1446            if (!MVzero(prevMB->mvs[0]))
1447                    if (!MVequal(prevMB->mvs[0], pmv[0]))
1448                            CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
1449    
1450  // left neighbour, if allowed  // left neighbour, if allowed
1451          if (x != 0)  
1452          {          if (!MVzero(pmv[1]))
1453                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!MVequal(pmv[1], prevMB->mvs[0]))
1454                  {       pmv[1].x = EVEN(pmv[1].x);                          if (!MVequal(pmv[1], pmv[0])) {
1455                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1456                                            pmv[1].x = EVEN(pmv[1].x);
1457                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1458                  }                  }
1459    
1460                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1461          }          }
   
1462  // top neighbour, if allowed  // top neighbour, if allowed
1463          if (y != 0)          if (!MVzero(pmv[2]))
1464          {                  if (!MVequal(pmv[2], prevMB->mvs[0]))
1465                  if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!MVequal(pmv[2], pmv[0]))
1466                  {       pmv[2].x = EVEN(pmv[2].x);                                  if (!MVequal(pmv[2], pmv[1])) {
1467                                            if (!(MotionFlags & PMV_HALFPEL16)) {
1468                                                    pmv[2].x = EVEN(pmv[2].x);
1469                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
1470                  }                  }
1471                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1472    
1473  // top right neighbour, if allowed  // top right neighbour, if allowed
1474                  if (x != (iWcount-1))                                          if (!MVzero(pmv[3]))
1475                  {                                                  if (!MVequal(pmv[3], prevMB->mvs[0]))
1476                          if (!(MotionFlags & PMV_HALFPEL16 ))                                                          if (!MVequal(pmv[3], pmv[0]))
1477                          {       pmv[3].x = EVEN(pmv[3].x);                                                                  if (!MVequal(pmv[3], pmv[1]))
1478                                                                            if (!MVequal(pmv[3], pmv[2])) {
1479                                                                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1480                                                                                            pmv[3].x = EVEN(pmv[3].x);
1481                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1482                          }                          }
1483                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                  CHECK_MV16_CANDIDATE(pmv[3].x,
1484                                                                                                                             pmv[3].y);
1485                  }                  }
1486          }          }
1487    
1488            if ((MVzero(*currMV)) &&
1489                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1490                    iMinSAD -= MV16_00_BIAS;
1491    
1492    
1493  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1494     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.
1495  */  */
1496    
1497          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )          if ((iMinSAD <= threshA) ||
1498          {                  (MVequal(*currMV, prevMB->mvs[0]) &&
1499                     ((int32_t) iMinSAD < prevMB->sad16))) {
1500                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1501                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
1502                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1069  Line 1514 
1514     Refine by using small diamond and goto step 10.     Refine by using small diamond and goto step 10.
1515  */  */
1516    
1517            if (MotionFlags & PMV_USESQUARES16)
1518                    MainSearchPtr = Square16_MainSearch;
1519            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
1520                    MainSearchPtr = AdvDiamond16_MainSearch;
1521            else
1522                    MainSearchPtr = Diamond16_MainSearch;
1523    
1524          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1525    
1526    
1527  /* 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 */
1528          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1529                                            x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1530                                            currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->x, currMV->y, iMinSAD, &newMV, center_x, center_y,
1531                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dx, max_dx,
1532                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1533                                                      iQuant, iFound);
1534    
1535          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1536                  *currMV = newMV;                  *currMV = newMV;
1537                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1538          }          }
1539    
1540          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
1541  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1542    
1543                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1544                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1545                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1546                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    center_x, center_y, iMinSAD, &newMV, center_x, center_y,
1547                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1548                                                                      iDiamondSize, iFcode, iQuant, iFound);
1549    
1550                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1551                          *currMV = newMV;                          *currMV = newMV;
1552                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1553                  }                  }
1554                  }                  }
1555    
1556                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1557                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1558                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1559                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y,
1560                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy,
1561                                                                      iEdgedWidth, iDiamondSize, iFcode,
1562                                                                      iQuant, iFound);
1563    
1564                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1565                          *currMV = newMV;                          *currMV = newMV;
1566                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1567                  }                  }
# Line 1120  Line 1574 
1574    
1575  PMVfast16_Terminate_with_Refine:  PMVfast16_Terminate_with_Refine:
1576          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1577                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1578                                    x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1579                                    currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1580                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1581    
1582  PMVfast16_Terminate_without_Refine:  PMVfast16_Terminate_without_Refine:
1583          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
1584          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
1585          return iMinSAD;          return iMinSAD;
1586  }  }
1587    
# Line 1136  Line 1590 
1590    
1591    
1592    
1593  int32_t Diamond8_MainSearch(  int32_t
1594          const uint8_t * const pRef,  Diamond8_MainSearch(const uint8_t * const pRef,
1595          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1596          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1597          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1598          const uint8_t * const cur,          const uint8_t * const cur,
1599          const int x, const int y,                                          const int x,
1600          int32_t startx, int32_t starty,                                          const int y,
1601                                            int32_t start_x,
1602                                            int32_t start_y,
1603          int32_t iMinSAD,          int32_t iMinSAD,
1604          VECTOR * const currMV,          VECTOR * const currMV,
1605          const VECTOR * const pmv,                                     const int center_x,
1606          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
1607          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
1608                                            const int32_t max_dx,
1609                                            const int32_t min_dy,
1610                                            const int32_t max_dy,
1611          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
1612          const int32_t iDiamondSize,          const int32_t iDiamondSize,
1613          const int32_t iFcode,          const int32_t iFcode,
# Line 1158  Line 1617 
1617  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
1618    
1619          int32_t iDirection=0;          int32_t iDirection=0;
1620            int32_t iDirectionBackup;
1621          int32_t iSAD;          int32_t iSAD;
1622          VECTOR backupMV;          VECTOR backupMV;
1623          backupMV.x = startx;  
1624          backupMV.y = starty;          backupMV.x = start_x;
1625            backupMV.y = start_y;
1626    
1627  /* 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 */
1628    
# Line 1170  Line 1631 
1631          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
1632          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1633    
1634          if (iDirection)          if (iDirection) {
1635                  while (!iFound)                  while (!iFound) {
                 {  
1636                          iFound = 1;                          iFound = 1;
1637                          backupMV=*currMV;       // since iDirection!=0, this is well defined!                          backupMV=*currMV;       // since iDirection!=0, this is well defined!
1638                            iDirectionBackup = iDirection;
1639    
1640                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
1641                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1642                          if ( iDirection != 1)                                                                                    backupMV.y, 1);
1643                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
1644                          if ( iDirection != 4)                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1645                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                    backupMV.y, 2);
1646                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
1647                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1648                                                                                      backupMV.y - iDiamondSize, 3);
1649                            if (iDirectionBackup != 3)
1650                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1651                                                                                      backupMV.y + iDiamondSize, 4);
1652                  }                  }
1653          else          } else {
1654                    currMV->x = start_x;
1655                    currMV->y = start_y;
1656            }
1657            return iMinSAD;
1658    }
1659    
1660    
1661    
1662    
1663    int32_t
1664    Square8_MainSearch(const uint8_t * const pRef,
1665                                            const uint8_t * const pRefH,
1666                                            const uint8_t * const pRefV,
1667                                            const uint8_t * const pRefHV,
1668                                            const uint8_t * const cur,
1669                                            const int x,
1670                                            const int y,
1671                                            int32_t start_x,
1672                                            int32_t start_y,
1673                                            int32_t iMinSAD,
1674                                            VECTOR * const currMV,
1675                                       const int center_x,
1676                                       const int center_y,
1677                                            const int32_t min_dx,
1678                                            const int32_t max_dx,
1679                                            const int32_t min_dy,
1680                                            const int32_t max_dy,
1681                                            const int32_t iEdgedWidth,
1682                                            const int32_t iDiamondSize,
1683                                            const int32_t iFcode,
1684                                            const int32_t iQuant,
1685                                            int iFound)
1686          {          {
1687                  currMV->x = startx;  /* Do a square search around given starting point, return SAD of best */
1688                  currMV->y = starty;  
1689            int32_t iDirection = 0;
1690            int32_t iSAD;
1691            VECTOR backupMV;
1692    
1693            backupMV.x = start_x;
1694            backupMV.y = start_y;
1695    
1696    /* It's one search with full square pattern, and new parts for all following diamonds */
1697    
1698    /*   new direction are extra, so 1-4 is normal diamond
1699          537
1700          1*2
1701          648
1702    */
1703    
1704            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1705            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1706            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1707            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1708    
1709            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1710                                                             backupMV.y - iDiamondSize, 5);
1711            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1712                                                             backupMV.y + iDiamondSize, 6);
1713            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1714                                                             backupMV.y - iDiamondSize, 7);
1715            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1716                                                             backupMV.y + iDiamondSize, 8);
1717    
1718    
1719            if (iDirection) {
1720                    while (!iFound) {
1721                            iFound = 1;
1722                            backupMV = *currMV;
1723    
1724                            switch (iDirection) {
1725                            case 1:
1726                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1727                                                                                       backupMV.y, 1);
1728                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1729                                                                                     backupMV.y - iDiamondSize, 5);
1730                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1731                                                                                     backupMV.y - iDiamondSize, 7);
1732                                    break;
1733                            case 2:
1734                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1735                                                                                     2);
1736                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1737                                                                                     backupMV.y + iDiamondSize, 6);
1738                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1739                                                                                     backupMV.y + iDiamondSize, 8);
1740                                    break;
1741    
1742                            case 3:
1743                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1744                                                                                     4);
1745                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1746                                                                                     backupMV.y - iDiamondSize, 7);
1747                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1748                                                                                     backupMV.y + iDiamondSize, 8);
1749                                    break;
1750    
1751                            case 4:
1752                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1753                                                                                     3);
1754                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1755                                                                                     backupMV.y - iDiamondSize, 5);
1756                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1757                                                                                     backupMV.y + iDiamondSize, 6);
1758                                    break;
1759    
1760                            case 5:
1761                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1762                                                                                     1);
1763                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1764                                                                                     3);
1765                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1766                                                                                     backupMV.y - iDiamondSize, 5);
1767                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1768                                                                                     backupMV.y + iDiamondSize, 6);
1769                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1770                                                                                     backupMV.y - iDiamondSize, 7);
1771                                    break;
1772    
1773                            case 6:
1774                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1775                                                                                     2);
1776                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1777                                                                                     3);
1778    
1779                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1780                                                                                     backupMV.y - iDiamondSize, 5);
1781                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1782                                                                                     backupMV.y + iDiamondSize, 6);
1783                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1784                                                                                     backupMV.y + iDiamondSize, 8);
1785    
1786                                    break;
1787    
1788                            case 7:
1789                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1790                                                                                       backupMV.y, 1);
1791                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1792                                                                                     4);
1793                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1794                                                                                     backupMV.y - iDiamondSize, 5);
1795                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1796                                                                                     backupMV.y - iDiamondSize, 7);
1797                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1798                                                                                     backupMV.y + iDiamondSize, 8);
1799                                    break;
1800    
1801                            case 8:
1802                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1803                                                                                     2);
1804                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1805                                                                                     4);
1806                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1807                                                                                     backupMV.y + iDiamondSize, 6);
1808                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1809                                                                                     backupMV.y - iDiamondSize, 7);
1810                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1811                                                                                     backupMV.y + iDiamondSize, 8);
1812                                    break;
1813                            default:
1814                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1815                                                                                     1);
1816                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1817                                                                                     2);
1818                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1819                                                                                     3);
1820                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1821                                                                                     4);
1822    
1823                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1824                                                                                     backupMV.y - iDiamondSize, 5);
1825                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1826                                                                                     backupMV.y + iDiamondSize, 6);
1827                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1828                                                                                     backupMV.y - iDiamondSize, 7);
1829                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1830                                                                                     backupMV.y + iDiamondSize, 8);
1831                                    break;
1832                            }
1833                    }
1834            } else {
1835                    currMV->x = start_x;
1836                    currMV->y = start_y;
1837          }          }
1838          return iMinSAD;          return iMinSAD;
1839  }  }
1840    
1841  int32_t Halfpel8_Refine(  
1842          const uint8_t * const pRef,  
1843    
1844    
1845    int32_t
1846    Halfpel8_Refine_c(const uint8_t * const pRef,
1847          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1848          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1849          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1850          const uint8_t * const cur,          const uint8_t * const cur,
1851          const int x, const int y,                                  const int x,
1852                                    const int y,
1853          VECTOR * const currMV,          VECTOR * const currMV,
1854          int32_t iMinSAD,          int32_t iMinSAD,
1855          const VECTOR * const pmv,                             const int center_x,
1856          const int32_t min_dx, const int32_t max_dx,                             const int center_y,
1857          const int32_t min_dy, const int32_t max_dy,                                  const int32_t min_dx,
1858                                    const int32_t max_dx,
1859                                    const int32_t min_dy,
1860                                    const int32_t max_dy,
1861          const int32_t iFcode,          const int32_t iFcode,
1862          const int32_t iQuant,          const int32_t iQuant,
1863          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 1229  Line 1882 
1882    
1883  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1884    
1885  int32_t PMVfastSearch8(  int32_t
1886                                          const uint8_t * const pRef,  PMVfastSearch8(const uint8_t * const pRef,
1887                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1888                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1889                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1890                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1891                                          const int x, const int y,                             const int x,
1892                                          const int start_x, int start_y,                             const int y,
1893                               const int start_x,
1894                               const int start_y,
1895                                    const int center_x,
1896                                    const int center_y,
1897                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1898                               const uint32_t iQuant,
1899                               const uint32_t iFcode,
1900                                          const MBParam * const pParam,                                          const MBParam * const pParam,
1901                                          MACROBLOCK * const pMBs,                             const MACROBLOCK * const pMBs,
1902                               const MACROBLOCK * const prevMBs,
1903                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1904                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
1905  {  {
1906          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;  
1907          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1908          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
1909          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 1264  Line 1921 
1921          int32_t psad[4];          int32_t psad[4];
1922          VECTOR newMV;          VECTOR newMV;
1923          VECTOR backupMV;          VECTOR backupMV;
1924            VECTOR startMV;
1925    
1926          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1927            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
1928    
1929          static int32_t threshA,threshB;           int32_t threshA, threshB;
1930          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
1931          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1932    
1933          int32_t iSubBlock = ((y&1)<<1) + (x&1);          int32_t iSubBlock = (y & 1) + (y & 1) + (x & 1);
1934    
1935  /* Get maximum range */          MainSearch8FuncPtr MainSearchPtr;
         get_range(&min_dx, &max_dx, &min_dy, &max_dy,  
                   x, y, 8, iWidth, iHeight, iFcode);  
1936    
1937  /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */          /* Init variables */
1938            startMV.x = start_x;
1939            startMV.y = start_y;
1940    
1941          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          /* Get maximum range */
1942          { min_dx = EVEN(min_dx);          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
1943                              iFcode);
1944    
1945            if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
1946                    min_dx = EVEN(min_dx);
1947          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1948          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1949          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1950          }               /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          }
   
1951    
1952          bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
1953            //bPredEq = get_pmvdata(pMBs, (x >> 1), (y >> 1), iWcount, iSubBlock, pmv, psad);
1954            bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
1955    
1956          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1957                  threshA =  512/4;                  threshA =  512/4;
1958                  threshB = 1024/4;                  threshB = 1024/4;
1959    
1960          }          } else {
1961          else                  threshA = psad[0] / 4;  /* good estimate? */
1962          {                  threshB = threshA + 256 / 4;
1963                  threshA = psad[0]/4;                    /* good estimate */                  if (threshA < 512 / 4)
1964                  threshB = threshA+256/4;                          threshA = 512 / 4;
1965                  if (threshA< 512/4) threshA =  512/4;                  if (threshA > 1024 / 4)
1966                  if (threshA>1024/4) threshA = 1024/4;                          threshA = 1024 / 4;
1967                  if (threshB>1792/4) threshB = 1792/4;                  if (threshB > 1792 / 4)
1968          }                          threshB = 1792 / 4;
1969            }
         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!  
1970    
1971          if (!(MotionFlags & PMV_HALFPELDIAMOND8) )          iFound = 0;
                 iDiamondSize*=2;  
1972    
1973  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1974     MinSAD=SAD     MinSAD=SAD
# Line 1336  Line 1980 
1980    
1981  // Prepare for main loop  // Prepare for main loop
1982    
1983          currMV->x=start_x;              /* start with mv16 */    if (MotionFlags & PMV_USESQUARES8)
1984          currMV->y=start_y;        MainSearchPtr = Square8_MainSearch;
1985      else
1986    
1987            if (MotionFlags & PMV_ADVANCEDDIAMOND8)
1988                    MainSearchPtr = AdvDiamond8_MainSearch;
1989            else
1990                    MainSearchPtr = Diamond8_MainSearch;
1991    
         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;  
1992    
1993          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          *currMV = startMV;
1994          {  
1995            iMinSAD =
1996                    sad8(cur,
1997                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
1998                                                    iEdgedWidth), iEdgedWidth);
1999            iMinSAD +=
2000                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2001                                             (uint8_t) iFcode, iQuant);
2002    
2003            if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))
2004                                                                    && ((int32_t) iMinSAD <
2005                                                                            prevMB->sad8[iSubBlock]))) {
2006                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2007                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2008                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
2009                          goto PMVfast8_Terminate_with_Refine;                          goto PMVfast8_Terminate_with_Refine;
2010          }          }
2011    
2012    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2013       vector of the median.
2014       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2015    */
2016    
2017            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[iSubBlock])))
2018                    iFound = 2;
2019    
2020    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2021       Otherwise select large Diamond Search.
2022    */
2023    
2024            if ((!MVzero(pmv[0])) || (threshB < 1536 / 4) || (bPredEq))
2025                    iDiamondSize = 1;               // 1 halfpel!
2026            else
2027                    iDiamondSize = 2;               // 2 halfpel = 1 full pixel!
2028    
2029            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2030                    iDiamondSize *= 2;
2031    
2032    
2033  /*  /*
2034     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.
2035     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
2036     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
2037     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
2038  */  */
2039    
2040  // 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);  
2041    
2042  // (0,0) is always possible          if (!MVequal(pmv[0], startMV))
2043                    CHECK_MV8_CANDIDATE(center_x, center_y);
2044    
2045    // (0,0) if needed
2046            if (!MVzero(pmv[0]))
2047                    if (!MVzero(startMV))
2048          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
2049    
2050  // previous frame MV is always possible  // previous frame MV if needed
2051          CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);          if (!MVzero(prevMB->mvs[iSubBlock]))
2052                    if (!MVequal(prevMB->mvs[iSubBlock], startMV))
2053                            if (!MVequal(prevMB->mvs[iSubBlock], pmv[0]))
2054                                    CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,
2055                                                                            prevMB->mvs[iSubBlock].y);
2056    
2057            if ((iMinSAD <= threshA) ||
2058                    (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2059                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2060                    if (MotionFlags & PMV_QUICKSTOP16)
2061                            goto PMVfast8_Terminate_without_Refine;
2062                    if (MotionFlags & PMV_EARLYSTOP16)
2063                            goto PMVfast8_Terminate_with_Refine;
2064            }
2065    
2066  // left neighbour, if allowed  // left neighbour, if allowed and needed
2067          if (psad[1] != MV_MAX_ERROR)          if (!MVzero(pmv[1]))
2068          {                  if (!MVequal(pmv[1], startMV))
2069                  if (!(MotionFlags & PMV_HALFPEL8 ))                          if (!MVequal(pmv[1], prevMB->mvs[iSubBlock]))
2070                  {       pmv[1].x = EVEN(pmv[1].x);                                  if (!MVequal(pmv[1], pmv[0])) {
2071                                            if (!(MotionFlags & PMV_HALFPEL8)) {
2072                                                    pmv[1].x = EVEN(pmv[1].x);
2073                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
2074                  }                  }
2075                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
2076          }          }
2077    // top neighbour, if allowed and needed
2078  // top neighbour, if allowed          if (!MVzero(pmv[2]))
2079          if (psad[2] != MV_MAX_ERROR)                  if (!MVequal(pmv[2], startMV))
2080          {                          if (!MVequal(pmv[2], prevMB->mvs[iSubBlock]))
2081                  if (!(MotionFlags & PMV_HALFPEL8 ))                                  if (!MVequal(pmv[2], pmv[0]))
2082                  {       pmv[2].x = EVEN(pmv[2].x);                                          if (!MVequal(pmv[2], pmv[1])) {
2083                                                    if (!(MotionFlags & PMV_HALFPEL8)) {
2084                                                            pmv[2].x = EVEN(pmv[2].x);
2085                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
2086                  }                  }
2087                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
2088    
2089  // top right neighbour, if allowed  // top right neighbour, if allowed and needed
2090                  if (psad[3] != MV_MAX_ERROR)                                                  if (!MVzero(pmv[3]))
2091                  {                                                          if (!MVequal(pmv[3], startMV))
2092                          if (!(MotionFlags & PMV_HALFPEL8 ))                                                                  if (!MVequal(pmv[3], prevMB->mvs[iSubBlock]))
2093                          {       pmv[3].x = EVEN(pmv[3].x);                                                                          if (!MVequal(pmv[3], pmv[0]))
2094                                                                                    if (!MVequal(pmv[3], pmv[1]))
2095                                                                                            if (!MVequal(pmv[3], pmv[2])) {
2096                                                                                                    if (!
2097                                                                                                            (MotionFlags &
2098                                                                                                             PMV_HALFPEL8)) {
2099                                                                                                            pmv[3].x = EVEN(pmv[3].x);
2100                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
2101                          }                          }
2102                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                                  CHECK_MV8_CANDIDATE(pmv[3].x,
2103                                                                                                                                            pmv[3].y);
2104                  }                  }
2105          }          }
2106    
2107            if ((MVzero(*currMV)) &&
2108                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2109                    iMinSAD -= MV8_00_BIAS;
2110    
2111    
2112  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
2113     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.
2114  */  */
2115    
2116          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
2117          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2118                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2119                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2120                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2121                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1424  Line 2135 
2135          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2136    
2137  /* 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 */
2138          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2139                                           x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2140                                           currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2141                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2142                                                      iQuant, iFound);
2143    
2144          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2145                  *currMV = newMV;                  *currMV = newMV;
2146                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2147          }          }
2148    
2149          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2150  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
2151    
2152                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2153                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2154                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2155                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2156                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2157                                                                      iDiamondSize, iFcode, iQuant, iFound);
2158    
2159                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2160                          *currMV = newMV;                          *currMV = newMV;
2161                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2162                  }                  }
2163                  }                  }
2164    
2165                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2166                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2167                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2168                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2169                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2170                                                                      iQuant, iFound);
2171    
2172                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2173                          *currMV = newMV;                          *currMV = newMV;
2174                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2175                  }                  }
# Line 1472  Line 2182 
2182    
2183  PMVfast8_Terminate_with_Refine:  PMVfast8_Terminate_with_Refine:
2184          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2185                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2186                                                   x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2187                                                   currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2188                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2189    
2190    
2191  PMVfast8_Terminate_without_Refine:  PMVfast8_Terminate_without_Refine:
2192          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2193          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2194    
2195          return iMinSAD;          return iMinSAD;
2196  }  }
2197    
2198  int32_t EPZSSearch16(  int32_t
2199                                          const uint8_t * const pRef,  EPZSSearch16(const uint8_t * const pRef,
2200                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2201                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2202                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2203                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2204                                          const int x, const int y,                           const int x,
2205                             const int y,
2206                            const int start_x,
2207                            const int start_y,
2208                            const int center_x,
2209                            const int center_y,
2210                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2211                             const uint32_t iQuant,
2212                             const uint32_t iFcode,
2213                                          const MBParam * const pParam,                                          const MBParam * const pParam,
2214                                          MACROBLOCK * const pMBs,                           const MACROBLOCK * const pMBs,
2215                             const MACROBLOCK * const prevMBs,
2216                                          VECTOR * const currMV,                                          VECTOR * const currMV,
2217                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
2218  {  {
2219          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
2220          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;  
2221    
2222          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
2223          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
# Line 1521  Line 2237 
2237          int32_t psad[8];          int32_t psad[8];
2238    
2239          static MACROBLOCK * oldMBs = NULL;          static MACROBLOCK * oldMBs = NULL;
2240          MACROBLOCK * const pMB = pMBs + x + y * iWcount;  
2241    //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
2242            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2243          MACROBLOCK * oldMB = NULL;          MACROBLOCK * oldMB = NULL;
2244    
2245          static int32_t thresh2;           int32_t thresh2;
2246          int32_t bPredEq;          int32_t bPredEq;
2247          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2248    
2249          MainSearch16FuncPtr EPZSMainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
2250    
2251          if (oldMBs == NULL)          if (oldMBs == NULL) {
2252          {       oldMBs = (MACROBLOCK*) calloc(1,iWcount*iHcount*sizeof(MACROBLOCK));                  oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
2253                  fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));  //      fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
2254          }          }
2255          oldMB = oldMBs + x + y * iWcount;          oldMB = oldMBs + x + y * iWcount;
2256    
2257  /* Get maximum range */  /* Get maximum range */
2258          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,
2259                          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 */  
2260    
2261          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
2262          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2263            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2264            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2265            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2266          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2267            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2268          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
2269            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2270    
2271  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2272          MinSAD=SAD          MinSAD=SAD
# Line 1560  Line 2277 
2277    
2278  // Prepare for main loop  // Prepare for main loop
2279    
2280          *currMV=pmv[0];         /* current best := median prediction */          currMV->x = start_x;
2281          if (!(MotionFlags & PMV_HALFPEL16))          currMV->y = start_y;
2282          {  
2283            if (!(MotionFlags & PMV_HALFPEL16)) {
2284                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2285                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2286          }          }
# Line 1578  Line 2296 
2296    
2297  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2298    
2299          iMinSAD = sad16( cur,          iMinSAD =
2300                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
2301                  iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2302          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2303            iMinSAD +=
2304                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2305                                              (uint8_t) iFcode, iQuant);
2306    
2307  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2308          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )          if ((iMinSAD < 256) ||
2309                  {                  ((MVequal(*currMV, prevMB->mvs[0])) &&
2310                     ((int32_t) iMinSAD < prevMB->sad16))) {
2311                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2312                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2313                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1595  Line 2317 
2317  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2318    
2319  // previous frame MV  // previous frame MV
2320          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
2321    
2322  // set threshhold based on Min of Prediction and SAD of collocated block  // set threshhold based on Min of Prediction and SAD of collocated block
2323  // 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
2324    
2325          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
2326                  thresh2 =  512;                  thresh2 =  512;
2327          }          } else {
         else  
         {  
2328  /* 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] */
2329    
2330                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
# Line 1617  Line 2336 
2336    
2337    
2338  // left neighbour, if allowed  // left neighbour, if allowed
2339          if (x != 0)          if (x != 0) {
2340          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2341                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[1].x = EVEN(pmv[1].x);
2342                  {       pmv[1].x = EVEN(pmv[1].x);                          pmv[1].y = EVEN(pmv[1].y);
2343                    }
2344                    CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
2345            }
2346    // top neighbour, if allowed
2347            if (y != 0) {
2348                    if (!(MotionFlags & PMV_HALFPEL16)) {
2349                            pmv[2].x = EVEN(pmv[2].x);
2350                            pmv[2].y = EVEN(pmv[2].y);
2351                    }
2352                    CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
2353    
2354    // top right neighbour, if allowed
2355                    if ((uint32_t) x != (iWcount - 1)) {
2356                            if (!(MotionFlags & PMV_HALFPEL16)) {
2357                                    pmv[3].x = EVEN(pmv[3].x);
2358                                    pmv[3].y = EVEN(pmv[3].y);
2359                            }
2360                            CHECK_MV16_CANDIDATE(pmv[3].x, pmv[3].y);
2361                    }
2362            }
2363    
2364    /* Terminate if MinSAD <= T_2
2365       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
2366    */
2367    
2368            if ((iMinSAD <= thresh2)
2369                    || (MVequal(*currMV, prevMB->mvs[0]) &&
2370                            ((int32_t) iMinSAD <= prevMB->sad16))) {
2371                    if (MotionFlags & PMV_QUICKSTOP16)
2372                            goto EPZS16_Terminate_without_Refine;
2373                    if (MotionFlags & PMV_EARLYSTOP16)
2374                            goto EPZS16_Terminate_with_Refine;
2375            }
2376    
2377    /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
2378    
2379            backupMV = prevMB->mvs[0];      // collocated MV
2380            backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x);     // acceleration X
2381            backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y);     // acceleration Y
2382    
2383            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y);
2384    
2385    // left neighbour
2386            if (x != 0)
2387                    CHECK_MV16_CANDIDATE((prevMB - 1)->mvs[0].x, (prevMB - 1)->mvs[0].y);
2388    
2389    // top neighbour
2390            if (y != 0)
2391                    CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,
2392                                                             (prevMB - iWcount)->mvs[0].y);
2393    
2394    // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
2395    
2396            if ((uint32_t) x != iWcount - 1)
2397                    CHECK_MV16_CANDIDATE((prevMB + 1)->mvs[0].x, (prevMB + 1)->mvs[0].y);
2398    
2399    // bottom neighbour, dito
2400            if ((uint32_t) y != iHcount - 1)
2401                    CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,
2402                                                             (prevMB + iWcount)->mvs[0].y);
2403    
2404    /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
2405            if (iMinSAD <= thresh2) {
2406                    if (MotionFlags & PMV_QUICKSTOP16)
2407                            goto EPZS16_Terminate_without_Refine;
2408                    if (MotionFlags & PMV_EARLYSTOP16)
2409                            goto EPZS16_Terminate_with_Refine;
2410            }
2411    
2412    /************ (if Diamond Search)  **************/
2413    
2414            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2415    
2416            if (MotionFlags & PMV_USESQUARES16)
2417                    MainSearchPtr = Square16_MainSearch;
2418            else
2419             if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2420                    MainSearchPtr = AdvDiamond16_MainSearch;
2421            else
2422                    MainSearchPtr = Diamond16_MainSearch;
2423    
2424    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2425    
2426            iSAD =
2427                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2428                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2429                                                      min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2430    
2431            if (iSAD < iMinSAD) {
2432                    *currMV = newMV;
2433                    iMinSAD = iSAD;
2434            }
2435    
2436    
2437            if (MotionFlags & PMV_EXTSEARCH16) {
2438    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2439    
2440                    if (!(MVequal(pmv[0], backupMV))) {
2441                            iSAD =
2442                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2443                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2444                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2445                                                                      2, iFcode, iQuant, 0);
2446                    }
2447    
2448                    if (iSAD < iMinSAD) {
2449                            *currMV = newMV;
2450                            iMinSAD = iSAD;
2451                    }
2452    
2453                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2454                            iSAD =
2455                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2456                                                                      iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2457                                                                      max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2458    
2459                            if (iSAD < iMinSAD) {
2460                                    *currMV = newMV;
2461                                    iMinSAD = iSAD;
2462                            }
2463                    }
2464            }
2465    
2466    /***************        Choose best MV found     **************/
2467    
2468      EPZS16_Terminate_with_Refine:
2469            if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
2470                    iMinSAD =
2471                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2472                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2473                                                             iFcode, iQuant, iEdgedWidth);
2474    
2475      EPZS16_Terminate_without_Refine:
2476    
2477            *oldMB = *prevMB;
2478    
2479            currPMV->x = currMV->x - center_x;
2480            currPMV->y = currMV->y - center_y;
2481            return iMinSAD;
2482    }
2483    
2484    
2485    int32_t
2486    EPZSSearch8(const uint8_t * const pRef,
2487                            const uint8_t * const pRefH,
2488                            const uint8_t * const pRefV,
2489                            const uint8_t * const pRefHV,
2490                            const IMAGE * const pCur,
2491                            const int x,
2492                            const int y,
2493                            const int start_x,
2494                            const int start_y,
2495                            const int center_x,
2496                            const int center_y,
2497                            const uint32_t MotionFlags,
2498                            const uint32_t iQuant,
2499                            const uint32_t iFcode,
2500                            const MBParam * const pParam,
2501                            const MACROBLOCK * const pMBs,
2502                            const MACROBLOCK * const prevMBs,
2503                            VECTOR * const currMV,
2504                            VECTOR * const currPMV)
2505    {
2506    /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
2507    
2508            const uint32_t iWcount = pParam->mb_width;
2509            const int32_t iWidth = pParam->width;
2510            const int32_t iHeight = pParam->height;
2511            const int32_t iEdgedWidth = pParam->edged_width;
2512    
2513            const uint8_t *cur = pCur->y + x * 8 + y * 8 * iEdgedWidth;
2514    
2515            int32_t iDiamondSize = 1;
2516    
2517            int32_t min_dx;
2518            int32_t max_dx;
2519            int32_t min_dy;
2520            int32_t max_dy;
2521    
2522            VECTOR newMV;
2523            VECTOR backupMV;
2524    
2525            VECTOR pmv[4];
2526            int32_t psad[8];
2527    
2528            const int32_t iSubBlock = ((y & 1) << 1) + (x & 1);
2529    
2530    //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2531            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
2532    
2533            int32_t bPredEq;
2534            int32_t iMinSAD, iSAD = 9999;
2535    
2536            MainSearch8FuncPtr MainSearchPtr;
2537    
2538    /* Get maximum range */
2539            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2540                              iFcode);
2541    
2542    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2543    
2544            if (!(MotionFlags & PMV_HALFPEL8)) {
2545                    min_dx = EVEN(min_dx);
2546                    max_dx = EVEN(max_dx);
2547                    min_dy = EVEN(min_dy);
2548                    max_dy = EVEN(max_dy);
2549            }
2550            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2551            //bPredEq = get_pmvdata(pMBs, x >> 1, y >> 1, iWcount, iSubBlock, pmv[0].x, pmv[0].y, psad);
2552            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2553    
2554    
2555    /* Step 4: Calculate SAD around the Median prediction.
2556            MinSAD=SAD
2557            If Motion Vector equal to Previous frame motion vector
2558                    and MinSAD<PrevFrmSAD goto Step 10.
2559            If SAD<=256 goto Step 10.
2560    */
2561    
2562    // Prepare for main loop
2563    
2564    
2565            if (!(MotionFlags & PMV_HALFPEL8)) {
2566                    currMV->x = EVEN(currMV->x);
2567                    currMV->y = EVEN(currMV->y);
2568            }
2569    
2570            if (currMV->x > max_dx)
2571                    currMV->x = max_dx;
2572            if (currMV->x < min_dx)
2573                    currMV->x = min_dx;
2574            if (currMV->y > max_dy)
2575                    currMV->y = max_dy;
2576            if (currMV->y < min_dy)
2577                    currMV->y = min_dy;
2578    
2579    /***************** This is predictor SET A: only median prediction ******************/
2580    
2581    
2582            iMinSAD =
2583                    sad8(cur,
2584                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2585                                                    iEdgedWidth), iEdgedWidth);
2586            iMinSAD +=
2587                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2588                                             (uint8_t) iFcode, iQuant);
2589    
2590    
2591    // thresh1 is fixed to 256
2592            if (iMinSAD < 256 / 4) {
2593                    if (MotionFlags & PMV_QUICKSTOP8)
2594                            goto EPZS8_Terminate_without_Refine;
2595                    if (MotionFlags & PMV_EARLYSTOP8)
2596                            goto EPZS8_Terminate_with_Refine;
2597            }
2598    
2599    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2600    
2601    
2602    // MV=(0,0) is often a good choice
2603            CHECK_MV8_ZERO;
2604    
2605    // previous frame MV
2606            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x, prevMB->mvs[iSubBlock].y);
2607    
2608    // left neighbour, if allowed
2609            if (psad[1] != MV_MAX_ERROR) {
2610                    if (!(MotionFlags & PMV_HALFPEL8)) {
2611                            pmv[1].x = EVEN(pmv[1].x);
2612                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2613                  }                  }
2614                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x, pmv[1].y);
2615          }          }
   
2616  // top neighbour, if allowed  // top neighbour, if allowed
2617          if (y != 0)          if (psad[2] != MV_MAX_ERROR) {
2618          {                  if (!(MotionFlags & PMV_HALFPEL8)) {
2619                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2620                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2621                  }                  }
2622                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x, pmv[2].y);
2623    
2624  // top right neighbour, if allowed  // top right neighbour, if allowed
2625                  if (x != (iWcount-1))                  if (psad[3] != MV_MAX_ERROR) {
2626                  {                          if (!(MotionFlags & PMV_HALFPEL8)) {
2627                          if (!(MotionFlags & PMV_HALFPEL16 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2628                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2629                          }                          }
2630                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV8_CANDIDATE(pmv[3].x, pmv[3].y);
2631                  }                  }
2632          }          }
2633    
2634    /*  // this bias is zero anyway, at the moment!
2635    
2636            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
2637                    iMinSAD -= MV8_00_BIAS;
2638    
2639    */
2640    
2641  /* Terminate if MinSAD <= T_2  /* Terminate if MinSAD <= T_2
2642     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]
2643  */  */
2644    
2645          if ( (iMinSAD <= thresh2)          if (iMinSAD < 512 / 4) {        /* T_2 == 512/4 hardcoded */
2646                  || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD <= pMB->sad16) ) )                  if (MotionFlags & PMV_QUICKSTOP8)
2647                  {                          goto EPZS8_Terminate_without_Refine;
2648                          if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_EARLYSTOP8)
2649                                  goto EPZS16_Terminate_without_Refine;                          goto EPZS8_Terminate_with_Refine;
                         if (MotionFlags & PMV_EARLYSTOP16)  
                                 goto EPZS16_Terminate_with_Refine;  
2650                  }                  }
2651    
2652  /***** 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);  
2653    
2654  // 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);  
2655    
2656  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */          if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2657          if (iMinSAD <= thresh2)                  iDiamondSize *= 2;
                 {  
                         if (MotionFlags & PMV_QUICKSTOP16)  
                                 goto EPZS16_Terminate_without_Refine;  
                         if (MotionFlags & PMV_EARLYSTOP16)  
                                 goto EPZS16_Terminate_with_Refine;  
                 }  
2658    
2659  /************ (if Diamond Search)  **************/  /* default: use best prediction as starting point for one call of EPZS_MainSearch */
2660    
2661          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */  // there is no EPZS^2 for inter4v at the moment
2662    
2663  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */    if (MotionFlags & PMV_USESQUARES8)
2664          MainSearchPtr = Square8_MainSearch;
2665      else
2666    
2667          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2668                  EPZSMainSearchPtr = Square16_MainSearch;                  MainSearchPtr = AdvDiamond8_MainSearch;
2669          else          else
2670                  EPZSMainSearchPtr = Diamond16_MainSearch;                  MainSearchPtr = Diamond8_MainSearch;
2671    
2672          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2673                          x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2674                          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,
2675                          2, iFcode, iQuant, 0);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2676                                                      iQuant, 0);
2677    
2678          if (iSAD < iMinSAD)  
2679          {          if (iSAD < iMinSAD) {
2680                  *currMV = newMV;                  *currMV = newMV;
2681                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2682          }          }
2683    
2684            if (MotionFlags & PMV_EXTSEARCH8) {
         if (MotionFlags & PMV_EXTSEARCH16)  
         {  
2685  /* 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) */
2686    
2687                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2688                  {                          iSAD =
2689                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2690                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2691                                  pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2692                                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, 0);
                 }  
2693    
2694                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2695                          *currMV = newMV;                          *currMV = newMV;
2696                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2697                  }                  }
2698                    }
2699    
2700                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2701                  {                          iSAD =
2702                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2703                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2704                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2705                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, /*iDiamondSize*/ 2, iFcode, iQuant, 0);                                                                    iQuant, 0);
2706    
2707                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2708                                  *currMV = newMV;                                  *currMV = newMV;
2709                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2710                          }                          }
# Line 1751  Line 2713 
2713    
2714  /***************        Choose best MV found     **************/  /***************        Choose best MV found     **************/
2715    
2716  EPZS16_Terminate_with_Refine:    EPZS8_Terminate_with_Refine:
2717          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step
2718                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2719                                  x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2720                                  currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2721                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
   
 EPZS16_Terminate_without_Refine:  
2722    
2723          *oldMB = *pMB;    EPZS8_Terminate_without_Refine:
2724    
2725          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2726          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2727          return iMinSAD;          return iMinSAD;
2728  }  }
2729    
2730    
2731  int32_t EPZSSearch8(  
2732                                          const uint8_t * const pRef,  int32_t
2733    PMVfastIntSearch16(const uint8_t * const pRef,
2734                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2735                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2736                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2737                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2738                                          const int x, const int y,                                  const int x,
2739                                          const int start_x, const int start_y,                                  const int y,
2740                            const int start_x,
2741                            const int start_y,
2742                            const int center_x,
2743                            const int center_y,
2744                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2745                                    const uint32_t iQuant,
2746                                    const uint32_t iFcode,
2747                                          const MBParam * const pParam,                                          const MBParam * const pParam,
2748                                          MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
2749                                    const MACROBLOCK * const prevMBs,
2750                                          VECTOR * const currMV,                                          VECTOR * const currMV,
2751                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
2752  {  {
2753          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;  
   
2754          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
2755          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
2756          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
2757    
2758          const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;          const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
2759            const VECTOR zeroMV = { 0, 0 };
2760    
2761          int32_t iDiamondSize=1;          int32_t iDiamondSize;
2762    
2763          int32_t min_dx;          int32_t min_dx;
2764          int32_t max_dx;          int32_t max_dx;
2765          int32_t min_dy;          int32_t min_dy;
2766          int32_t max_dy;          int32_t max_dy;
2767    
2768            int32_t iFound;
2769    
2770          VECTOR newMV;          VECTOR newMV;
2771          VECTOR backupMV;          VECTOR backupMV;                        /* just for PMVFAST */
2772    
2773          VECTOR pmv[4];          VECTOR pmv[4];
2774          int32_t psad[8];          int32_t psad[4];
2775    
2776          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);          MainSearch16FuncPtr MainSearchPtr;
2777    
2778          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2779            MACROBLOCK *const pMB = pMBs + x + y * iWcount;
2780    
2781            int32_t threshA, threshB;
2782          int32_t bPredEq;          int32_t bPredEq;
2783          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD, iSAD;
2784    
         MainSearch8FuncPtr EPZSMainSearchPtr;  
2785    
2786  /* Get maximum range */  /* Get maximum range */
2787          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,
2788                          x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2789    
2790  /* 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 */
2791    
2792          if (!(MotionFlags & PMV_HALFPEL8 ))          if ((x == 0) && (y == 0)) {
2793          { min_dx = EVEN(min_dx);                  threshA = 512;
2794            max_dx = EVEN(max_dx);                  threshB = 1024;
2795            min_dy = EVEN(min_dy);  
2796            max_dy = EVEN(max_dy);                  bPredEq = 0;
2797          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */                  psad[0] = psad[1] = psad[2] = psad[3] = 0;
2798                    *currMV = pmv[0] = pmv[1] = pmv[2] = pmv[3] = zeroMV;
2799    
2800            } else {
2801                    threshA = psad[0];
2802                    threshB = threshA + 256;
2803                    if (threshA < 512)
2804                            threshA = 512;
2805                    if (threshA > 1024)
2806                            threshA = 1024;
2807                    if (threshB > 1792)
2808                            threshB = 1792;
2809    
2810          bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);                  bPredEq = get_ipmvdata(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2811                    *currMV = pmv[0];                       /* current best := prediction */
2812            }
2813    
2814            iFound = 0;
2815    
2816  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2817          MinSAD=SAD          MinSAD=SAD
# Line 1837  Line 2820 
2820          If SAD<=256 goto Step 10.          If SAD<=256 goto Step 10.
2821  */  */
2822    
2823  // Prepare for main loop          if (currMV->x > max_dx) {
2824                    currMV->x = EVEN(max_dx);
2825            }
2826            if (currMV->x < min_dx) {
2827                    currMV->x = EVEN(min_dx);
2828            }
2829            if (currMV->y > max_dy) {
2830                    currMV->y = EVEN(max_dy);
2831            }
2832            if (currMV->y < min_dy) {
2833                    currMV->y = EVEN(min_dy);
2834            }
2835    
2836            iMinSAD =
2837                    sad16(cur,
2838                              get_iref_mv(pRef, x, y, 16, currMV,
2839                                                     iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2840            iMinSAD +=
2841                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2842                                              (uint8_t) iFcode, iQuant);
2843    
2844            if ((iMinSAD < 256) ||
2845                    ((MVequal(*currMV, prevMB->i_mvs[0])) &&
2846                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2847                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
2848                    {
2849                            if (!MVzero(*currMV)) {
2850                                    iMinSAD += MV16_00_BIAS;
2851                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
2852                                    iMinSAD -= MV16_00_BIAS;
2853                            }
2854                    }
2855    
2856          if (!(MotionFlags & PMV_HALFPEL8))                  if (MotionFlags & PMV_EARLYSTOP16)
2857          {                          goto PMVfastInt16_Terminate_with_Refine;
                 currMV->x = EVEN(currMV->x);  
                 currMV->y = EVEN(currMV->y);  
2858          }          }
2859    
         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;  
2860    
2861  /***************** This is predictor SET A: only median prediction ******************/  /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2862       vector of the median.
2863       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2864    */
2865    
2866            if ((bPredEq) && (MVequal(pmv[0], prevMB->i_mvs[0])))
2867                    iFound = 2;
2868    
2869          iMinSAD = sad8( cur,  /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2870                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),     Otherwise select large Diamond Search.
2871                  iEdgedWidth);  */
         iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;  
2872    
2873            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
2874                    iDiamondSize = 2;               // halfpel units!
2875            else
2876                    iDiamondSize = 4;               // halfpel units!
2877    
2878  // thresh1 is fixed to 256  /*
2879          if (iMinSAD < 256/4 )     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
2880                  {     Also calculate (0,0) but do not subtract offset.
2881                          if (MotionFlags & PMV_QUICKSTOP8)     Let MinSAD be the smallest SAD up to this point.
2882                                  goto EPZS8_Terminate_without_Refine;     If MV is (0,0) subtract offset.
2883                          if (MotionFlags & PMV_EARLYSTOP8)  */
                                 goto EPZS8_Terminate_with_Refine;  
                 }  
2884    
2885  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  // (0,0) is often a good choice
2886    
2887  // previous frame MV          if (!MVzero(pmv[0]))
2888          CHECK_MV8_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);                  CHECK_MV16_ZERO;
2889    
2890  // MV=(0,0) is often a good choice  // previous frame MV is always possible
2891    
2892          CHECK_MV8_ZERO;          if (!MVzero(prevMB->i_mvs[0]))
2893                    if (!MVequal(prevMB->i_mvs[0], pmv[0]))
2894                            CHECK_MV16_CANDIDATE(prevMB->i_mvs[0].x, prevMB->i_mvs[0].y);
2895    
2896  /* Terminate if MinSAD <= T_2  // left neighbour, if allowed
2897     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]  
2898            if (!MVzero(pmv[1]))
2899                    if (!MVequal(pmv[1], prevMB->i_mvs[0]))
2900                            if (!MVequal(pmv[1], pmv[0]))
2901                                    CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
2902    
2903    // top neighbour, if allowed
2904            if (!MVzero(pmv[2]))
2905                    if (!MVequal(pmv[2], prevMB->i_mvs[0]))
2906                            if (!MVequal(pmv[2], pmv[0]))
2907                                    if (!MVequal(pmv[2], pmv[1]))
2908                                            CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
2909    
2910    // top right neighbour, if allowed
2911                                            if (!MVzero(pmv[3]))
2912                                                    if (!MVequal(pmv[3], prevMB->i_mvs[0]))
2913                                                            if (!MVequal(pmv[3], pmv[0]))
2914                                                                    if (!MVequal(pmv[3], pmv[1]))
2915                                                                            if (!MVequal(pmv[3], pmv[2]))
2916                                                                                    CHECK_MV16_CANDIDATE(pmv[3].x,
2917                                                                                                                             pmv[3].y);
2918    
2919            if ((MVzero(*currMV)) &&
2920                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2921                    iMinSAD -= MV16_00_BIAS;
2922    
2923    
2924    /* Step 6: If MinSAD <= thresa goto Step 10.
2925       If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
2926  */  */
2927    
2928          if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */          if ((iMinSAD <= threshA) ||
2929                  {                  (MVequal(*currMV, prevMB->i_mvs[0]) &&
2930                          if (MotionFlags & PMV_QUICKSTOP8)                   ((int32_t) iMinSAD < prevMB->i_sad16))) {
2931                                  goto EPZS8_Terminate_without_Refine;  
2932                          if (MotionFlags & PMV_EARLYSTOP8)                  if (MotionFlags & PMV_EARLYSTOP16)
2933                                  goto EPZS8_Terminate_with_Refine;                          goto PMVfastInt16_Terminate_with_Refine;
2934                  }                  }
2935    
 /************ (if Diamond Search)  **************/  
2936    
2937          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */  /************ (Diamond Search)  **************/
2938    /*
2939       Step 7: Perform Diamond search, with either the small or large diamond.
2940       If Found=2 only examine one Diamond pattern, and afterwards goto step 10
2941       Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
2942       If center then goto step 10.
2943       Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
2944       Refine by using small diamond and goto step 10.
2945    */
2946    
2947          if (!(MotionFlags & PMV_HALFPELDIAMOND8))          if (MotionFlags & PMV_USESQUARES16)
2948                  iDiamondSize *= 2;                  MainSearchPtr = Square16_MainSearch;
2949            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2950                    MainSearchPtr = AdvDiamond16_MainSearch;
2951            else
2952                    MainSearchPtr = Diamond16_MainSearch;
2953    
2954  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */          backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2955    
 //      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);  
2956    
2957    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2958            iSAD =
2959                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2960                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2961                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2962                                                      iQuant, iFound);
2963    
2964          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2965                  *currMV = newMV;                  *currMV = newMV;
2966                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2967          }          }
2968    
2969          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH16) {
2970          {  /* 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) */  
2971    
2972                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2973                  {                          iSAD =
2974                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2975                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2976                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2977                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, iFound);
2978    
2979                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2980                                  *currMV = newMV;                                  *currMV = newMV;
2981                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2982                          }                          }
2983                  }                  }
2984    
2985                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2986                  {                          iSAD =
2987                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2988                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2989                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2990                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iQuant, iFound);
2991    
2992                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2993                                  *currMV = newMV;                                  *currMV = newMV;
2994                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2995                          }                          }
2996                  }                  }
2997          }          }
2998    
2999  /***************        Choose best MV found     **************/  /*
3000       Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.
3001    */
3002    
3003  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);  
3004    
3005  EPZS8_Terminate_without_Refine:          pMB->i_mvs[0] = pMB->i_mvs[1] = pMB->i_mvs[2] = pMB->i_mvs[3] = pMB->i_mv16 = *currMV;
3006            pMB->i_sad8[0] = pMB->i_sad8[1] = pMB->i_sad8[2] = pMB->i_sad8[3] = pMB->i_sad16 = iMinSAD;
3007    
3008          currPMV->x = currMV->x - pmv[0].x;          if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
3009          currPMV->y = currMV->y - pmv[0].y;                  iMinSAD =
3010                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
3011                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
3012                                                             iFcode, iQuant, iEdgedWidth);
3013    
3014            pmv[0] = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          // get _REAL_ prediction (halfpel possible)
3015    
3016    PMVfastInt16_Terminate_without_Refine:
3017            currPMV->x = currMV->x - center_x;
3018            currPMV->y = currMV->y - center_y;
3019          return iMinSAD;          return iMinSAD;
3020  }  }
3021    
3022    
3023    
3024    /* ***********************************************************
3025            bvop motion estimation
3026    // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)
3027    ***************************************************************/
3028    
3029    
3030    #define DIRECT_PENALTY 0
3031    #define DIRECT_UPPERLIMIT 256   // never use direct mode if SAD is larger than this
3032    
3033    void
3034    MotionEstimationBVOP(MBParam * const pParam,
3035                                             FRAMEINFO * const frame,
3036                                             const int32_t time_bp,
3037                                             const int32_t time_pp,
3038                                             // forward (past) reference
3039                                             const MACROBLOCK * const f_mbs,
3040                                             const IMAGE * const f_ref,
3041                                             const IMAGE * const f_refH,
3042                                             const IMAGE * const f_refV,
3043                                             const IMAGE * const f_refHV,
3044                                             // backward (future) reference
3045                                             const MACROBLOCK * const b_mbs,
3046                                             const IMAGE * const b_ref,
3047                                             const IMAGE * const b_refH,
3048                                             const IMAGE * const b_refV,
3049                                             const IMAGE * const b_refHV)
3050    {
3051            const int mb_width = pParam->mb_width;
3052            const int mb_height = pParam->mb_height;
3053            const int edged_width = pParam->edged_width;
3054    
3055            int i, j, k;
3056    
3057            static const VECTOR zeroMV={0,0};
3058    
3059            int f_sad16;    /* forward (as usual) search */
3060            int b_sad16;    /* backward (only in b-frames) search */
3061            int i_sad16;    /* interpolated (both direction, b-frames only) */
3062            int d_sad16;    /* direct mode (assume linear motion) */
3063    
3064            int best_sad;
3065    
3066            VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/
3067            VECTOR pmv_dontcare;
3068    
3069            int f_count=0;
3070            int b_count=0;
3071            int i_count=0;
3072            int d_count=0;
3073            int s_count=0;
3074    
3075            const int64_t TRB = (int32_t)time_pp - (int32_t)time_bp;
3076        const int64_t TRD = (int32_t)time_pp;
3077    
3078            // fprintf(stderr,"TRB = %lld  TRD = %lld  time_bp =%d time_pp =%d\n\n",TRB,TRD,time_bp,time_pp);
3079            // note: i==horizontal, j==vertical
3080            for (j = 0; j < mb_height; j++) {
3081    
3082                    f_predMV = zeroMV;      /* prediction is reset at left boundary */
3083                    b_predMV = zeroMV;
3084    
3085                    for (i = 0; i < mb_width; i++) {
3086                            MACROBLOCK *mb = &frame->mbs[i + j * mb_width];
3087                            const MACROBLOCK *f_mb = &f_mbs[i + j * mb_width];
3088                            const MACROBLOCK *b_mb = &b_mbs[i + j * mb_width];
3089    
3090                            mb->deltamv=zeroMV;
3091    
3092    /* special case, if collocated block is SKIPed: encoding is forward(0,0)  */
3093    
3094    #ifndef _DISABLE_SKIP
3095                            if (b_mb->mode == MODE_INTER && b_mb->cbp == 0 &&
3096                                    b_mb->mvs[0].x == 0 && b_mb->mvs[0].y == 0) {
3097                                    mb->mode = MODE_NOT_CODED;
3098                                    mb->mvs[0].x = 0;
3099                                    mb->mvs[0].y = 0;
3100                                    mb->b_mvs[0].x = 0;
3101                                    mb->b_mvs[0].y = 0;
3102                                    continue;
3103                            }
3104    #endif
3105    
3106                            d_sad16 = DIRECT_PENALTY;
3107    
3108                            if (b_mb->mode == MODE_INTER4V)
3109                            {
3110    
3111                            /* same method of scaling as in decoder.c, so we copy from there */
3112                        for (k = 0; k < 4; k++) {
3113    
3114                                            mb->directmv[k] = b_mb->mvs[k];
3115    
3116                                            mb->mvs[k].x = (int32_t) ((TRB * mb->directmv[k].x) / TRD + mb->deltamv.x);
3117                        mb->b_mvs[k].x = (int32_t) ((mb->deltamv.x == 0)
3118                                                                                    ? ((TRB - TRD) * mb->directmv[k].x) / TRD
3119                                                : mb->mvs[k].x - mb->directmv[k].x);
3120    
3121                        mb->mvs[k].y = (int32_t) ((TRB * mb->directmv[k].y) / TRD + mb->deltamv.y);
3122                            mb->b_mvs[k].y = (int32_t) ((mb->directmv[k].y == 0)
3123                                                                                    ? ((TRB - TRD) * mb->directmv[k].y) / TRD
3124                                                : mb->mvs[k].y - mb->directmv[k].y);
3125    
3126                                            d_sad16 +=
3127                                                    sad8bi(frame->image.y + 2*(i+(k&1))*8 + 2*(j+(k>>1))*8*edged_width,
3128                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3129                                                                    2*(i+(k&1)), 2*(j+(k>>1)), 8, &mb->mvs[k], edged_width),
3130                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3131                                                                    2*(i+(k&1)), 2*(j+(k>>1)), 8, &mb->b_mvs[k], edged_width),
3132                                                      edged_width);
3133                                    }
3134                            }
3135                            else
3136                            {
3137                                    mb->directmv[3] = mb->directmv[2] = mb->directmv[1] =
3138                                    mb->directmv[0] = b_mb->mvs[0];
3139    
3140                                    mb->mvs[0].x = (int32_t) ((TRB * mb->directmv[0].x) / TRD + mb->deltamv.x);
3141                        mb->b_mvs[0].x = (int32_t) ((mb->deltamv.x == 0)
3142                                                                            ? ((TRB - TRD) * mb->directmv[0].x) / TRD
3143                                        : mb->mvs[0].x - mb->directmv[0].x);
3144    
3145                        mb->mvs[0].y = (int32_t) ((TRB * mb->directmv[0].y) / TRD + mb->deltamv.y);
3146                    mb->b_mvs[0].y = (int32_t) ((mb->directmv[0].y == 0)
3147                                                                            ? ((TRB - TRD) * mb->directmv[0].y) / TRD
3148                                        : mb->mvs[0].y - mb->directmv[0].y);
3149    
3150                                    d_sad16 += sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,
3151                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3152                                                                    i, j, 16, &mb->mvs[0], edged_width),
3153                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3154                                                                    i, j, 16, &mb->b_mvs[0], edged_width),
3155                                                      edged_width);
3156    
3157                }
3158                        d_sad16 += calc_delta_16(mb->deltamv.x, mb->deltamv.y, 1, frame->quant);
3159    
3160                            // forward search
3161                            f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3162                                                    &frame->image, i, j,
3163                                                    mb->mvs[0].x, mb->mvs[0].y,                     /* start point f_directMV */
3164                                                    f_predMV.x, f_predMV.y,                         /* center is f-prediction */
3165                                                    frame->motion_flags,
3166                                                    frame->quant, frame->fcode, pParam,
3167                                                    f_mbs, f_mbs,
3168                                                    &mb->mvs[0], &pmv_dontcare);
3169    
3170    
3171                            // backward search
3172                            b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3173                                                    &frame->image, i, j,
3174                                                    mb->b_mvs[0].x, mb->b_mvs[0].y,         /* start point b_directMV */
3175                                                    b_predMV.x, b_predMV.y,                         /* center is b-prediction */
3176                                                    frame->motion_flags,
3177                                                    frame->quant, frame->bcode, pParam,
3178                                                    b_mbs, b_mbs,
3179                                                    &mb->b_mvs[0], &pmv_dontcare);
3180    
3181                            i_sad16 =
3182                                    sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,
3183                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3184                                                                    i, j, 16, &mb->mvs[0], edged_width),
3185                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3186                                                                    i, j, 16, &mb->b_mvs[0], edged_width),
3187                                                      edged_width);
3188                        i_sad16 += calc_delta_16(mb->mvs[0].x-f_predMV.x, mb->mvs[0].y-f_predMV.y,
3189                                                                    frame->fcode, frame->quant);
3190                        i_sad16 += calc_delta_16(mb->b_mvs[0].x-b_predMV.x, mb->b_mvs[0].y-b_predMV.y,
3191                                                                    frame->bcode, frame->quant);
3192    
3193                            // TODO: direct search
3194                            // predictor + delta vector in range [-32,32] (fcode=1)
3195    
3196                            i_sad16 = 65535;
3197                            f_sad16 = 65535;
3198                            b_sad16 = 65535;
3199    //                      d_sad16 = 65535;
3200    
3201                            if (f_sad16 < b_sad16) {
3202                                    best_sad = f_sad16;
3203                                    mb->mode = MODE_FORWARD;
3204                            } else {
3205                                    best_sad = b_sad16;
3206                                    mb->mode = MODE_BACKWARD;
3207                            }
3208    
3209                            if (i_sad16 < best_sad) {
3210                                    best_sad = i_sad16;
3211                                    mb->mode = MODE_INTERPOLATE;
3212                            }
3213    
3214                            if (d_sad16 < best_sad) {
3215    
3216                                    if (b_mb->mode == MODE_INTER4V)
3217                                    {
3218    
3219                                    /* same method of scaling as in decoder.c, so we copy from there */
3220                                for (k = 0; k < 4; k++) {
3221    
3222                                                    mb->mvs[k].x = (int32_t) ((TRB * mb->directmv[k].x) / TRD + mb->deltamv.x);
3223                                mb->b_mvs[k].x = (int32_t) ((mb->deltamv.x == 0)
3224                                                                                            ? ((TRB - TRD) * mb->directmv[k].x) / TRD
3225                                                        : mb->mvs[k].x - mb->directmv[k].x);
3226    
3227                                mb->mvs[k].y = (int32_t) ((TRB * mb->directmv[k].y) / TRD + mb->deltamv.y);
3228                            mb->b_mvs[k].y = (int32_t) ((mb->directmv[k].y == 0)
3229                                                                                            ? ((TRB - TRD) * mb->directmv[k].y) / TRD
3230                                                : mb->mvs[k].y - mb->directmv[k].y);
3231                                            }
3232                                    }
3233                                    else
3234                                    {
3235                                            mb->mvs[0].x = (int32_t) ((TRB * mb->directmv[0].x) / TRD + mb->deltamv.x);
3236    
3237                        mb->b_mvs[0].x = (int32_t) ((mb->deltamv.x == 0)
3238                                                                                    ? ((TRB - TRD) * mb->directmv[0].x) / TRD
3239                                            : mb->mvs[0].x - mb->directmv[0].x);
3240    
3241                                mb->mvs[0].y = (int32_t) ((TRB * mb->directmv[0].y) / TRD + mb->deltamv.y);
3242    
3243                            mb->b_mvs[0].y = (int32_t) ((mb->directmv[0].y == 0)
3244                                                                                    ? ((TRB - TRD) * mb->directmv[0].y) / TRD
3245                                                : mb->mvs[0].y - mb->directmv[0].y);
3246    
3247                                            mb->mvs[3] = mb->mvs[2] = mb->mvs[1] = mb->mvs[0];
3248                                            mb->b_mvs[3] = mb->b_mvs[2] = mb->b_mvs[1] = mb->b_mvs[0];
3249                    }
3250    
3251                                    best_sad = d_sad16;
3252                                    mb->mode = MODE_DIRECT;
3253                                    mb->mode = MODE_INTERPOLATE;            // direct mode still broken :-(
3254                            }
3255    
3256                            switch (mb->mode)
3257                            {
3258                                    case MODE_FORWARD:
3259                                            f_count++;
3260                                            f_predMV = mb->mvs[0];
3261                                            break;
3262                                    case MODE_BACKWARD:
3263                                            b_count++;
3264                                            b_predMV = mb->b_mvs[0];
3265    
3266                                            break;
3267                                    case MODE_INTERPOLATE:
3268                                            i_count++;
3269                                            f_predMV = mb->mvs[0];
3270                                            b_predMV = mb->b_mvs[0];
3271                                            break;
3272                                    case MODE_DIRECT:
3273                                            d_count++;
3274                                            break;
3275                                    default:
3276                                            s_count++;              // ???
3277                                            break;
3278                            }
3279    
3280                    }
3281            }
3282    
3283    #ifdef _DEBUG_BFRAME_STAT
3284            fprintf(stderr,"B-Stat: F: %04d   B: %04d   I: %04d  D: %04d   S: %04d\n",
3285                                    f_count,b_count,i_count,d_count,s_count);
3286    #endif
3287    
3288    }

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

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