[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 167, Tue May 7 20:03:18 2002 UTC revision 346, Sun Jul 28 02:55:41 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   *      01.05.2002      updated MotionEstimationBVOP
# Line 47  Line 77 
77  #include "motion.h"  #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)  
 #define MV8_00_BIAS     (0)  
   
 /* 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)  
   
   
 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 uint32_t iQuant,  
                                         const uint32_t iFcode,  
                                         const MBParam * const pParam,  
                                         const MACROBLOCK * const pMBs,  
                                         const MACROBLOCK * const prevMBs,  
                                         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 uint32_t iQuant,  
                                         const uint32_t iFcode,  
                                         const MBParam * const pParam,  
                                         const MACROBLOCK * const pMBs,  
                                         const MACROBLOCK * const prevMBs,  
                                         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, const int start_y,  
                                         const uint32_t MotionFlags,  
                                         const uint32_t iQuant,  
                                         const uint32_t iFcode,  
                                         const MBParam * const pParam,  
                                         const MACROBLOCK * const pMBs,  
                                         const MACROBLOCK * const prevMBs,  
                                         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, const int start_y,  
                                         const uint32_t MotionFlags,  
                                         const uint32_t iQuant,  
                                         const uint32_t iFcode,  
                                         const MBParam * const pParam,  
                                         const MACROBLOCK * const pMBs,  
                                         const MACROBLOCK * const prevMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
   
 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);  
   
 typedef MainSearch16Func* MainSearch16FuncPtr;  
   
   
 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);  
80    
 typedef MainSearch8Func* MainSearch8FuncPtr;  
81    
82  static int32_t lambda_vec16[32] =  /* rounded values for lambda param for weight of motion bits as in modified H.26L */  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), (int)(1.49591+0.5), (int)(1.68601+0.5),  { 0, (int) (1.00235 + 0.5), (int) (1.15582 + 0.5), (int) (1.31976 + 0.5),
84          (int)(1.89187+0.5), (int)(2.11542+0.5), (int)(2.35878+0.5), (int)(2.62429+0.5), (int)(2.91455+0.5),                  (int) (1.49591 + 0.5), (int) (1.68601 + 0.5),
85          (int)(3.23253+0.5), (int)(3.58158+0.5), (int)(3.96555+0.5), (int)(4.38887+0.5), (int)(4.85673+0.5),          (int) (1.89187 + 0.5), (int) (2.11542 + 0.5), (int) (2.35878 + 0.5),
86          (int)(5.37519+0.5), (int)(5.95144+0.5), (int)(6.59408+0.5), (int)(7.31349+0.5), (int)(8.12242+0.5),                  (int) (2.62429 + 0.5), (int) (2.91455 + 0.5),
87          (int)(9.03669+0.5), (int)(10.0763+0.5), (int)(11.2669+0.5), (int)(12.6426+0.5), (int)(14.2493+0.5),          (int) (3.23253 + 0.5), (int) (3.58158 + 0.5), (int) (3.96555 + 0.5),
88          (int)(16.1512+0.5), (int)(18.442+0.5),  (int)(21.2656+0.5), (int)(24.8580+0.5), (int)(29.6436+0.5),                  (int) (4.38887 + 0.5), (int) (4.85673 + 0.5),
89          (int)(36.4949+0.5)      };          (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*/  static int32_t *lambda_vec8 = lambda_vec16;     /* same table for INTER and INTER4V for now*/
99    
# Line 207  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 215  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 233  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, const uint32_t iQuant)  static __inline uint32_t
139    calc_delta_16(const int32_t dx,
140                              const int32_t dy,
141                              const uint32_t iFcode,
142                              const uint32_t iQuant)
143  {  {
144          return NEIGH_TEND_16X16 * lambda_vec16[iQuant] * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));          return NEIGH_TEND_16X16 * lambda_vec16[iQuant] * (mv_bits(dx, iFcode) +
145                                                                                                              mv_bits(dy, iFcode));
146  }  }
147    
148  static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode, const uint32_t iQuant)  static __inline uint32_t
149    calc_delta_8(const int32_t dx,
150                             const int32_t dy,
151                             const uint32_t iFcode,
152                             const uint32_t iQuant)
153  {  {
154      return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));          return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) +
155                                                                                                       mv_bits(dy, iFcode));
156  }  }
157    
158    bool
159    MotionEstimation(MBParam * const pParam,
   
   
 #ifndef SEARCH16  
 #define SEARCH16        PMVfastSearch16  
 //#define SEARCH16      FullSearch16  
 //#define SEARCH16      EPZSSearch16  
 #endif  
   
 #ifndef SEARCH8  
 #define SEARCH8         PMVfastSearch8  
 //#define SEARCH8       EPZSSearch8  
 #endif  
   
 bool MotionEstimation(  
         MBParam * const pParam,  
160          FRAMEINFO * const current,          FRAMEINFO * const current,
161          FRAMEINFO * const reference,          FRAMEINFO * const reference,
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,
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 * pMBs = current->mbs;          MACROBLOCK *const pMBs = current->mbs;
170          IMAGE * pCurrent = &current->image;          MACROBLOCK *const prevMBs = reference->mbs;
171            const IMAGE *const pCurrent = &current->image;
172          MACROBLOCK * prevMBs = reference->mbs;  // previous frame          const IMAGE *const pRef = &reference->image;
173          IMAGE * pRef = &reference->image;  
174            static const VECTOR zeroMV = { 0, 0 };
175            VECTOR predMV;
176          uint32_t i, j, iIntra = 0;  
177            int32_t x, y;
178          VECTOR mv16;          int32_t iIntra = 0;
179          VECTOR pmv16;          VECTOR pmv;
   
         int32_t sad8 = 0;  
         int32_t sad16;  
         int32_t deviation;  
180    
181          if (sadInit)          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];  
                         MACROBLOCK *prevMB = &prevMBs[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, current->motion_flags, current->quant, current->fcode,  
                                          pParam, pMBs, prevMBs, &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                                  pMB->mode = MODE_INTRA;                                                    pParam->edged_width);
                                 pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;  
                                 pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;  
204    
205                                  pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = 0;                                  if (deviation < (pMB->sad16 - MV16_INTER_BIAS)) {
206                                            pMB->mode = MODE_INTRA;
207                                            pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
208                                                    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 323  Line 215 
215    
216                                  continue;                                  continue;
217                          }                          }
218                            }
219    
220                            pmv = pMB->pmvs[0];
221                          if (current->global_flags & XVID_INTER4V)                          if (current->global_flags & XVID_INTER4V)
222                          {                                  if ((!(current->global_flags & XVID_LUMIMASKING) ||
223                                  pMB->sad8[0] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                           pMB->dquant == NO_CHANGE)) {
224                                                         2 * j, 2 * i, mv16.x, mv16.y,                                          int32_t sad8 = IMV16X16 * current->quant;
225                                                             current->motion_flags, current->quant, current->fcode,  
226                                                         pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]);                                          if (sad8 < pMB->sad16) {
227                                                    sad8 += pMB->sad8[0] =
228                                  pMB->sad8[1] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
229                                                         2 * j + 1, 2 * i, mv16.x, mv16.y,                                                                          pCurrent, 2 * x, 2 * y,
230                                                             current->motion_flags, current->quant, current->fcode,                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
231                                                         pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]);                                                                          current->motion_flags,
232                                                                            current->quant, current->fcode, pParam,
233                                  pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                                          pMBs, prevMBs, &pMB->mvs[0],
234                                                         2 * j, 2 * i + 1, mv16.x, mv16.y,                                                                          &pMB->pmvs[0]);
235                                                             current->motion_flags, current->quant, current->fcode,                                          }
236                                                         pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]);                                          if (sad8 < pMB->sad16) {
237    
238                                  pMB->sad8[3] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                  predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 1);
239                                                         2 * j + 1, 2 * i + 1, mv16.x, mv16.y,                                                  sad8 += pMB->sad8[1] =
240                                                             current->motion_flags, current->quant, current->fcode,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
241                                                         pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]);                                                                          pCurrent, 2 * x + 1, 2 * y,
242                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
243                                  sad8 = pMB->sad8[0] + pMB->sad8[1] + pMB->sad8[2] + pMB->sad8[3];                                                                          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 (!(current->global_flags & XVID_LUMIMASKING) || pMB->dquant == NO_CHANGE)                                          if (sad8 < pMB->sad16) {
                         {  
                                 if (((current->global_flags & XVID_INTER4V)==0) ||  
                                     (sad16 < (sad8 + (int32_t)(IMV16X16 * current->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->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = sad16;  
                                         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;                                          pMB->sad8[0] *= 4;
279                                          pMB->sad8[1] *= 4;                                          pMB->sad8[1] *= 4;
280                                          pMB->sad8[2] *= 4;                                          pMB->sad8[2] *= 4;
281                                          pMB->sad8[3] *= 4;                                          pMB->sad8[3] *= 4;
282                                                    continue;
283                                  }                                  }
284    
285                          }                          }
                         else  
                         {  
                                 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->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = sad16;  
286    
287                                  pMB->pmvs[0].x = pmv16.x;                          pMB->mode = MODE_INTER;
288                                  pMB->pmvs[0].y = pmv16.y;                          pMB->pmvs[0] = pmv;     /* pMB->pmvs[1] = pMB->pmvs[2] = pMB->pmvs[3]  are not needed for INTER */
289                            pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
290                            pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =
291                                    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);\
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 420  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 430  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 440  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 448  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 456  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 466  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 476  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 486  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 512  Line 410 
410          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
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    
416          get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);          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 524  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 554  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 566  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 613  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 629  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 743  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 753  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 */
770          CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y-1);  
771          CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y-1);                          if (iDirection)         //checking if anything found
772          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y);                          {
773          CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y);                                  bDirection = iDirection;
774          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y+1);                                  iDirection = 0;
775          CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y+1);                                  start_x = currMV->x;
776          CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y+1);                                  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                                    if (iDirection) {
788                                            bDirection += iDirection;
789                                            start_x = currMV->x;
790                                            start_y = currMV->y;
791                                    }
792                            } else                          //about to quit, eh? not so fast....
793                            {
794                                    switch (bDirection) {
795                                    case 2:
796                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
797                                                                                             start_y - iDiamondSize, 2 + 4);
798                                            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;          return iMinSAD;
875  }  }
876    
877  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  #define CHECK_MV16_F_INTERPOL(X,Y) { \
878      if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
879        && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
880      { \
881        iSAD = sad16bi( cur, \
882                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
883                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
884                            iEdgedWidth); \
885        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
886        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
887        if (iSAD < iMinSAD) \
888        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); } } \
889    }
890    
891    #define CHECK_MV16_F_INTERPOL_FOUND(X,Y) { \
892      if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
893        && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
894      { \
895        iSAD = sad16bi( cur, \
896                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
897                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
898                            iEdgedWidth); \
899        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
900        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
901        if (iSAD < iMinSAD) \
902        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); iFound=0;} } \
903    }
904    
905  int32_t PMVfastSearch16(  #define CHECK_MV16_B_INTERPOL(X,Y) { \
906                                          const uint8_t * const pRef,    if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
907        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
908      { \
909        iSAD = sad16bi( cur, \
910                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
911                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
912                            iEdgedWidth); \
913        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
914        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
915        if (iSAD < iMinSAD) \
916        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); } } \
917    }
918    
919    #define CHECK_MV16_B_INTERPOL_FOUND(X,Y) { \
920      if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
921        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
922      { \
923        iSAD = sad16bi( cur, \
924                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
925                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
926                            iEdgedWidth); \
927        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
928        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
929        if (iSAD < iMinSAD) \
930        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); iFound=0;} } \
931    }
932    
933    int32_t
934    Diamond16_InterpolMainSearch(
935                                            const uint8_t * const f_pRef,
936                                             const uint8_t * const f_pRefH,
937                                             const uint8_t * const f_pRefV,
938                                             const uint8_t * const f_pRefHV,
939    
940                                             const uint8_t * const cur,
941    
942                                            const uint8_t * const b_pRef,
943                                             const uint8_t * const b_pRefH,
944                                             const uint8_t * const b_pRefV,
945                                             const uint8_t * const b_pRefHV,
946    
947                                             const int x,
948                                             const int y,
949    
950                                       const int f_start_x,
951                                       const int f_start_y,
952                                       const int b_start_x,
953                                       const int b_start_y,
954    
955                                       int iMinSAD,
956                                       VECTOR * const f_currMV,
957                                       VECTOR * const b_currMV,
958    
959                                       const int f_center_x,
960                                       const int f_center_y,
961                                       const int b_center_x,
962                                       const int b_center_y,
963    
964                                        const int32_t f_min_dx,
965                                            const int32_t f_max_dx,
966                                            const int32_t f_min_dy,
967                                            const int32_t f_max_dy,
968    
969                                        const int32_t b_min_dx,
970                                            const int32_t b_max_dx,
971                                            const int32_t b_min_dy,
972                                            const int32_t b_max_dy,
973    
974                                            const int32_t iEdgedWidth,
975                                            const int32_t iDiamondSize,
976    
977                                            const int32_t f_iFcode,
978                                            const int32_t b_iFcode,
979    
980                                            const int32_t iQuant,
981                                            int iFound)
982    {
983    /* Do a diamond search around given starting point, return SAD of best */
984    
985            int32_t iSAD;
986    
987            VECTOR f_backupMV;
988            VECTOR b_backupMV;
989    
990            f_currMV->x = f_start_x;
991            f_currMV->y = f_start_y;
992            b_currMV->x = b_start_x;
993            b_currMV->y = b_start_y;
994    
995            do
996            {
997                    iFound = 1;
998    
999                    f_backupMV = *f_currMV;
1000    
1001                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x - iDiamondSize, f_backupMV.y);
1002                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x + iDiamondSize, f_backupMV.y);
1003                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y - iDiamondSize);
1004                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y + iDiamondSize);
1005    
1006                    b_backupMV = *b_currMV;
1007    
1008                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x - iDiamondSize, b_backupMV.y);
1009                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x + iDiamondSize, b_backupMV.y);
1010                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y - iDiamondSize);
1011                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y + iDiamondSize);
1012    
1013            } while (!iFound);
1014    
1015            return iMinSAD;
1016    }
1017    
1018    /* Sorry, these MACROS really got too large... I'll turn them into function soon! */
1019    
1020    #define CHECK_MV16_DIRECT_FOUND(X,Y) \
1021            if ( (X)>=(-32) && (X)<=(31) && ((Y)>=-32) && ((Y)<=31) ) \
1022            { int k;\
1023            VECTOR mvs,b_mvs;       \
1024            iSAD = 0;\
1025            for (k = 0; k < 4; k++) {       \
1026                                            mvs.x = (int32_t) ((TRB * directmv[k].x) / TRD + (X));          \
1027                        b_mvs.x = (int32_t) (((X) == 0)                                                     \
1028                                                                                    ? ((TRB - TRD) * directmv[k].x) / TRD   \
1029                                                : mvs.x - directmv[k].x);                           \
1030                                                                                                                                                                    \
1031                        mvs.y = (int32_t) ((TRB * directmv[k].y) / TRD + (Y));              \
1032                            b_mvs.y = (int32_t) (((Y) == 0)                                                         \
1033                                                                                    ? ((TRB - TRD) * directmv[k].y) / TRD   \
1034                                                : mvs.y - directmv[k].y);                           \
1035                                                                                                                                                                    \
1036      if ( (mvs.x <= max_dx) && (mvs.x >= min_dx) \
1037        && (mvs.y <= max_dy) && (mvs.y >= min_dy)  \
1038            && (b_mvs.x <= max_dx) && (b_mvs.x >= min_dx)  \
1039        && (b_mvs.y <= max_dy) && (b_mvs.y >= min_dy) ) { \
1040                iSAD += sad8bi( cur + 8*(k&1) + 8*(k>>1)*iEdgedWidth,                                                                                                       \
1041                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \
1042                                            mvs.x, mvs.y, iEdgedWidth),                                                             \
1043                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \
1044                                            b_mvs.x, b_mvs.y, iEdgedWidth),                                                         \
1045                            iEdgedWidth); \
1046                    }       \
1047            else    \
1048                    iSAD = 65535;   \
1049            } \
1050            iSAD += calc_delta_16((X),(Y), 1, iQuant);\
1051            if (iSAD < iMinSAD) \
1052                {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iFound=0; } \
1053    }
1054    
1055    
1056    
1057    int32_t
1058    Diamond16_DirectMainSearch(
1059                                            const uint8_t * const f_pRef,
1060                                            const uint8_t * const f_pRefH,
1061                                            const uint8_t * const f_pRefV,
1062                                            const uint8_t * const f_pRefHV,
1063    
1064                                            const uint8_t * const cur,
1065    
1066                                            const uint8_t * const b_pRef,
1067                                            const uint8_t * const b_pRefH,
1068                                            const uint8_t * const b_pRefV,
1069                                            const uint8_t * const b_pRefHV,
1070    
1071                                            const int x,
1072                                            const int y,
1073    
1074                                            const int TRB,
1075                                            const int TRD,
1076    
1077                                        const int start_x,
1078                                        const int start_y,
1079    
1080                                        int iMinSAD,
1081                                        VECTOR * const currMV,
1082                                            const VECTOR * const directmv,
1083    
1084                                        const int32_t min_dx,
1085                                            const int32_t max_dx,
1086                                            const int32_t min_dy,
1087                                            const int32_t max_dy,
1088    
1089                                            const int32_t iEdgedWidth,
1090                                            const int32_t iDiamondSize,
1091    
1092                                            const int32_t iQuant,
1093                                            int iFound)
1094    {
1095    /* Do a diamond search around given starting point, return SAD of best */
1096    
1097            int32_t iSAD;
1098    
1099            VECTOR backupMV;
1100    
1101            currMV->x = start_x;
1102            currMV->y = start_y;
1103    
1104    /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1105    
1106            do
1107            {
1108                    iFound = 1;
1109    
1110                    backupMV = *currMV;
1111    
1112                    CHECK_MV16_DIRECT_FOUND(backupMV.x - iDiamondSize, backupMV.y);
1113                    CHECK_MV16_DIRECT_FOUND(backupMV.x + iDiamondSize, backupMV.y);
1114                    CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y - iDiamondSize);
1115                    CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y + iDiamondSize);
1116    
1117            } while (!iFound);
1118    
1119            return iMinSAD;
1120    }
1121    
1122    
1123    int32_t
1124    AdvDiamond8_MainSearch(const uint8_t * const pRef,
1125                                               const uint8_t * const pRefH,
1126                                               const uint8_t * const pRefV,
1127                                               const uint8_t * const pRefHV,
1128                                               const uint8_t * const cur,
1129                                               const int x,
1130                                               const int y,
1131                                               int start_x,
1132                                               int start_y,
1133                                               int iMinSAD,
1134                                               VECTOR * const currMV,
1135                                               const int center_x,
1136                                               const int center_y,
1137                                               const int32_t min_dx,
1138                                               const int32_t max_dx,
1139                                               const int32_t min_dy,
1140                                               const int32_t max_dy,
1141                                               const int32_t iEdgedWidth,
1142                                               const int32_t iDiamondSize,
1143                                               const int32_t iFcode,
1144                                               const int32_t iQuant,
1145                                               int iDirection)
1146    {
1147    
1148            int32_t iSAD;
1149    
1150    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
1151    
1152            if (iDirection) {
1153                    CHECK_MV8_CANDIDATE(start_x - iDiamondSize, start_y);
1154                    CHECK_MV8_CANDIDATE(start_x + iDiamondSize, start_y);
1155                    CHECK_MV8_CANDIDATE(start_x, start_y - iDiamondSize);
1156                    CHECK_MV8_CANDIDATE(start_x, start_y + iDiamondSize);
1157            } else {
1158                    int bDirection = 1 + 2 + 4 + 8;
1159    
1160                    do {
1161                            iDirection = 0;
1162                            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)
1163                                    CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1164    
1165                            if (bDirection & 2)
1166                                    CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1167    
1168                            if (bDirection & 4)
1169                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1170    
1171                            if (bDirection & 8)
1172                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1173    
1174                            /* now we're doing diagonal checks near our candidate */
1175    
1176                            if (iDirection)         //checking if anything found
1177                            {
1178                                    bDirection = iDirection;
1179                                    iDirection = 0;
1180                                    start_x = currMV->x;
1181                                    start_y = currMV->y;
1182                                    if (bDirection & 3)     //our candidate is left or right
1183                                    {
1184                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1185                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1186                                    } else                  // what remains here is up or down
1187                                    {
1188                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1189                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1190                                    }
1191    
1192                                    if (iDirection) {
1193                                            bDirection += iDirection;
1194                                            start_x = currMV->x;
1195                                            start_y = currMV->y;
1196                                    }
1197                            } else                          //about to quit, eh? not so fast....
1198                            {
1199                                    switch (bDirection) {
1200                                    case 2:
1201                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1202                                                                                            start_y - iDiamondSize, 2 + 4);
1203                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1204                                                                                            start_y + iDiamondSize, 2 + 8);
1205                                            break;
1206                                    case 1:
1207                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1208                                                                                            start_y - iDiamondSize, 1 + 4);
1209                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1210                                                                                            start_y + iDiamondSize, 1 + 8);
1211                                            break;
1212                                    case 2 + 4:
1213                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1214                                                                                            start_y - iDiamondSize, 1 + 4);
1215                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1216                                                                                            start_y - iDiamondSize, 2 + 4);
1217                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1218                                                                                            start_y + iDiamondSize, 2 + 8);
1219                                            break;
1220                                    case 4:
1221                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1222                                                                                            start_y - iDiamondSize, 2 + 4);
1223                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1224                                                                                            start_y - iDiamondSize, 1 + 4);
1225                                            break;
1226                                    case 8:
1227                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1228                                                                                            start_y + iDiamondSize, 2 + 8);
1229                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1230                                                                                            start_y + iDiamondSize, 1 + 8);
1231                                            break;
1232                                    case 1 + 4:
1233                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1234                                                                                            start_y + iDiamondSize, 1 + 8);
1235                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1236                                                                                            start_y - iDiamondSize, 1 + 4);
1237                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1238                                                                                            start_y - iDiamondSize, 2 + 4);
1239                                            break;
1240                                    case 2 + 8:
1241                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1242                                                                                            start_y - iDiamondSize, 1 + 4);
1243                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1244                                                                                            start_y + iDiamondSize, 1 + 8);
1245                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1246                                                                                            start_y + iDiamondSize, 2 + 8);
1247                                            break;
1248                                    case 1 + 8:
1249                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1250                                                                                            start_y - iDiamondSize, 2 + 4);
1251                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1252                                                                                            start_y + iDiamondSize, 2 + 8);
1253                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1254                                                                                            start_y + iDiamondSize, 1 + 8);
1255                                            break;
1256                                    default:                //1+2+4+8 == we didn't find anything at all
1257                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1258                                                                                            start_y - iDiamondSize, 1 + 4);
1259                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1260                                                                                            start_y + iDiamondSize, 1 + 8);
1261                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1262                                                                                            start_y - iDiamondSize, 2 + 4);
1263                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1264                                                                                            start_y + iDiamondSize, 2 + 8);
1265                                            break;
1266                                    }
1267                                    if (!(iDirection))
1268                                            break;          //ok, the end. really
1269                                    else {
1270                                            bDirection = iDirection;
1271                                            start_x = currMV->x;
1272                                            start_y = currMV->y;
1273                                    }
1274                            }
1275                    }
1276                    while (1);                              //forever
1277            }
1278            return iMinSAD;
1279    }
1280    
1281    
1282    int32_t
1283    Full8_MainSearch(const uint8_t * const pRef,
1284                                     const uint8_t * const pRefH,
1285                                     const uint8_t * const pRefV,
1286                                     const uint8_t * const pRefHV,
1287                                     const uint8_t * const cur,
1288                                     const int x,
1289                                     const int y,
1290                               const int start_x,
1291                               const int start_y,
1292                               int iMinSAD,
1293                               VECTOR * const currMV,
1294                               const int center_x,
1295                               const int center_y,
1296                                     const int32_t min_dx,
1297                                     const int32_t max_dx,
1298                                     const int32_t min_dy,
1299                                     const int32_t max_dy,
1300                                     const int32_t iEdgedWidth,
1301                                     const int32_t iDiamondSize,
1302                                     const int32_t iFcode,
1303                                     const int32_t iQuant,
1304                                     int iFound)
1305    {
1306            int32_t iSAD;
1307            int32_t dx, dy;
1308            VECTOR backupMV;
1309    
1310            backupMV.x = start_x;
1311            backupMV.y = start_y;
1312    
1313            for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
1314                    for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
1315                            NOCHECK_MV8_CANDIDATE(dx, dy);
1316    
1317            return iMinSAD;
1318    }
1319    
1320    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1321    
1322    int32_t
1323    Halfpel16_Refine(const uint8_t * const pRef,
1324                                     const uint8_t * const pRefH,
1325                                     const uint8_t * const pRefV,
1326                                     const uint8_t * const pRefHV,
1327                                     const uint8_t * const cur,
1328                                     const int x,
1329                                     const int y,
1330                                     VECTOR * const currMV,
1331                                     int32_t iMinSAD,
1332                               const int center_x,
1333                               const int center_y,
1334                                     const int32_t min_dx,
1335                                     const int32_t max_dx,
1336                                     const int32_t min_dy,
1337                                     const int32_t max_dy,
1338                                     const int32_t iFcode,
1339                                     const int32_t iQuant,
1340                                     const int32_t iEdgedWidth)
1341    {
1342    /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
1343    
1344            int32_t iSAD;
1345            VECTOR backupMV = *currMV;
1346    
1347            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y - 1);
1348            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y - 1);
1349            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y - 1);
1350            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y);
1351            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y);
1352            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y + 1);
1353            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y + 1);
1354            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y + 1);
1355    
1356            return iMinSAD;
1357    }
1358    
1359    #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1360    
1361    
1362    
1363    int32_t
1364    PMVfastSearch16(const uint8_t * const pRef,
1365                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1366                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1367                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1368                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1369                                          const int x, const int y,                                  const int x,
1370                                    const int y,
1371                                    const int start_x,      /* start is searched first, so it should contain the most */
1372                                    const int start_y,  /* likely motion vector for this block */
1373                                    const int center_x,     /* center is from where length of MVs is measured */
1374                                    const int center_y,
1375                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1376                                          const uint32_t iQuant,                                          const uint32_t iQuant,
1377                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 861  Line 1403 
1403          VECTOR pmv[4];          VECTOR pmv[4];
1404          int32_t psad[4];          int32_t psad[4];
1405    
1406          const MACROBLOCK * const pMB = pMBs + x + y * iWcount;          MainSearch16FuncPtr MainSearchPtr;
1407    
1408          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1409    
1410          static int32_t threshA,threshB;          int32_t threshA, threshB;
1411          int32_t bPredEq;          int32_t bPredEq;
1412          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1413    
1414  /* Get maximum range */  /* Get maximum range */
1415          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,
1416                    x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
1417    
1418  /* 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 */
1419    
1420          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
1421          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1422          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1423          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1424          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1425          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
   
1426    
1427          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1428            //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1429            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1430    
1431          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1432                  threshA =  512;                  threshA =  512;
1433                  threshB = 1024;                  threshB = 1024;
1434            } else {
         }  
         else  
         {  
1435                  threshA = psad[0];                  threshA = psad[0];
1436                  threshB = threshA+256;                  threshB = threshA+256;
1437                  if (threshA< 512) threshA =  512;                  if (threshA < 512)
1438                  if (threshA>1024) threshA = 1024;                          threshA = 512;
1439                  if (threshB>1792) threshB = 1792;                  if (threshA > 1024)
1440                            threshA = 1024;
1441                    if (threshB > 1792)
1442                            threshB = 1792;
1443          }          }
1444    
1445          iFound=0;          iFound=0;
1446    
 /* 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],prevMB->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;  
   
1447  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1448     MinSAD=SAD     MinSAD=SAD
1449     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 928  Line 1451 
1451     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
1452  */  */
1453    
1454            currMV->x = start_x;
1455            currMV->y = start_y;
1456    
1457  // 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! */  
1458                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1459                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
1460          }          }
1461    
1462          if (currMV->x > max_dx)          if (currMV->x > max_dx) {
         {  
1463                  currMV->x=max_dx;                  currMV->x=max_dx;
1464          }          }
1465          if (currMV->x < min_dx)          if (currMV->x < min_dx) {
         {  
1466                  currMV->x=min_dx;                  currMV->x=min_dx;
1467          }          }
1468          if (currMV->y > max_dy)          if (currMV->y > max_dy) {
         {  
1469                  currMV->y=max_dy;                  currMV->y=max_dy;
1470          }          }
1471          if (currMV->y < min_dy)          if (currMV->y < min_dy) {
         {  
1472                  currMV->y=min_dy;                  currMV->y=min_dy;
1473          }          }
1474    
1475          iMinSAD = sad16( cur,          iMinSAD =
1476                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1477                           iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1478          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1479            iMinSAD +=
1480          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
1481          {                                            (uint8_t) iFcode, iQuant);
1482    
1483            if ((iMinSAD < 256) ||
1484                    ((MVequal(*currMV, prevMB->mvs[0])) &&
1485                     ((int32_t) iMinSAD < prevMB->sad16))) {
1486                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
1487                    {
1488                            if (!MVzero(*currMV)) {
1489                                    iMinSAD += MV16_00_BIAS;
1490                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
1491                                    iMinSAD -= MV16_00_BIAS;
1492                            }
1493                    }
1494    
1495                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1496                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
# Line 969  Line 1498 
1498                          goto PMVfast16_Terminate_with_Refine;                          goto PMVfast16_Terminate_with_Refine;
1499          }          }
1500    
1501    
1502    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1503       vector of the median.
1504       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1505    */
1506    
1507            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[0])))
1508                    iFound = 2;
1509    
1510    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1511       Otherwise select large Diamond Search.
1512    */
1513    
1514            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
1515                    iDiamondSize = 1;               // halfpel!
1516            else
1517                    iDiamondSize = 2;               // halfpel!
1518    
1519            if (!(MotionFlags & PMV_HALFPELDIAMOND16))
1520                    iDiamondSize *= 2;
1521    
1522  /*  /*
1523     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.
1524     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
# Line 978  Line 1528 
1528    
1529  // (0,0) is always possible  // (0,0) is always possible
1530    
1531            if (!MVzero(pmv[0]))
1532          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1533    
1534  // previous frame MV is always possible  // previous frame MV is always possible
1535    
1536            if (!MVzero(prevMB->mvs[0]))
1537                    if (!MVequal(prevMB->mvs[0], pmv[0]))
1538          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1539    
1540  // left neighbour, if allowed  // left neighbour, if allowed
1541          if (x != 0)  
1542          {          if (!MVzero(pmv[1]))
1543                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!MVequal(pmv[1], prevMB->mvs[0]))
1544                  {       pmv[1].x = EVEN(pmv[1].x);                          if (!MVequal(pmv[1], pmv[0])) {
1545                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1546                                            pmv[1].x = EVEN(pmv[1].x);
1547                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1548                  }                  }
1549    
1550                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1551          }          }
   
1552  // top neighbour, if allowed  // top neighbour, if allowed
1553          if (y != 0)          if (!MVzero(pmv[2]))
1554          {                  if (!MVequal(pmv[2], prevMB->mvs[0]))
1555                  if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!MVequal(pmv[2], pmv[0]))
1556                  {       pmv[2].x = EVEN(pmv[2].x);                                  if (!MVequal(pmv[2], pmv[1])) {
1557                                            if (!(MotionFlags & PMV_HALFPEL16)) {
1558                                                    pmv[2].x = EVEN(pmv[2].x);
1559                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
1560                  }                  }
1561                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1562    
1563  // top right neighbour, if allowed  // top right neighbour, if allowed
1564                  if ((uint32_t)x != (iWcount-1))                                          if (!MVzero(pmv[3]))
1565                  {                                                  if (!MVequal(pmv[3], prevMB->mvs[0]))
1566                          if (!(MotionFlags & PMV_HALFPEL16 ))                                                          if (!MVequal(pmv[3], pmv[0]))
1567                          {       pmv[3].x = EVEN(pmv[3].x);                                                                  if (!MVequal(pmv[3], pmv[1]))
1568                                                                            if (!MVequal(pmv[3], pmv[2])) {
1569                                                                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1570                                                                                            pmv[3].x = EVEN(pmv[3].x);
1571                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1572                          }                          }
1573                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                  CHECK_MV16_CANDIDATE(pmv[3].x,
1574                                                                                                                             pmv[3].y);
1575                  }                  }
1576          }          }
1577    
1578          if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96)*/ )          if ((MVzero(*currMV)) &&
1579                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1580                  iMinSAD -= MV16_00_BIAS;                  iMinSAD -= MV16_00_BIAS;
1581    
1582    
# Line 1021  Line 1584 
1584     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.
1585  */  */
1586    
1587          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ((iMinSAD <= threshA) ||
1588          {                  (MVequal(*currMV, prevMB->mvs[0]) &&
1589                     ((int32_t) iMinSAD < prevMB->sad16))) {
1590                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1591                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
1592                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1040  Line 1604 
1604     Refine by using small diamond and goto step 10.     Refine by using small diamond and goto step 10.
1605  */  */
1606    
1607            if (MotionFlags & PMV_USESQUARES16)
1608                    MainSearchPtr = Square16_MainSearch;
1609            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
1610                    MainSearchPtr = AdvDiamond16_MainSearch;
1611            else
1612                    MainSearchPtr = Diamond16_MainSearch;
1613    
1614          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1615    
1616    
1617  /* 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 */
1618          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1619                                            x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1620                                            currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->x, currMV->y, iMinSAD, &newMV, center_x, center_y,
1621                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dx, max_dx,
1622                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1623                                                      iQuant, iFound);
1624    
1625          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1626                  *currMV = newMV;                  *currMV = newMV;
1627                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1628          }          }
1629    
1630          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
1631  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1632    
1633                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1634                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1635                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1636                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    center_x, center_y, iMinSAD, &newMV, center_x, center_y,
1637                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1638                                                                      iDiamondSize, iFcode, iQuant, iFound);
1639    
1640                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1641                          *currMV = newMV;                          *currMV = newMV;
1642                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1643                  }                  }
1644                  }                  }
1645    
1646                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1647                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1648                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1649                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y,
1650                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy,
1651                                                                      iEdgedWidth, iDiamondSize, iFcode,
1652                                                                      iQuant, iFound);
1653    
1654                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1655                          *currMV = newMV;                          *currMV = newMV;
1656                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1657                  }                  }
# Line 1091  Line 1664 
1664    
1665  PMVfast16_Terminate_with_Refine:  PMVfast16_Terminate_with_Refine:
1666          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1667                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1668                                    x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1669                                    currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1670                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1671    
1672  PMVfast16_Terminate_without_Refine:  PMVfast16_Terminate_without_Refine:
1673          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
1674          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
1675          return iMinSAD;          return iMinSAD;
1676  }  }
1677    
# Line 1107  Line 1680 
1680    
1681    
1682    
1683  int32_t Diamond8_MainSearch(  int32_t
1684          const uint8_t * const pRef,  Diamond8_MainSearch(const uint8_t * const pRef,
1685          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1686          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1687          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1688          const uint8_t * const cur,          const uint8_t * const cur,
1689          const int x, const int y,                                          const int x,
1690          int32_t startx, int32_t starty,                                          const int y,
1691                                            int32_t start_x,
1692                                            int32_t start_y,
1693          int32_t iMinSAD,          int32_t iMinSAD,
1694          VECTOR * const currMV,          VECTOR * const currMV,
1695          const VECTOR * const pmv,                                     const int center_x,
1696          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
1697          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
1698                                            const int32_t max_dx,
1699                                            const int32_t min_dy,
1700                                            const int32_t max_dy,
1701          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
1702          const int32_t iDiamondSize,          const int32_t iDiamondSize,
1703          const int32_t iFcode,          const int32_t iFcode,
# Line 1129  Line 1707 
1707  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
1708    
1709          int32_t iDirection=0;          int32_t iDirection=0;
1710            int32_t iDirectionBackup;
1711          int32_t iSAD;          int32_t iSAD;
1712          VECTOR backupMV;          VECTOR backupMV;
1713          backupMV.x = startx;  
1714          backupMV.y = starty;          backupMV.x = start_x;
1715            backupMV.y = start_y;
1716    
1717  /* 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 */
1718    
# Line 1141  Line 1721 
1721          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
1722          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1723    
1724          if (iDirection)          if (iDirection) {
1725                  while (!iFound)                  while (!iFound) {
                 {  
1726                          iFound = 1;                          iFound = 1;
1727                          backupMV=*currMV;       // since iDirection!=0, this is well defined!                          backupMV=*currMV;       // since iDirection!=0, this is well defined!
1728                            iDirectionBackup = iDirection;
1729    
1730                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
1731                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1732                          if ( iDirection != 1)                                                                                    backupMV.y, 1);
1733                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
1734                          if ( iDirection != 4)                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1735                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                    backupMV.y, 2);
1736                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
1737                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1738                                                                                      backupMV.y - iDiamondSize, 3);
1739                            if (iDirectionBackup != 3)
1740                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1741                                                                                      backupMV.y + iDiamondSize, 4);
1742                  }                  }
1743          else          } else {
1744                    currMV->x = start_x;
1745                    currMV->y = start_y;
1746            }
1747            return iMinSAD;
1748    }
1749    
1750    
1751    
1752    
1753    int32_t
1754    Square8_MainSearch(const uint8_t * const pRef,
1755                                            const uint8_t * const pRefH,
1756                                            const uint8_t * const pRefV,
1757                                            const uint8_t * const pRefHV,
1758                                            const uint8_t * const cur,
1759                                            const int x,
1760                                            const int y,
1761                                            int32_t start_x,
1762                                            int32_t start_y,
1763                                            int32_t iMinSAD,
1764                                            VECTOR * const currMV,
1765                                       const int center_x,
1766                                       const int center_y,
1767                                            const int32_t min_dx,
1768                                            const int32_t max_dx,
1769                                            const int32_t min_dy,
1770                                            const int32_t max_dy,
1771                                            const int32_t iEdgedWidth,
1772                                            const int32_t iDiamondSize,
1773                                            const int32_t iFcode,
1774                                            const int32_t iQuant,
1775                                            int iFound)
1776          {          {
1777                  currMV->x = startx;  /* Do a square search around given starting point, return SAD of best */
1778                  currMV->y = starty;  
1779            int32_t iDirection = 0;
1780            int32_t iSAD;
1781            VECTOR backupMV;
1782    
1783            backupMV.x = start_x;
1784            backupMV.y = start_y;
1785    
1786    /* It's one search with full square pattern, and new parts for all following diamonds */
1787    
1788    /*   new direction are extra, so 1-4 is normal diamond
1789          537
1790          1*2
1791          648
1792    */
1793    
1794            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1795            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1796            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1797            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1798    
1799            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1800                                                             backupMV.y - iDiamondSize, 5);
1801            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1802                                                             backupMV.y + iDiamondSize, 6);
1803            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1804                                                             backupMV.y - iDiamondSize, 7);
1805            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1806                                                             backupMV.y + iDiamondSize, 8);
1807    
1808    
1809            if (iDirection) {
1810                    while (!iFound) {
1811                            iFound = 1;
1812                            backupMV = *currMV;
1813    
1814                            switch (iDirection) {
1815                            case 1:
1816                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1817                                                                                       backupMV.y, 1);
1818                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1819                                                                                     backupMV.y - iDiamondSize, 5);
1820                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1821                                                                                     backupMV.y - iDiamondSize, 7);
1822                                    break;
1823                            case 2:
1824                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1825                                                                                     2);
1826                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1827                                                                                     backupMV.y + iDiamondSize, 6);
1828                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1829                                                                                     backupMV.y + iDiamondSize, 8);
1830                                    break;
1831    
1832                            case 3:
1833                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1834                                                                                     4);
1835                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1836                                                                                     backupMV.y - iDiamondSize, 7);
1837                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1838                                                                                     backupMV.y + iDiamondSize, 8);
1839                                    break;
1840    
1841                            case 4:
1842                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1843                                                                                     3);
1844                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1845                                                                                     backupMV.y - iDiamondSize, 5);
1846                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1847                                                                                     backupMV.y + iDiamondSize, 6);
1848                                    break;
1849    
1850                            case 5:
1851                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1852                                                                                     1);
1853                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1854                                                                                     3);
1855                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1856                                                                                     backupMV.y - iDiamondSize, 5);
1857                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1858                                                                                     backupMV.y + iDiamondSize, 6);
1859                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1860                                                                                     backupMV.y - iDiamondSize, 7);
1861                                    break;
1862    
1863                            case 6:
1864                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1865                                                                                     2);
1866                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1867                                                                                     3);
1868    
1869                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1870                                                                                     backupMV.y - iDiamondSize, 5);
1871                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1872                                                                                     backupMV.y + iDiamondSize, 6);
1873                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1874                                                                                     backupMV.y + iDiamondSize, 8);
1875    
1876                                    break;
1877    
1878                            case 7:
1879                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1880                                                                                       backupMV.y, 1);
1881                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1882                                                                                     4);
1883                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1884                                                                                     backupMV.y - iDiamondSize, 5);
1885                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1886                                                                                     backupMV.y - iDiamondSize, 7);
1887                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1888                                                                                     backupMV.y + iDiamondSize, 8);
1889                                    break;
1890    
1891                            case 8:
1892                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1893                                                                                     2);
1894                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1895                                                                                     4);
1896                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1897                                                                                     backupMV.y + iDiamondSize, 6);
1898                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1899                                                                                     backupMV.y - iDiamondSize, 7);
1900                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1901                                                                                     backupMV.y + iDiamondSize, 8);
1902                                    break;
1903                            default:
1904                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1905                                                                                     1);
1906                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1907                                                                                     2);
1908                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1909                                                                                     3);
1910                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1911                                                                                     4);
1912    
1913                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1914                                                                                     backupMV.y - iDiamondSize, 5);
1915                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1916                                                                                     backupMV.y + iDiamondSize, 6);
1917                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1918                                                                                     backupMV.y - iDiamondSize, 7);
1919                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1920                                                                                     backupMV.y + iDiamondSize, 8);
1921                                    break;
1922                            }
1923                    }
1924            } else {
1925                    currMV->x = start_x;
1926                    currMV->y = start_y;
1927          }          }
1928          return iMinSAD;          return iMinSAD;
1929  }  }
1930    
1931  int32_t Halfpel8_Refine(  
1932          const uint8_t * const pRef,  
1933    
1934    
1935    int32_t
1936    Halfpel8_Refine_c(const uint8_t * const pRef,
1937          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1938          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1939          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1940          const uint8_t * const cur,          const uint8_t * const cur,
1941          const int x, const int y,                                  const int x,
1942                                    const int y,
1943          VECTOR * const currMV,          VECTOR * const currMV,
1944          int32_t iMinSAD,          int32_t iMinSAD,
1945          const VECTOR * const pmv,                             const int center_x,
1946          const int32_t min_dx, const int32_t max_dx,                             const int center_y,
1947          const int32_t min_dy, const int32_t max_dy,                                  const int32_t min_dx,
1948                                    const int32_t max_dx,
1949                                    const int32_t min_dy,
1950                                    const int32_t max_dy,
1951          const int32_t iFcode,          const int32_t iFcode,
1952          const int32_t iQuant,          const int32_t iQuant,
1953          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 1200  Line 1972 
1972    
1973  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1974    
1975  int32_t PMVfastSearch8(  int32_t
1976                                          const uint8_t * const pRef,  PMVfastSearch8(const uint8_t * const pRef,
1977                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1978                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1979                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1980                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1981                                          const int x, const int y,                             const int x,
1982                                          const int start_x, const int start_y,                             const int y,
1983                               const int start_x,
1984                               const int start_y,
1985                                    const int center_x,
1986                                    const int center_y,
1987                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1988                                          const uint32_t iQuant,                                          const uint32_t iQuant,
1989                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1235  Line 2011 
2011          int32_t psad[4];          int32_t psad[4];
2012          VECTOR newMV;          VECTOR newMV;
2013          VECTOR backupMV;          VECTOR backupMV;
2014            VECTOR startMV;
2015    
2016          const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2017          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
2018    
2019          static int32_t threshA,threshB;           int32_t threshA, threshB;
2020          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
2021          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
2022    
2023          int32_t iSubBlock = ((y&1)<<1) + (x&1);          int32_t iSubBlock = (y & 1) + (y & 1) + (x & 1);
2024    
2025            MainSearch8FuncPtr MainSearchPtr;
2026    
2027            /* Init variables */
2028            startMV.x = start_x;
2029            startMV.y = start_y;
2030    
2031  /* Get maximum range */  /* Get maximum range */
2032          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2033                    x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2034    
2035          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
2036          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2037          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
2038          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
2039          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
2040          }               /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          }
2041    
2042            /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
2043            //bPredEq = get_pmvdata(pMBs, (x >> 1), (y >> 1), iWcount, iSubBlock, pmv, psad);
2044            bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
2045    
2046            if ((x == 0) && (y == 0)) {
2047                    threshA = 512 / 4;
2048                    threshB = 1024 / 4;
2049    
2050            } else {
2051                    threshA = psad[0] / 4;  /* good estimate? */
2052                    threshB = threshA + 256 / 4;
2053                    if (threshA < 512 / 4)
2054                            threshA = 512 / 4;
2055                    if (threshA > 1024 / 4)
2056                            threshA = 1024 / 4;
2057                    if (threshB > 1792 / 4)
2058                            threshB = 1792 / 4;
2059            }
2060    
2061            iFound = 0;
2062    
2063    /* Step 4: Calculate SAD around the Median prediction.
2064       MinSAD=SAD
2065       If Motion Vector equal to Previous frame motion vector
2066       and MinSAD<PrevFrmSAD goto Step 10.
2067       If SAD<=256 goto Step 10.
2068    */
2069    
2070    
2071    // Prepare for main loop
2072    
2073      if (MotionFlags & PMV_USESQUARES8)
2074          MainSearchPtr = Square8_MainSearch;
2075      else
2076    
2077          bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2078                    MainSearchPtr = AdvDiamond8_MainSearch;
2079            else
2080                    MainSearchPtr = Diamond8_MainSearch;
2081    
         if ((x==0) && (y==0) )  
         {  
                 threshA =  512/4;  
                 threshB = 1024/4;  
2082    
2083          }          *currMV = startMV;
         else  
         {  
                 threshA = psad[0]/4;                    /* good estimate */  
                 threshB = threshA+256/4;  
                 if (threshA< 512/4) threshA =  512/4;  
                 if (threshA>1024/4) threshA = 1024/4;  
                 if (threshB>1792/4) threshB = 1792/4;  
         }  
2084    
2085          iFound=0;          iMinSAD =
2086                    sad8(cur,
2087                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2088                                                    iEdgedWidth), iEdgedWidth);
2089            iMinSAD +=
2090                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2091                                             (uint8_t) iFcode, iQuant);
2092    
2093            if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))
2094                                                                    && ((int32_t) iMinSAD <
2095                                                                            prevMB->sad8[iSubBlock]))) {
2096                    if (MotionFlags & PMV_QUICKSTOP16)
2097                            goto PMVfast8_Terminate_without_Refine;
2098                    if (MotionFlags & PMV_EARLYSTOP16)
2099                            goto PMVfast8_Terminate_with_Refine;
2100            }
2101    
2102  /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2103     vector of the median.     vector of the median.
2104     If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2     If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2105  */  */
# Line 1284  Line 2107 
2107          if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[iSubBlock]) ) )          if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[iSubBlock]) ) )
2108                  iFound=2;                  iFound=2;
2109    
2110  /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2111     Otherwise select large Diamond Search.     Otherwise select large Diamond Search.
2112  */  */
2113    
2114          if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536/4) || (bPredEq) )          if ((!MVzero(pmv[0])) || (threshB < 1536 / 4) || (bPredEq))
2115                  iDiamondSize=1; // 1 halfpel!                  iDiamondSize=1; // 1 halfpel!
2116          else          else
2117                  iDiamondSize=2; // 2 halfpel = 1 full pixel!                  iDiamondSize=2; // 2 halfpel = 1 full pixel!
# Line 1296  Line 2119 
2119          if (!(MotionFlags & PMV_HALFPELDIAMOND8) )          if (!(MotionFlags & PMV_HALFPELDIAMOND8) )
2120                  iDiamondSize*=2;                  iDiamondSize*=2;
2121    
 /* Step 4: Calculate SAD around the Median prediction.  
    MinSAD=SAD  
    If Motion Vector equal to Previous frame motion vector  
    and MinSAD<PrevFrmSAD goto Step 10.  
    If SAD<=256 goto Step 10.  
 */  
   
   
 // Prepare for main loop  
   
         currMV->x=start_x;              /* start with mv16 */  
         currMV->y=start_y;  
   
         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);  
   
         if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock])) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )  
         {  
                 if (MotionFlags & PMV_QUICKSTOP16)  
                         goto PMVfast8_Terminate_without_Refine;  
                 if (MotionFlags & PMV_EARLYSTOP16)  
                         goto PMVfast8_Terminate_with_Refine;  
         }  
   
2122    
2123  /*  /*
2124     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.
# Line 1330  Line 2127 
2127     If MV is (0,0) subtract offset.     If MV is (0,0) subtract offset.
2128  */  */
2129    
2130  // 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);  
2131    
2132  // (0,0) is always possible          if (!MVequal(pmv[0], startMV))
2133                    CHECK_MV8_CANDIDATE(center_x, center_y);
2134    
2135    // (0,0) if needed
2136            if (!MVzero(pmv[0]))
2137                    if (!MVzero(startMV))
2138          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
2139    
2140  // previous frame MV is always possible  // previous frame MV if needed
2141          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);          if (!MVzero(prevMB->mvs[iSubBlock]))
2142                    if (!MVequal(prevMB->mvs[iSubBlock], startMV))
2143                            if (!MVequal(prevMB->mvs[iSubBlock], pmv[0]))
2144                                    CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,
2145                                                                            prevMB->mvs[iSubBlock].y);
2146    
2147            if ((iMinSAD <= threshA) ||
2148                    (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2149                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2150                    if (MotionFlags & PMV_QUICKSTOP16)
2151                            goto PMVfast8_Terminate_without_Refine;
2152                    if (MotionFlags & PMV_EARLYSTOP16)
2153                            goto PMVfast8_Terminate_with_Refine;
2154            }
2155    
2156  // left neighbour, if allowed  // left neighbour, if allowed and needed
2157          if (psad[1] != MV_MAX_ERROR)          if (!MVzero(pmv[1]))
2158          {                  if (!MVequal(pmv[1], startMV))
2159                  if (!(MotionFlags & PMV_HALFPEL8 ))                          if (!MVequal(pmv[1], prevMB->mvs[iSubBlock]))
2160                  {       pmv[1].x = EVEN(pmv[1].x);                                  if (!MVequal(pmv[1], pmv[0])) {
2161                                            if (!(MotionFlags & PMV_HALFPEL8)) {
2162                                                    pmv[1].x = EVEN(pmv[1].x);
2163                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
2164                  }                  }
2165                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
2166          }          }
2167    // top neighbour, if allowed and needed
2168  // top neighbour, if allowed          if (!MVzero(pmv[2]))
2169          if (psad[2] != MV_MAX_ERROR)                  if (!MVequal(pmv[2], startMV))
2170          {                          if (!MVequal(pmv[2], prevMB->mvs[iSubBlock]))
2171                  if (!(MotionFlags & PMV_HALFPEL8 ))                                  if (!MVequal(pmv[2], pmv[0]))
2172                  {       pmv[2].x = EVEN(pmv[2].x);                                          if (!MVequal(pmv[2], pmv[1])) {
2173                                                    if (!(MotionFlags & PMV_HALFPEL8)) {
2174                                                            pmv[2].x = EVEN(pmv[2].x);
2175                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
2176                  }                  }
2177                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
2178    
2179  // top right neighbour, if allowed  // top right neighbour, if allowed and needed
2180                  if (psad[3] != MV_MAX_ERROR)                                                  if (!MVzero(pmv[3]))
2181                  {                                                          if (!MVequal(pmv[3], startMV))
2182                          if (!(MotionFlags & PMV_HALFPEL8 ))                                                                  if (!MVequal(pmv[3], prevMB->mvs[iSubBlock]))
2183                          {       pmv[3].x = EVEN(pmv[3].x);                                                                          if (!MVequal(pmv[3], pmv[0]))
2184                                                                                    if (!MVequal(pmv[3], pmv[1]))
2185                                                                                            if (!MVequal(pmv[3], pmv[2])) {
2186                                                                                                    if (!
2187                                                                                                            (MotionFlags &
2188                                                                                                             PMV_HALFPEL8)) {
2189                                                                                                            pmv[3].x = EVEN(pmv[3].x);
2190                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
2191                          }                          }
2192                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                                  CHECK_MV8_CANDIDATE(pmv[3].x,
2193                                                                                                                                            pmv[3].y);
2194                  }                  }
2195          }          }
2196    
2197          if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )          if ((MVzero(*currMV)) &&
2198                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2199                  iMinSAD -= MV8_00_BIAS;                  iMinSAD -= MV8_00_BIAS;
2200    
2201    
# Line 1377  Line 2203 
2203     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.
2204  */  */
2205    
2206          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
2207          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2208                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2209                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2210                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2211                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1398  Line 2225 
2225          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2226    
2227  /* 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 */
2228          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2229                                           x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2230                                           currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2231                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2232                                                      iQuant, iFound);
2233    
2234          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2235                  *currMV = newMV;                  *currMV = newMV;
2236                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2237          }          }
2238    
2239          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2240  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
2241    
2242                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2243                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2244                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2245                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2246                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2247                                                                      iDiamondSize, iFcode, iQuant, iFound);
2248    
2249                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2250                          *currMV = newMV;                          *currMV = newMV;
2251                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2252                  }                  }
2253                  }                  }
2254    
2255                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2256                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2257                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2258                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2259                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2260                                                                      iQuant, iFound);
2261    
2262                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2263                          *currMV = newMV;                          *currMV = newMV;
2264                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2265                  }                  }
# Line 1446  Line 2272 
2272    
2273  PMVfast8_Terminate_with_Refine:  PMVfast8_Terminate_with_Refine:
2274          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2275                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2276                                                   x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2277                                                   currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2278                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2279    
2280    
2281  PMVfast8_Terminate_without_Refine:  PMVfast8_Terminate_without_Refine:
2282          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2283          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2284    
2285          return iMinSAD;          return iMinSAD;
2286  }  }
2287    
2288  int32_t EPZSSearch16(  int32_t
2289                                          const uint8_t * const pRef,  EPZSSearch16(const uint8_t * const pRef,
2290                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2291                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2292                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2293                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2294                                          const int x, const int y,                           const int x,
2295                             const int y,
2296                            const int start_x,
2297                            const int start_y,
2298                            const int center_x,
2299                            const int center_y,
2300                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2301                                          const uint32_t iQuant,                                          const uint32_t iQuant,
2302                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1496  Line 2327 
2327          int32_t psad[8];          int32_t psad[8];
2328    
2329          static MACROBLOCK * oldMBs = NULL;          static MACROBLOCK * oldMBs = NULL;
2330          const MACROBLOCK * const pMB = pMBs + x + y * iWcount;  
2331    //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
2332          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
2333          MACROBLOCK * oldMB = NULL;          MACROBLOCK * oldMB = NULL;
2334    
2335          static int32_t thresh2;           int32_t thresh2;
2336          int32_t bPredEq;          int32_t bPredEq;
2337          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2338    
2339          MainSearch16FuncPtr EPZSMainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
2340    
2341          if (oldMBs == NULL)          if (oldMBs == NULL) {
2342          {       oldMBs = (MACROBLOCK*) calloc(iWcount*iHcount,sizeof(MACROBLOCK));                  oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
2343  //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));  //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
2344          }          }
2345          oldMB = oldMBs + x + y * iWcount;          oldMB = oldMBs + x + y * iWcount;
2346    
2347  /* Get maximum range */  /* Get maximum range */
2348          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,
2349                          x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
2350    
2351          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
2352          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2353            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2354            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2355            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2356          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2357            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2358          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
2359            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2360    
2361  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2362          MinSAD=SAD          MinSAD=SAD
# Line 1534  Line 2367 
2367    
2368  // Prepare for main loop  // Prepare for main loop
2369    
2370          *currMV=pmv[0];         /* current best := median prediction */          currMV->x = start_x;
2371          if (!(MotionFlags & PMV_HALFPEL16))          currMV->y = start_y;
2372          {  
2373            if (!(MotionFlags & PMV_HALFPEL16)) {
2374                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2375                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2376          }          }
# Line 1552  Line 2386 
2386    
2387  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2388    
2389          iMinSAD = sad16( cur,          iMinSAD =
2390                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
2391                  iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2392          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2393            iMinSAD +=
2394                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2395                                              (uint8_t) iFcode, iQuant);
2396    
2397  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2398          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV, prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ((iMinSAD < 256) ||
2399                  {                  ((MVequal(*currMV, prevMB->mvs[0])) &&
2400                     ((int32_t) iMinSAD < prevMB->sad16))) {
2401                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2402                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2403                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1574  Line 2412 
2412  // set threshhold based on Min of Prediction and SAD of collocated block  // set threshhold based on Min of Prediction and SAD of collocated block
2413  // 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
2414    
2415          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
2416                  thresh2 =  512;                  thresh2 =  512;
2417          }          } else {
         else  
         {  
2418  /* 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] */
2419    
2420                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
# Line 1591  Line 2426 
2426    
2427    
2428  // left neighbour, if allowed  // left neighbour, if allowed
2429          if (x != 0)          if (x != 0) {
2430          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2431                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2432                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2433                  }                  }
2434                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
2435          }          }
   
2436  // top neighbour, if allowed  // top neighbour, if allowed
2437          if (y != 0)          if (y != 0) {
2438          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2439                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2440                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2441                  }                  }
2442                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
2443    
2444  // top right neighbour, if allowed  // top right neighbour, if allowed
2445                  if ((uint32_t)x != (iWcount-1))                  if ((uint32_t) x != (iWcount - 1)) {
2446                  {                          if (!(MotionFlags & PMV_HALFPEL16)) {
2447                          if (!(MotionFlags & PMV_HALFPEL16 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2448                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2449                          }                          }
2450                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
# Line 1625  Line 2456 
2456  */  */
2457    
2458          if ( (iMinSAD <= thresh2)          if ( (iMinSAD <= thresh2)
2459                  || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )                  || (MVequal(*currMV, prevMB->mvs[0]) &&
2460                  {                          ((int32_t) iMinSAD <= prevMB->sad16))) {
2461                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2462                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2463                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1647  Line 2478 
2478    
2479  // top neighbour  // top neighbour
2480          if (y != 0)          if (y != 0)
2481                  CHECK_MV16_CANDIDATE((prevMB-iWcount)->mvs[0].x,(prevMB-iWcount)->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,
2482                                                             (prevMB - iWcount)->mvs[0].y);
2483    
2484  // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs  // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
2485    
# Line 1656  Line 2488 
2488    
2489  // bottom neighbour, dito  // bottom neighbour, dito
2490          if ((uint32_t)y != iHcount-1)          if ((uint32_t)y != iHcount-1)
2491                  CHECK_MV16_CANDIDATE((prevMB+iWcount)->mvs[0].x,(prevMB+iWcount)->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,
2492                                                             (prevMB + iWcount)->mvs[0].y);
2493    
2494  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
2495          if (iMinSAD <= thresh2)          if (iMinSAD <= thresh2) {
                 {  
2496                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2497                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2498                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1671  Line 2503 
2503    
2504          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2505    
2506  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */          if (MotionFlags & PMV_USESQUARES16)
2507                    MainSearchPtr = Square16_MainSearch;
2508            else
2509             if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2510                    MainSearchPtr = AdvDiamond16_MainSearch;
2511            else
2512                    MainSearchPtr = Diamond16_MainSearch;
2513    
2514    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2515    
2516            iSAD =
2517                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2518                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2519                                                      min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2520    
2521            if (iSAD < iMinSAD) {
2522                    *currMV = newMV;
2523                    iMinSAD = iSAD;
2524            }
2525    
2526    
2527            if (MotionFlags & PMV_EXTSEARCH16) {
2528    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2529    
2530                    if (!(MVequal(pmv[0], backupMV))) {
2531                            iSAD =
2532                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2533                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2534                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2535                                                                      2, iFcode, iQuant, 0);
2536                    }
2537    
2538                    if (iSAD < iMinSAD) {
2539                            *currMV = newMV;
2540                            iMinSAD = iSAD;
2541                    }
2542    
2543                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2544                            iSAD =
2545                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2546                                                                      iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2547                                                                      max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2548    
2549                            if (iSAD < iMinSAD) {
2550                                    *currMV = newMV;
2551                                    iMinSAD = iSAD;
2552                            }
2553                    }
2554            }
2555    
2556    /***************        Choose best MV found     **************/
2557    
2558      EPZS16_Terminate_with_Refine:
2559            if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
2560                    iMinSAD =
2561                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2562                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2563                                                             iFcode, iQuant, iEdgedWidth);
2564    
2565      EPZS16_Terminate_without_Refine:
2566    
2567            *oldMB = *prevMB;
2568    
2569            currPMV->x = currMV->x - center_x;
2570            currPMV->y = currMV->y - center_y;
2571            return iMinSAD;
2572    }
2573    
2574    
2575    int32_t
2576    EPZSSearch8(const uint8_t * const pRef,
2577                            const uint8_t * const pRefH,
2578                            const uint8_t * const pRefV,
2579                            const uint8_t * const pRefHV,
2580                            const IMAGE * const pCur,
2581                            const int x,
2582                            const int y,
2583                            const int start_x,
2584                            const int start_y,
2585                            const int center_x,
2586                            const int center_y,
2587                            const uint32_t MotionFlags,
2588                            const uint32_t iQuant,
2589                            const uint32_t iFcode,
2590                            const MBParam * const pParam,
2591                            const MACROBLOCK * const pMBs,
2592                            const MACROBLOCK * const prevMBs,
2593                            VECTOR * const currMV,
2594                            VECTOR * const currPMV)
2595    {
2596    /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
2597    
2598            const uint32_t iWcount = pParam->mb_width;
2599            const int32_t iWidth = pParam->width;
2600            const int32_t iHeight = pParam->height;
2601            const int32_t iEdgedWidth = pParam->edged_width;
2602    
2603            const uint8_t *cur = pCur->y + x * 8 + y * 8 * iEdgedWidth;
2604    
2605            int32_t iDiamondSize = 1;
2606    
2607            int32_t min_dx;
2608            int32_t max_dx;
2609            int32_t min_dy;
2610            int32_t max_dy;
2611    
2612            VECTOR newMV;
2613            VECTOR backupMV;
2614    
2615            VECTOR pmv[4];
2616            int32_t psad[8];
2617    
2618            const int32_t iSubBlock = ((y & 1) << 1) + (x & 1);
2619    
2620    //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2621            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
2622    
2623            int32_t bPredEq;
2624            int32_t iMinSAD, iSAD = 9999;
2625    
2626            MainSearch8FuncPtr MainSearchPtr;
2627    
2628    /* Get maximum range */
2629            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2630                              iFcode);
2631    
2632    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2633    
2634            if (!(MotionFlags & PMV_HALFPEL8)) {
2635                    min_dx = EVEN(min_dx);
2636                    max_dx = EVEN(max_dx);
2637                    min_dy = EVEN(min_dy);
2638                    max_dy = EVEN(max_dy);
2639            }
2640            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2641            //bPredEq = get_pmvdata(pMBs, x >> 1, y >> 1, iWcount, iSubBlock, pmv[0].x, pmv[0].y, psad);
2642            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2643    
2644    
2645    /* Step 4: Calculate SAD around the Median prediction.
2646            MinSAD=SAD
2647            If Motion Vector equal to Previous frame motion vector
2648                    and MinSAD<PrevFrmSAD goto Step 10.
2649            If SAD<=256 goto Step 10.
2650    */
2651    
2652    // Prepare for main loop
2653    
2654    
2655            if (!(MotionFlags & PMV_HALFPEL8)) {
2656                    currMV->x = EVEN(currMV->x);
2657                    currMV->y = EVEN(currMV->y);
2658            }
2659    
2660            if (currMV->x > max_dx)
2661                    currMV->x = max_dx;
2662            if (currMV->x < min_dx)
2663                    currMV->x = min_dx;
2664            if (currMV->y > max_dy)
2665                    currMV->y = max_dy;
2666            if (currMV->y < min_dy)
2667                    currMV->y = min_dy;
2668    
2669    /***************** This is predictor SET A: only median prediction ******************/
2670    
2671    
2672            iMinSAD =
2673                    sad8(cur,
2674                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2675                                                    iEdgedWidth), iEdgedWidth);
2676            iMinSAD +=
2677                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2678                                             (uint8_t) iFcode, iQuant);
2679    
2680    
2681    // thresh1 is fixed to 256
2682            if (iMinSAD < 256 / 4) {
2683                    if (MotionFlags & PMV_QUICKSTOP8)
2684                            goto EPZS8_Terminate_without_Refine;
2685                    if (MotionFlags & PMV_EARLYSTOP8)
2686                            goto EPZS8_Terminate_with_Refine;
2687            }
2688    
2689    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2690    
2691    
2692    // MV=(0,0) is often a good choice
2693            CHECK_MV8_ZERO;
2694    
2695    // previous frame MV
2696            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x, prevMB->mvs[iSubBlock].y);
2697    
2698    // left neighbour, if allowed
2699            if (psad[1] != MV_MAX_ERROR) {
2700                    if (!(MotionFlags & PMV_HALFPEL8)) {
2701                            pmv[1].x = EVEN(pmv[1].x);
2702                            pmv[1].y = EVEN(pmv[1].y);
2703                    }
2704                    CHECK_MV8_CANDIDATE(pmv[1].x, pmv[1].y);
2705            }
2706    // top neighbour, if allowed
2707            if (psad[2] != MV_MAX_ERROR) {
2708                    if (!(MotionFlags & PMV_HALFPEL8)) {
2709                            pmv[2].x = EVEN(pmv[2].x);
2710                            pmv[2].y = EVEN(pmv[2].y);
2711                    }
2712                    CHECK_MV8_CANDIDATE(pmv[2].x, pmv[2].y);
2713    
2714    // top right neighbour, if allowed
2715                    if (psad[3] != MV_MAX_ERROR) {
2716                            if (!(MotionFlags & PMV_HALFPEL8)) {
2717                                    pmv[3].x = EVEN(pmv[3].x);
2718                                    pmv[3].y = EVEN(pmv[3].y);
2719                            }
2720                            CHECK_MV8_CANDIDATE(pmv[3].x, pmv[3].y);
2721                    }
2722            }
2723    
2724    /*  // this bias is zero anyway, at the moment!
2725    
2726            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
2727                    iMinSAD -= MV8_00_BIAS;
2728    
2729    */
2730    
2731    /* Terminate if MinSAD <= T_2
2732       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
2733    */
2734    
2735            if (iMinSAD < 512 / 4) {        /* T_2 == 512/4 hardcoded */
2736                    if (MotionFlags & PMV_QUICKSTOP8)
2737                            goto EPZS8_Terminate_without_Refine;
2738                    if (MotionFlags & PMV_EARLYSTOP8)
2739                            goto EPZS8_Terminate_with_Refine;
2740            }
2741    
2742    /************ (Diamond Search)  **************/
2743    
2744            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2745    
2746            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2747                    iDiamondSize *= 2;
2748    
2749          if (MotionFlags & PMV_USESQUARES16)  /* default: use best prediction as starting point for one call of EPZS_MainSearch */
2750                  EPZSMainSearchPtr = Square16_MainSearch;  
2751    // there is no EPZS^2 for inter4v at the moment
2752    
2753      if (MotionFlags & PMV_USESQUARES8)
2754          MainSearchPtr = Square8_MainSearch;
2755          else          else
                 EPZSMainSearchPtr = Diamond16_MainSearch;  
2756    
2757          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2758                          x, y,                  MainSearchPtr = AdvDiamond8_MainSearch;
2759                          currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,          else
2760                          2, iFcode, iQuant, 0);                  MainSearchPtr = Diamond8_MainSearch;
2761    
2762          if (iSAD < iMinSAD)          iSAD =
2763          {                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2764                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2765                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2766                                                      iQuant, 0);
2767    
2768    
2769            if (iSAD < iMinSAD) {
2770                  *currMV = newMV;                  *currMV = newMV;
2771                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2772          }          }
2773    
2774            if (MotionFlags & PMV_EXTSEARCH8) {
         if (MotionFlags & PMV_EXTSEARCH16)  
         {  
2775  /* 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) */
2776    
2777                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2778                  {                          iSAD =
2779                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2780                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2781                                  pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2782                                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, 0);
                 }  
2783    
2784                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2785                          *currMV = newMV;                          *currMV = newMV;
2786                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2787                  }                  }
2788                    }
2789    
2790                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2791                  {                          iSAD =
2792                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2793                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2794                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2795                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    iQuant, 0);
2796    
2797                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2798                                  *currMV = newMV;                                  *currMV = newMV;
2799                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2800                          }                          }
# Line 1725  Line 2803 
2803    
2804  /***************        Choose best MV found     **************/  /***************        Choose best MV found     **************/
2805    
2806  EPZS16_Terminate_with_Refine:    EPZS8_Terminate_with_Refine:
2807          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step
2808                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2809                                  x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2810                                  currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2811                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
   
 EPZS16_Terminate_without_Refine:  
2812    
2813          *oldMB = *prevMB;    EPZS8_Terminate_without_Refine:
2814    
2815          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2816          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2817          return iMinSAD;          return iMinSAD;
2818  }  }
2819    
2820    
2821  int32_t EPZSSearch8(  
2822                                          const uint8_t * const pRef,  int32_t
2823    PMVfastIntSearch16(const uint8_t * const pRef,
2824                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2825                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2826                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2827                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2828                                          const int x, const int y,                                  const int x,
2829                                          const int start_x, const int start_y,                                  const int y,
2830                                    const int start_x,              /* start should be most likely vector */
2831                                    const int start_y,
2832                                    const int center_x,             /* center is from where length of MVs is measured */
2833                                    const int center_y,
2834                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2835                                          const uint32_t iQuant,                                          const uint32_t iQuant,
2836                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1759  Line 2840 
2840                                          VECTOR * const currMV,                                          VECTOR * const currMV,
2841                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
2842  {  {
 /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */  
   
2843          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
2844          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
2845          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
2846          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
2847    
2848          const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;          const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
2849            const VECTOR zeroMV = { 0, 0 };
2850    
2851          int32_t iDiamondSize=1;          int32_t iDiamondSize;
2852    
2853          int32_t min_dx;          int32_t min_dx;
2854          int32_t max_dx;          int32_t max_dx;
2855          int32_t min_dy;          int32_t min_dy;
2856          int32_t max_dy;          int32_t max_dy;
2857    
2858            int32_t iFound;
2859    
2860          VECTOR newMV;          VECTOR newMV;
2861          VECTOR backupMV;          VECTOR backupMV;
2862    
2863          VECTOR pmv[4];          VECTOR pmv[4];
2864          int32_t psad[8];          int32_t psad[4];
2865    
2866          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);          MainSearch16FuncPtr MainSearchPtr;
2867    
2868          const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2869          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;          MACROBLOCK *const pMB = pMBs + x + y * iWcount;
2870    
2871            int32_t threshA, threshB;
2872          int32_t bPredEq;          int32_t bPredEq;
2873          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD, iSAD;
2874    
         MainSearch8FuncPtr EPZSMainSearchPtr;  
2875    
2876  /* Get maximum range */  /* Get maximum range */
2877          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,
2878                          x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2879    
2880  /* 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 */
2881    
2882          if (!(MotionFlags & PMV_HALFPEL8 ))          if ((x == 0) && (y == 0)) {
2883          { min_dx = EVEN(min_dx);                  threshA = 512;
2884            max_dx = EVEN(max_dx);                  threshB = 1024;
2885            min_dy = EVEN(min_dy);  
2886            max_dy = EVEN(max_dy);                  bPredEq = 0;
2887          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */                  psad[0] = psad[1] = psad[2] = psad[3] = 0;
2888                    *currMV = pmv[0] = pmv[1] = pmv[2] = pmv[3] = zeroMV;
2889    
2890            } else {
2891                    threshA = psad[0];
2892                    threshB = threshA + 256;
2893                    if (threshA < 512)
2894                            threshA = 512;
2895                    if (threshA > 1024)
2896                            threshA = 1024;
2897                    if (threshB > 1792)
2898                            threshB = 1792;
2899    
2900          bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);                  bPredEq = get_ipmvdata(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2901                    *currMV = pmv[0];                       /* current best := prediction */
2902            }
2903    
2904            iFound = 0;
2905    
2906  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2907          MinSAD=SAD          MinSAD=SAD
# Line 1814  Line 2910 
2910          If SAD<=256 goto Step 10.          If SAD<=256 goto Step 10.
2911  */  */
2912    
2913  // Prepare for main loop          if (currMV->x > max_dx) {
2914                    currMV->x = EVEN(max_dx);
2915            }
2916            if (currMV->x < min_dx) {
2917                    currMV->x = EVEN(min_dx);
2918            }
2919            if (currMV->y > max_dy) {
2920                    currMV->y = EVEN(max_dy);
2921            }
2922            if (currMV->y < min_dy) {
2923                    currMV->y = EVEN(min_dy);
2924            }
2925    
2926            iMinSAD =
2927                    sad16(cur,
2928                              get_iref_mv(pRef, x, y, 16, currMV,