[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 345, Sat Jul 27 23:47:01 2002 UTC
# Line 1  Line 1 
1  /**************************************************************************  /**************************************************************************
2   *   *
3     *      XVID MPEG-4 VIDEO CODEC
4     *      motion estimation
5     *
6     *      This program is an implementation of a part of one or more MPEG-4
7     *      Video tools as specified in ISO/IEC 14496-2 standard.  Those intending
8     *      to use this software module in hardware or software products are
9     *      advised that its use may infringe existing patents or copyrights, and
10     *      any such use would be at such party's own risk.  The original
11     *      developer of this software module and his/her company, and subsequent
12     *      editors and their companies, will have no liability for use of this
13     *      software or modifications or derivatives thereof.
14     *
15     *      This program is free software; you can redistribute it and/or modify
16     *      it under the terms of the GNU General Public License as published by
17     *      the Free Software Foundation; either version 2 of the License, or
18     *      (at your option) any later version.
19     *
20     *      This program is distributed in the hope that it will be useful,
21     *      but WITHOUT ANY WARRANTY; without even the implied warranty of
22     *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23     *      GNU General Public License for more details.
24     *
25     *      You should have received a copy of the GNU General Public License
26     *      along with this program; if not, write to the Free Software
27     *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28     *
29     *************************************************************************/
30    
31    /**************************************************************************
32     *
33   *  Modifications:   *  Modifications:
34   *   *
35   *      01.05.2002      updated MotionEstimationBVOP   *      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 */
         CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y-1);  
         CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y-1);  
         CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y);  
         CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y);  
         CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y+1);  
         CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y+1);  
         CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y+1);  
770    
771          return iMinSAD;                          if (iDirection)         //checking if anything found
772                            {
773                                    bDirection = iDirection;
774                                    iDirection = 0;
775                                    start_x = currMV->x;
776                                    start_y = currMV->y;
777                                    if (bDirection & 3)     //our candidate is left or right
778                                    {
779                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
780                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
781                                    } else                  // what remains here is up or down
782                                    {
783                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
784                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
785  }  }
786    
787  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)                                  if (iDirection) {
788                                            bDirection += iDirection;
789                                            start_x = currMV->x;
790                                            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;
875    }
876    
877  int32_t PMVfastSearch16(  
878                                          const uint8_t * const pRef,  #define CHECK_MV16_F_INTERPOL(X,Y,BX,BY) { \
879      if ( ((X) <= max_dx) && ((X) >= min_dx) \
880        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
881      { \
882        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
883        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
884        if (iSAD < iMinSAD) \
885        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
886    }
887    
888    #define CHECK_MV16_F_INTERPOL_DIR(X,Y,BX,BY,D) { \
889      if ( ((X) <= max_dx) && ((X) >= min_dx) \
890        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
891      { \
892        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
893        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
894        if (iSAD < iMinSAD) \
895        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
896    }
897    
898    #define CHECK_MV16_F_INTERPOL_FOUND(X,Y,BX,BY,D) { \
899      if ( ((X) <= max_dx) && ((X) >= min_dx) \
900        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
901      { \
902        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
903        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
904        if (iSAD < iMinSAD) \
905        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
906    }
907    
908    
909    #define CHECK_MV16_B_INTERPOL(FX,FY,X,Y) { \
910      if ( ((X) <= max_dx) && ((X) >= min_dx) \
911        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
912      { \
913        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
914        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
915        if (iSAD < iMinSAD) \
916        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
917    }
918    
919    
920    #define CHECK_MV16_B_INTERPOL_DIR(FX,FY,X,Y,D) { \
921      if ( ((X) <= max_dx) && ((X) >= min_dx) \
922        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
923      { \
924        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
925        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
926        if (iSAD < iMinSAD) \
927        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
928    }
929    
930    
931    #define CHECK_MV16_B_INTERPOL_FOUND(FX,FY,X,Y,D) { \
932      if ( ((X) <= max_dx) && ((X) >= min_dx) \
933        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
934      { \
935        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
936        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
937        if (iSAD < iMinSAD) \
938        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
939    }
940    
941    
942    #if (0==1)
943    int32_t
944    Diamond16_InterpolMainSearch(
945                                            const uint8_t * const f_pRef,
946                                             const uint8_t * const f_pRefH,
947                                             const uint8_t * const f_pRefV,
948                                             const uint8_t * const f_pRefHV,
949                                             const uint8_t * const cur,
950    
951                                            const uint8_t * const b_pRef,
952                                             const uint8_t * const b_pRefH,
953                                             const uint8_t * const b_pRefV,
954                                             const uint8_t * const b_pRefHV,
955    
956                                             const int x,
957                                             const int y,
958    
959                                       const int f_start_x,
960                                       const int f_start_y,
961                                       const int b_start_x,
962                                       const int b_start_y,
963    
964                                       int iMinSAD,
965                                       VECTOR * const f_currMV,
966                                       VECTOR * const b_currMV,
967    
968                                       const int f_center_x,
969                                       const int f_center_y,
970                                       const int b_center_x,
971                                       const int b_center_y,
972    
973                                             const int32_t min_dx,
974                                             const int32_t max_dx,
975                                             const int32_t min_dy,
976                                             const int32_t max_dy,
977                                             const int32_t iEdgedWidth,
978                                             const int32_t iDiamondSize,
979    
980                                             const int32_t f_iFcode,
981                                             const int32_t b_iFcode,
982    
983                                             const int32_t iQuant,
984                                             int iFound)
985    {
986    /* Do a diamond search around given starting point, return SAD of best */
987    
988            int32_t f_iDirection = 0;
989            int32_t b_iDirection = 0;
990            int32_t iSAD;
991    
992            VECTOR f_backupMV;
993            VECTOR b_backupMV;
994    
995            f_backupMV.x = start_x;
996            f_backupMV.y = start_y;
997            b_backupMV.x = start_x;
998            b_backupMV.y = start_y;
999    
1000    /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1001    
1002            CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1003            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1004            CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1005            CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1006    
1007            if (iDirection)
1008                    while (!iFound) {
1009                            iFound = 1;
1010                            backupMV = *currMV;
1011    
1012                            if (iDirection != 2)
1013                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1014                                                                                       backupMV.y, 1);
1015                            if (iDirection != 1)
1016                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1017                                                                                       backupMV.y, 2);
1018                            if (iDirection != 4)
1019                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
1020                                                                                       backupMV.y - iDiamondSize, 3);
1021                            if (iDirection != 3)
1022                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
1023                                                                                       backupMV.y + iDiamondSize, 4);
1024            } else {
1025                    currMV->x = start_x;
1026                    currMV->y = start_y;
1027            }
1028            return iMinSAD;
1029    }
1030    #endif
1031    
1032    
1033    int32_t
1034    AdvDiamond8_MainSearch(const uint8_t * const pRef,
1035                                               const uint8_t * const pRefH,
1036                                               const uint8_t * const pRefV,
1037                                               const uint8_t * const pRefHV,
1038                                               const uint8_t * const cur,
1039                                               const int x,
1040                                               const int y,
1041                                               int start_x,
1042                                               int start_y,
1043                                               int iMinSAD,
1044                                               VECTOR * const currMV,
1045                                               const int center_x,
1046                                               const int center_y,
1047                                               const int32_t min_dx,
1048                                               const int32_t max_dx,
1049                                               const int32_t min_dy,
1050                                               const int32_t max_dy,
1051                                               const int32_t iEdgedWidth,
1052                                               const int32_t iDiamondSize,
1053                                               const int32_t iFcode,
1054                                               const int32_t iQuant,
1055                                               int iDirection)
1056    {
1057    
1058            int32_t iSAD;
1059    
1060    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
1061    
1062            if (iDirection) {
1063                    CHECK_MV8_CANDIDATE(start_x - iDiamondSize, start_y);
1064                    CHECK_MV8_CANDIDATE(start_x + iDiamondSize, start_y);
1065                    CHECK_MV8_CANDIDATE(start_x, start_y - iDiamondSize);
1066                    CHECK_MV8_CANDIDATE(start_x, start_y + iDiamondSize);
1067            } else {
1068                    int bDirection = 1 + 2 + 4 + 8;
1069    
1070                    do {
1071                            iDirection = 0;
1072                            if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
1073                                    CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1074    
1075                            if (bDirection & 2)
1076                                    CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1077    
1078                            if (bDirection & 4)
1079                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1080    
1081                            if (bDirection & 8)
1082                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1083    
1084                            /* now we're doing diagonal checks near our candidate */
1085    
1086                            if (iDirection)         //checking if anything found
1087                            {
1088                                    bDirection = iDirection;
1089                                    iDirection = 0;
1090                                    start_x = currMV->x;
1091                                    start_y = currMV->y;
1092                                    if (bDirection & 3)     //our candidate is left or right
1093                                    {
1094                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1095                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1096                                    } else                  // what remains here is up or down
1097                                    {
1098                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1099                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1100                                    }
1101    
1102                                    if (iDirection) {
1103                                            bDirection += iDirection;
1104                                            start_x = currMV->x;
1105                                            start_y = currMV->y;
1106                                    }
1107                            } else                          //about to quit, eh? not so fast....
1108                            {
1109                                    switch (bDirection) {
1110                                    case 2:
1111                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1112                                                                                            start_y - iDiamondSize, 2 + 4);
1113                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1114                                                                                            start_y + iDiamondSize, 2 + 8);
1115                                            break;
1116                                    case 1:
1117                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1118                                                                                            start_y - iDiamondSize, 1 + 4);
1119                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1120                                                                                            start_y + iDiamondSize, 1 + 8);
1121                                            break;
1122                                    case 2 + 4:
1123                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1124                                                                                            start_y - iDiamondSize, 1 + 4);
1125                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1126                                                                                            start_y - iDiamondSize, 2 + 4);
1127                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1128                                                                                            start_y + iDiamondSize, 2 + 8);
1129                                            break;
1130                                    case 4:
1131                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1132                                                                                            start_y - iDiamondSize, 2 + 4);
1133                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1134                                                                                            start_y - iDiamondSize, 1 + 4);
1135                                            break;
1136                                    case 8:
1137                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1138                                                                                            start_y + iDiamondSize, 2 + 8);
1139                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1140                                                                                            start_y + iDiamondSize, 1 + 8);
1141                                            break;
1142                                    case 1 + 4:
1143                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1144                                                                                            start_y + iDiamondSize, 1 + 8);
1145                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1146                                                                                            start_y - iDiamondSize, 1 + 4);
1147                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1148                                                                                            start_y - iDiamondSize, 2 + 4);
1149                                            break;
1150                                    case 2 + 8:
1151                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1152                                                                                            start_y - iDiamondSize, 1 + 4);
1153                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1154                                                                                            start_y + iDiamondSize, 1 + 8);
1155                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1156                                                                                            start_y + iDiamondSize, 2 + 8);
1157                                            break;
1158                                    case 1 + 8:
1159                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1160                                                                                            start_y - iDiamondSize, 2 + 4);
1161                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1162                                                                                            start_y + iDiamondSize, 2 + 8);
1163                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1164                                                                                            start_y + iDiamondSize, 1 + 8);
1165                                            break;
1166                                    default:                //1+2+4+8 == we didn't find anything at all
1167                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1168                                                                                            start_y - iDiamondSize, 1 + 4);
1169                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1170                                                                                            start_y + iDiamondSize, 1 + 8);
1171                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1172                                                                                            start_y - iDiamondSize, 2 + 4);
1173                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1174                                                                                            start_y + iDiamondSize, 2 + 8);
1175                                            break;
1176                                    }
1177                                    if (!(iDirection))
1178                                            break;          //ok, the end. really
1179                                    else {
1180                                            bDirection = iDirection;
1181                                            start_x = currMV->x;
1182                                            start_y = currMV->y;
1183                                    }
1184                            }
1185                    }
1186                    while (1);                              //forever
1187            }
1188            return iMinSAD;
1189    }
1190    
1191    
1192    int32_t
1193    Full8_MainSearch(const uint8_t * const pRef,
1194                                     const uint8_t * const pRefH,
1195                                     const uint8_t * const pRefV,
1196                                     const uint8_t * const pRefHV,
1197                                     const uint8_t * const cur,
1198                                     const int x,
1199                                     const int y,
1200                               const int start_x,
1201                               const int start_y,
1202                               int iMinSAD,
1203                               VECTOR * const currMV,
1204                               const int center_x,
1205                               const int center_y,
1206                                     const int32_t min_dx,
1207                                     const int32_t max_dx,
1208                                     const int32_t min_dy,
1209                                     const int32_t max_dy,
1210                                     const int32_t iEdgedWidth,
1211                                     const int32_t iDiamondSize,
1212                                     const int32_t iFcode,
1213                                     const int32_t iQuant,
1214                                     int iFound)
1215    {
1216            int32_t iSAD;
1217            int32_t dx, dy;
1218            VECTOR backupMV;
1219    
1220            backupMV.x = start_x;
1221            backupMV.y = start_y;
1222    
1223            for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
1224                    for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
1225                            NOCHECK_MV8_CANDIDATE(dx, dy);
1226    
1227            return iMinSAD;
1228    }
1229    
1230    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1231    
1232    int32_t
1233    Halfpel16_Refine(const uint8_t * const pRef,
1234                                     const uint8_t * const pRefH,
1235                                     const uint8_t * const pRefV,
1236                                     const uint8_t * const pRefHV,
1237                                     const uint8_t * const cur,
1238                                     const int x,
1239                                     const int y,
1240                                     VECTOR * const currMV,
1241                                     int32_t iMinSAD,
1242                               const int center_x,
1243                               const int center_y,
1244                                     const int32_t min_dx,
1245                                     const int32_t max_dx,
1246                                     const int32_t min_dy,
1247                                     const int32_t max_dy,
1248                                     const int32_t iFcode,
1249                                     const int32_t iQuant,
1250                                     const int32_t iEdgedWidth)
1251    {
1252    /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
1253    
1254            int32_t iSAD;
1255            VECTOR backupMV = *currMV;
1256    
1257            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y - 1);
1258            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y - 1);
1259            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y - 1);
1260            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y);
1261            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y);
1262            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y + 1);
1263            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y + 1);
1264            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y + 1);
1265    
1266            return iMinSAD;
1267    }
1268    
1269    #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1270    
1271    
1272    
1273    int32_t
1274    PMVfastSearch16(const uint8_t * const pRef,
1275                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1276                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1277                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1278                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1279                                          const int x, const int y,                                  const int x,
1280                                    const int y,
1281                                    const int start_x,
1282                                    const int start_y,
1283                                    const int center_x,
1284                                    const int center_y,
1285                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1286                                          const uint32_t iQuant,                                          const uint32_t iQuant,
1287                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 861  Line 1313 
1313          VECTOR pmv[4];          VECTOR pmv[4];
1314          int32_t psad[4];          int32_t psad[4];
1315    
1316          const MACROBLOCK * const pMB = pMBs + x + y * iWcount;          MainSearch16FuncPtr MainSearchPtr;
1317    
1318          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1319    
1320          static int32_t threshA,threshB;          int32_t threshA, threshB;
1321          int32_t bPredEq;          int32_t bPredEq;
1322          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1323    
1324  /* Get maximum range */  /* Get maximum range */
1325          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
1326                    x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
1327    
1328  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1329    
1330          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
1331          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1332          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1333          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1334          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1335          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
   
1336    
1337          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1338            //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1339            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1340    
1341          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1342                  threshA =  512;                  threshA =  512;
1343                  threshB = 1024;                  threshB = 1024;
1344            } else {
         }  
         else  
         {  
1345                  threshA = psad[0];                  threshA = psad[0];
1346                  threshB = threshA+256;                  threshB = threshA+256;
1347                  if (threshA< 512) threshA =  512;                  if (threshA < 512)
1348                  if (threshA>1024) threshA = 1024;                          threshA = 512;
1349                  if (threshB>1792) threshB = 1792;                  if (threshA > 1024)
1350                            threshA = 1024;
1351                    if (threshB > 1792)
1352                            threshB = 1792;
1353          }          }
1354    
1355          iFound=0;          iFound=0;
1356    
 /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  
    vector of the median.  
    If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2  
 */  
   
         if ((bPredEq) && (MVequal(pmv[0],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;  
   
1357  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1358     MinSAD=SAD     MinSAD=SAD
1359     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 928  Line 1361 
1361     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
1362  */  */
1363    
1364            currMV->x = start_x;
1365            currMV->y = start_y;
1366    
1367  // Prepare for main loop          if (!(MotionFlags & PMV_HALFPEL16)) {   /* This should NOT be necessary! */
   
         *currMV=pmv[0];         /* current best := prediction */  
         if (!(MotionFlags & PMV_HALFPEL16 ))  
         {       /* This should NOT be necessary! */  
1368                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1369                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
1370          }          }
1371    
1372          if (currMV->x > max_dx)          if (currMV->x > max_dx) {
         {  
1373                  currMV->x=max_dx;                  currMV->x=max_dx;
1374          }          }
1375          if (currMV->x < min_dx)          if (currMV->x < min_dx) {
         {  
1376                  currMV->x=min_dx;                  currMV->x=min_dx;
1377          }          }
1378          if (currMV->y > max_dy)          if (currMV->y > max_dy) {
         {  
1379                  currMV->y=max_dy;                  currMV->y=max_dy;
1380          }          }
1381          if (currMV->y < min_dy)          if (currMV->y < min_dy) {
         {  
1382                  currMV->y=min_dy;                  currMV->y=min_dy;
1383          }          }
1384    
1385          iMinSAD = sad16( cur,          iMinSAD =
1386                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1387                           iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1388          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1389            iMinSAD +=
1390          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
1391          {                                            (uint8_t) iFcode, iQuant);
1392    
1393            if ((iMinSAD < 256) ||
1394                    ((MVequal(*currMV, prevMB->mvs[0])) &&
1395                     ((int32_t) iMinSAD < prevMB->sad16))) {
1396                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
1397                    {
1398                            if (!MVzero(*currMV)) {
1399                                    iMinSAD += MV16_00_BIAS;
1400                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
1401                                    iMinSAD -= MV16_00_BIAS;
1402                            }
1403                    }
1404    
1405                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1406                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
# Line 969  Line 1408 
1408                          goto PMVfast16_Terminate_with_Refine;                          goto PMVfast16_Terminate_with_Refine;
1409          }          }
1410    
1411    
1412    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1413       vector of the median.
1414       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1415    */
1416    
1417            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[0])))
1418                    iFound = 2;
1419    
1420    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1421       Otherwise select large Diamond Search.
1422    */
1423    
1424            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
1425                    iDiamondSize = 1;               // halfpel!
1426            else
1427                    iDiamondSize = 2;               // halfpel!
1428    
1429            if (!(MotionFlags & PMV_HALFPELDIAMOND16))
1430                    iDiamondSize *= 2;
1431    
1432  /*  /*
1433     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
1434     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
# Line 978  Line 1438 
1438    
1439  // (0,0) is always possible  // (0,0) is always possible
1440    
1441            if (!MVzero(pmv[0]))
1442          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1443    
1444  // previous frame MV is always possible  // previous frame MV is always possible
1445    
1446            if (!MVzero(prevMB->mvs[0]))
1447                    if (!MVequal(prevMB->mvs[0], pmv[0]))
1448          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1449    
1450  // left neighbour, if allowed  // left neighbour, if allowed
1451          if (x != 0)  
1452          {          if (!MVzero(pmv[1]))
1453                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!MVequal(pmv[1], prevMB->mvs[0]))
1454                  {       pmv[1].x = EVEN(pmv[1].x);                          if (!MVequal(pmv[1], pmv[0])) {
1455                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1456                                            pmv[1].x = EVEN(pmv[1].x);
1457                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1458                  }                  }
1459    
1460                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1461          }          }
   
1462  // top neighbour, if allowed  // top neighbour, if allowed
1463          if (y != 0)          if (!MVzero(pmv[2]))
1464          {                  if (!MVequal(pmv[2], prevMB->mvs[0]))
1465                  if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!MVequal(pmv[2], pmv[0]))
1466                  {       pmv[2].x = EVEN(pmv[2].x);                                  if (!MVequal(pmv[2], pmv[1])) {
1467                                            if (!(MotionFlags & PMV_HALFPEL16)) {
1468                                                    pmv[2].x = EVEN(pmv[2].x);
1469                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
1470                  }                  }
1471                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1472    
1473  // top right neighbour, if allowed  // top right neighbour, if allowed
1474                  if ((uint32_t)x != (iWcount-1))                                          if (!MVzero(pmv[3]))
1475                  {                                                  if (!MVequal(pmv[3], prevMB->mvs[0]))
1476                          if (!(MotionFlags & PMV_HALFPEL16 ))                                                          if (!MVequal(pmv[3], pmv[0]))
1477                          {       pmv[3].x = EVEN(pmv[3].x);                                                                  if (!MVequal(pmv[3], pmv[1]))
1478                                                                            if (!MVequal(pmv[3], pmv[2])) {
1479                                                                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1480                                                                                            pmv[3].x = EVEN(pmv[3].x);
1481                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1482                          }                          }
1483                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                  CHECK_MV16_CANDIDATE(pmv[3].x,
1484                                                                                                                             pmv[3].y);
1485                  }                  }
1486          }          }
1487    
1488          if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96)*/ )          if ((MVzero(*currMV)) &&
1489                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1490                  iMinSAD -= MV16_00_BIAS;                  iMinSAD -= MV16_00_BIAS;
1491    
1492    
# Line 1021  Line 1494 
1494     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
1495  */  */
1496    
1497          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ((iMinSAD <= threshA) ||
1498          {                  (MVequal(*currMV, prevMB->mvs[0]) &&
1499                     ((int32_t) iMinSAD < prevMB->sad16))) {
1500                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1501                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
1502                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1040  Line 1514 
1514     Refine by using small diamond and goto step 10.     Refine by using small diamond and goto step 10.
1515  */  */
1516    
1517            if (MotionFlags & PMV_USESQUARES16)
1518                    MainSearchPtr = Square16_MainSearch;
1519            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
1520                    MainSearchPtr = AdvDiamond16_MainSearch;
1521            else
1522                    MainSearchPtr = Diamond16_MainSearch;
1523    
1524          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1525    
1526    
1527  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1528          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1529                                            x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1530                                            currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->x, currMV->y, iMinSAD, &newMV, center_x, center_y,
1531                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dx, max_dx,
1532                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1533                                                      iQuant, iFound);
1534    
1535          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1536                  *currMV = newMV;                  *currMV = newMV;
1537                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1538          }          }
1539    
1540          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
1541  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1542    
1543                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1544                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1545                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1546                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    center_x, center_y, iMinSAD, &newMV, center_x, center_y,
1547                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1548                                                                      iDiamondSize, iFcode, iQuant, iFound);
1549    
1550                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1551                          *currMV = newMV;                          *currMV = newMV;
1552                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1553                  }                  }
1554                  }                  }
1555    
1556                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1557                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1558                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1559                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y,
1560                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy,
1561                                                                      iEdgedWidth, iDiamondSize, iFcode,
1562                                                                      iQuant, iFound);
1563    
1564                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1565                          *currMV = newMV;                          *currMV = newMV;
1566                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1567                  }                  }
# Line 1091  Line 1574 
1574    
1575  PMVfast16_Terminate_with_Refine:  PMVfast16_Terminate_with_Refine:
1576          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1577                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1578                                    x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1579                                    currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1580                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1581    
1582  PMVfast16_Terminate_without_Refine:  PMVfast16_Terminate_without_Refine:
1583          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
1584          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
1585          return iMinSAD;          return iMinSAD;
1586  }  }
1587    
# Line 1107  Line 1590 
1590    
1591    
1592    
1593  int32_t Diamond8_MainSearch(  int32_t
1594          const uint8_t * const pRef,  Diamond8_MainSearch(const uint8_t * const pRef,
1595          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1596          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1597          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1598          const uint8_t * const cur,          const uint8_t * const cur,
1599          const int x, const int y,                                          const int x,
1600          int32_t startx, int32_t starty,                                          const int y,
1601                                            int32_t start_x,
1602                                            int32_t start_y,
1603          int32_t iMinSAD,          int32_t iMinSAD,
1604          VECTOR * const currMV,          VECTOR * const currMV,
1605          const VECTOR * const pmv,                                     const int center_x,
1606          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
1607          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
1608                                            const int32_t max_dx,
1609                                            const int32_t min_dy,
1610                                            const int32_t max_dy,
1611          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
1612          const int32_t iDiamondSize,          const int32_t iDiamondSize,
1613          const int32_t iFcode,          const int32_t iFcode,
# Line 1129  Line 1617 
1617  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
1618    
1619          int32_t iDirection=0;          int32_t iDirection=0;
1620            int32_t iDirectionBackup;
1621          int32_t iSAD;          int32_t iSAD;
1622          VECTOR backupMV;          VECTOR backupMV;
1623          backupMV.x = startx;  
1624          backupMV.y = starty;          backupMV.x = start_x;
1625            backupMV.y = start_y;
1626    
1627  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1628    
# Line 1141  Line 1631 
1631          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
1632          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1633    
1634          if (iDirection)          if (iDirection) {
1635                  while (!iFound)                  while (!iFound) {
                 {  
1636                          iFound = 1;                          iFound = 1;
1637                          backupMV=*currMV;       // since iDirection!=0, this is well defined!                          backupMV=*currMV;       // since iDirection!=0, this is well defined!
1638                            iDirectionBackup = iDirection;
1639    
1640                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
1641                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1642                          if ( iDirection != 1)                                                                                    backupMV.y, 1);
1643                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
1644                          if ( iDirection != 4)                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1645                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                    backupMV.y, 2);
1646                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
1647                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1648                                                                                      backupMV.y - iDiamondSize, 3);
1649                            if (iDirectionBackup != 3)
1650                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1651                                                                                      backupMV.y + iDiamondSize, 4);
1652                  }                  }
1653          else          } else {
1654                    currMV->x = start_x;
1655                    currMV->y = start_y;
1656            }
1657            return iMinSAD;
1658    }
1659    
1660    
1661    
1662    
1663    int32_t
1664    Square8_MainSearch(const uint8_t * const pRef,
1665                                            const uint8_t * const pRefH,
1666                                            const uint8_t * const pRefV,
1667                                            const uint8_t * const pRefHV,
1668                                            const uint8_t * const cur,
1669                                            const int x,
1670                                            const int y,
1671                                            int32_t start_x,
1672                                            int32_t start_y,
1673                                            int32_t iMinSAD,
1674                                            VECTOR * const currMV,
1675                                       const int center_x,
1676                                       const int center_y,
1677                                            const int32_t min_dx,
1678                                            const int32_t max_dx,
1679                                            const int32_t min_dy,
1680                                            const int32_t max_dy,
1681                                            const int32_t iEdgedWidth,
1682                                            const int32_t iDiamondSize,
1683                                            const int32_t iFcode,
1684                                            const int32_t iQuant,
1685                                            int iFound)
1686          {          {
1687                  currMV->x = startx;  /* Do a square search around given starting point, return SAD of best */
1688                  currMV->y = starty;  
1689            int32_t iDirection = 0;
1690            int32_t iSAD;
1691            VECTOR backupMV;
1692    
1693            backupMV.x = start_x;
1694            backupMV.y = start_y;
1695    
1696    /* It's one search with full square pattern, and new parts for all following diamonds */
1697    
1698    /*   new direction are extra, so 1-4 is normal diamond
1699          537
1700          1*2
1701          648
1702    */
1703    
1704            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1705            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1706            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1707            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1708    
1709            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1710                                                             backupMV.y - iDiamondSize, 5);
1711            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1712                                                             backupMV.y + iDiamondSize, 6);
1713            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1714                                                             backupMV.y - iDiamondSize, 7);
1715            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1716                                                             backupMV.y + iDiamondSize, 8);
1717    
1718    
1719            if (iDirection) {
1720                    while (!iFound) {
1721                            iFound = 1;
1722                            backupMV = *currMV;
1723    
1724                            switch (iDirection) {
1725                            case 1:
1726                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1727                                                                                       backupMV.y, 1);
1728                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1729                                                                                     backupMV.y - iDiamondSize, 5);
1730                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1731                                                                                     backupMV.y - iDiamondSize, 7);
1732                                    break;
1733                            case 2:
1734                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1735                                                                                     2);
1736                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1737                                                                                     backupMV.y + iDiamondSize, 6);
1738                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1739                                                                                     backupMV.y + iDiamondSize, 8);
1740                                    break;
1741    
1742                            case 3:
1743                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1744                                                                                     4);
1745                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1746                                                                                     backupMV.y - iDiamondSize, 7);
1747                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1748                                                                                     backupMV.y + iDiamondSize, 8);
1749                                    break;
1750    
1751                            case 4:
1752                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1753                                                                                     3);
1754                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1755                                                                                     backupMV.y - iDiamondSize, 5);
1756                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1757                                                                                     backupMV.y + iDiamondSize, 6);
1758                                    break;
1759    
1760                            case 5:
1761                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1762                                                                                     1);
1763                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1764                                                                                     3);
1765                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1766                                                                                     backupMV.y - iDiamondSize, 5);
1767                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1768                                                                                     backupMV.y + iDiamondSize, 6);
1769                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1770                                                                                     backupMV.y - iDiamondSize, 7);
1771                                    break;
1772    
1773                            case 6:
1774                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1775                                                                                     2);
1776                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1777                                                                                     3);
1778    
1779                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1780                                                                                     backupMV.y - iDiamondSize, 5);
1781                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1782                                                                                     backupMV.y + iDiamondSize, 6);
1783                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1784                                                                                     backupMV.y + iDiamondSize, 8);
1785    
1786                                    break;
1787    
1788                            case 7:
1789                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1790                                                                                       backupMV.y, 1);
1791                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1792                                                                                     4);
1793                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1794                                                                                     backupMV.y - iDiamondSize, 5);
1795                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1796                                                                                     backupMV.y - iDiamondSize, 7);
1797                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1798                                                                                     backupMV.y + iDiamondSize, 8);
1799                                    break;
1800    
1801                            case 8:
1802                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1803                                                                                     2);
1804                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1805                                                                                     4);
1806                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1807                                                                                     backupMV.y + iDiamondSize, 6);
1808                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1809                                                                                     backupMV.y - iDiamondSize, 7);
1810                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1811                                                                                     backupMV.y + iDiamondSize, 8);
1812                                    break;
1813                            default:
1814                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1815                                                                                     1);
1816                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1817                                                                                     2);
1818                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1819                                                                                     3);
1820                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1821                                                                                     4);
1822    
1823                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1824                                                                                     backupMV.y - iDiamondSize, 5);
1825                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1826                                                                                     backupMV.y + iDiamondSize, 6);
1827                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1828                                                                                     backupMV.y - iDiamondSize, 7);
1829                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1830                                                                                     backupMV.y + iDiamondSize, 8);
1831                                    break;
1832                            }
1833                    }
1834            } else {
1835                    currMV->x = start_x;
1836                    currMV->y = start_y;
1837          }          }
1838          return iMinSAD;          return iMinSAD;
1839  }  }
1840    
1841  int32_t Halfpel8_Refine(  
1842          const uint8_t * const pRef,  
1843    
1844    
1845    int32_t
1846    Halfpel8_Refine_c(const uint8_t * const pRef,
1847          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1848          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1849          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1850          const uint8_t * const cur,          const uint8_t * const cur,
1851          const int x, const int y,                                  const int x,
1852                                    const int y,
1853          VECTOR * const currMV,          VECTOR * const currMV,
1854          int32_t iMinSAD,          int32_t iMinSAD,
1855          const VECTOR * const pmv,                             const int center_x,
1856          const int32_t min_dx, const int32_t max_dx,                             const int center_y,
1857          const int32_t min_dy, const int32_t max_dy,                                  const int32_t min_dx,
1858                                    const int32_t max_dx,
1859                                    const int32_t min_dy,
1860                                    const int32_t max_dy,
1861          const int32_t iFcode,          const int32_t iFcode,
1862          const int32_t iQuant,          const int32_t iQuant,
1863          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 1200  Line 1882 
1882    
1883  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1884    
1885  int32_t PMVfastSearch8(  int32_t
1886                                          const uint8_t * const pRef,  PMVfastSearch8(const uint8_t * const pRef,
1887                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1888                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1889                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1890                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1891                                          const int x, const int y,                             const int x,
1892                                          const int start_x, const int start_y,                             const int y,
1893                               const int start_x,
1894                               const int start_y,
1895                                    const int center_x,
1896                                    const int center_y,
1897                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1898                                          const uint32_t iQuant,                                          const uint32_t iQuant,
1899                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1235  Line 1921 
1921          int32_t psad[4];          int32_t psad[4];
1922          VECTOR newMV;          VECTOR newMV;
1923          VECTOR backupMV;          VECTOR backupMV;
1924            VECTOR startMV;
1925    
1926          const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1927          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1928    
1929          static int32_t threshA,threshB;           int32_t threshA, threshB;
1930          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
1931          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1932    
1933          int32_t iSubBlock = ((y&1)<<1) + (x&1);          int32_t iSubBlock = (y & 1) + (y & 1) + (x & 1);
1934    
1935            MainSearch8FuncPtr MainSearchPtr;
1936    
1937            /* Init variables */
1938            startMV.x = start_x;
1939            startMV.y = start_y;
1940    
1941  /* Get maximum range */  /* Get maximum range */
1942          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,
1943                    x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
1944    
1945          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
1946          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1947          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1948          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1949          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1950          }               /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          }
   
1951    
1952          bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
1953            //bPredEq = get_pmvdata(pMBs, (x >> 1), (y >> 1), iWcount, iSubBlock, pmv, psad);
1954            bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
1955    
1956          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1957                  threshA =  512/4;                  threshA =  512/4;
1958                  threshB = 1024/4;                  threshB = 1024/4;
1959    
1960          }          } else {
1961          else                  threshA = psad[0] / 4;  /* good estimate? */
         {  
                 threshA = psad[0]/4;                    /* good estimate */  
1962                  threshB = threshA+256/4;                  threshB = threshA+256/4;
1963                  if (threshA< 512/4) threshA =  512/4;                  if (threshA < 512 / 4)
1964                  if (threshA>1024/4) threshA = 1024/4;                          threshA = 512 / 4;
1965                  if (threshB>1792/4) threshB = 1792/4;                  if (threshA > 1024 / 4)
1966                            threshA = 1024 / 4;
1967                    if (threshB > 1792 / 4)
1968                            threshB = 1792 / 4;
1969          }          }
1970    
1971          iFound=0;          iFound=0;
1972    
 /* 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[iSubBlock]) ) )  
                 iFound=2;  
   
 /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  
    Otherwise select large Diamond Search.  
 */  
   
         if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536/4) || (bPredEq) )  
                 iDiamondSize=1; // 1 halfpel!  
         else  
                 iDiamondSize=2; // 2 halfpel = 1 full pixel!  
   
         if (!(MotionFlags & PMV_HALFPELDIAMOND8) )  
                 iDiamondSize*=2;  
   
1973  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1974     MinSAD=SAD     MinSAD=SAD
1975     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 1306  Line 1980 
1980    
1981  // Prepare for main loop  // Prepare for main loop
1982    
1983          currMV->x=start_x;              /* start with mv16 */    if (MotionFlags & PMV_USESQUARES8)
1984          currMV->y=start_y;        MainSearchPtr = Square8_MainSearch;
1985      else
1986    
1987          iMinSAD = sad8( cur,          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
1988                          get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  MainSearchPtr = AdvDiamond8_MainSearch;
1989                          iEdgedWidth);          else
1990          iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode, iQuant);                  MainSearchPtr = Diamond8_MainSearch;
1991    
1992          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock])) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )  
1993          {          *currMV = startMV;
1994    
1995            iMinSAD =
1996                    sad8(cur,
1997                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
1998                                                    iEdgedWidth), iEdgedWidth);
1999            iMinSAD +=
2000                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2001                                             (uint8_t) iFcode, iQuant);
2002    
2003            if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))
2004                                                                    && ((int32_t) iMinSAD <
2005                                                                            prevMB->sad8[iSubBlock]))) {
2006                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2007                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2008                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
2009                          goto PMVfast8_Terminate_with_Refine;                          goto PMVfast8_Terminate_with_Refine;
2010          }          }
2011    
2012    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2013       vector of the median.
2014       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2015    */
2016    
2017            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[iSubBlock])))
2018                    iFound = 2;
2019    
2020    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2021       Otherwise select large Diamond Search.
2022    */
2023    
2024            if ((!MVzero(pmv[0])) || (threshB < 1536 / 4) || (bPredEq))
2025                    iDiamondSize = 1;               // 1 halfpel!
2026            else
2027                    iDiamondSize = 2;               // 2 halfpel = 1 full pixel!
2028    
2029            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2030                    iDiamondSize *= 2;
2031    
2032    
2033  /*  /*
2034     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
# Line 1330  Line 2037 
2037     If MV is (0,0) subtract offset.     If MV is (0,0) subtract offset.
2038  */  */
2039    
2040  // the prediction might be even better than mv16  // the median prediction might be even better than mv16
         CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);  
2041    
2042  // (0,0) is always possible          if (!MVequal(pmv[0], startMV))
2043                    CHECK_MV8_CANDIDATE(center_x, center_y);
2044    
2045    // (0,0) if needed
2046            if (!MVzero(pmv[0]))
2047                    if (!MVzero(startMV))
2048          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
2049    
2050  // previous frame MV is always possible  // previous frame MV if needed
2051          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);          if (!MVzero(prevMB->mvs[iSubBlock]))
2052                    if (!MVequal(prevMB->mvs[iSubBlock], startMV))
2053                            if (!MVequal(prevMB->mvs[iSubBlock], pmv[0]))
2054                                    CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,
2055                                                                            prevMB->mvs[iSubBlock].y);
2056    
2057            if ((iMinSAD <= threshA) ||
2058                    (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2059                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2060                    if (MotionFlags & PMV_QUICKSTOP16)
2061                            goto PMVfast8_Terminate_without_Refine;
2062                    if (MotionFlags & PMV_EARLYSTOP16)
2063                            goto PMVfast8_Terminate_with_Refine;
2064            }
2065    
2066  // left neighbour, if allowed  // left neighbour, if allowed and needed
2067          if (psad[1] != MV_MAX_ERROR)          if (!MVzero(pmv[1]))
2068          {                  if (!MVequal(pmv[1], startMV))
2069                  if (!(MotionFlags & PMV_HALFPEL8 ))                          if (!MVequal(pmv[1], prevMB->mvs[iSubBlock]))
2070                  {       pmv[1].x = EVEN(pmv[1].x);                                  if (!MVequal(pmv[1], pmv[0])) {
2071                                            if (!(MotionFlags & PMV_HALFPEL8)) {
2072                                                    pmv[1].x = EVEN(pmv[1].x);
2073                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
2074                  }                  }
2075                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
2076          }          }
2077    // top neighbour, if allowed and needed
2078  // top neighbour, if allowed          if (!MVzero(pmv[2]))
2079          if (psad[2] != MV_MAX_ERROR)                  if (!MVequal(pmv[2], startMV))
2080          {                          if (!MVequal(pmv[2], prevMB->mvs[iSubBlock]))
2081                  if (!(MotionFlags & PMV_HALFPEL8 ))                                  if (!MVequal(pmv[2], pmv[0]))
2082                  {       pmv[2].x = EVEN(pmv[2].x);                                          if (!MVequal(pmv[2], pmv[1])) {
2083                                                    if (!(MotionFlags & PMV_HALFPEL8)) {
2084                                                            pmv[2].x = EVEN(pmv[2].x);
2085                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
2086                  }                  }
2087                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
2088    
2089  // top right neighbour, if allowed  // top right neighbour, if allowed and needed
2090                  if (psad[3] != MV_MAX_ERROR)                                                  if (!MVzero(pmv[3]))
2091                  {                                                          if (!MVequal(pmv[3], startMV))
2092                          if (!(MotionFlags & PMV_HALFPEL8 ))                                                                  if (!MVequal(pmv[3], prevMB->mvs[iSubBlock]))
2093                          {       pmv[3].x = EVEN(pmv[3].x);                                                                          if (!MVequal(pmv[3], pmv[0]))
2094                                                                                    if (!MVequal(pmv[3], pmv[1]))
2095                                                                                            if (!MVequal(pmv[3], pmv[2])) {
2096                                                                                                    if (!
2097                                                                                                            (MotionFlags &
2098                                                                                                             PMV_HALFPEL8)) {
2099                                                                                                            pmv[3].x = EVEN(pmv[3].x);
2100                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
2101                          }                          }
2102                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                                  CHECK_MV8_CANDIDATE(pmv[3].x,
2103                                                                                                                                            pmv[3].y);
2104                  }                  }
2105          }          }
2106    
2107          if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )          if ((MVzero(*currMV)) &&
2108                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2109                  iMinSAD -= MV8_00_BIAS;                  iMinSAD -= MV8_00_BIAS;
2110    
2111    
# Line 1377  Line 2113 
2113     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
2114  */  */
2115    
2116          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
2117          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2118                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2119                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2120                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2121                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1398  Line 2135 
2135          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2136    
2137  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2138          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2139                                           x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2140                                           currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2141                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2142                                                      iQuant, iFound);
2143    
2144          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2145                  *currMV = newMV;                  *currMV = newMV;
2146                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2147          }          }
2148    
2149          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2150  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
2151    
2152                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2153                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2154                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2155                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2156                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2157                                                                      iDiamondSize, iFcode, iQuant, iFound);
2158    
2159                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2160                          *currMV = newMV;                          *currMV = newMV;
2161                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2162                  }                  }
2163                  }                  }
2164    
2165                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2166                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2167                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2168                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2169                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2170                                                                      iQuant, iFound);
2171    
2172                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2173                          *currMV = newMV;                          *currMV = newMV;
2174                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2175                  }                  }
# Line 1446  Line 2182 
2182    
2183  PMVfast8_Terminate_with_Refine:  PMVfast8_Terminate_with_Refine:
2184          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2185                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2186                                                   x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2187                                                   currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2188                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2189    
2190    
2191  PMVfast8_Terminate_without_Refine:  PMVfast8_Terminate_without_Refine:
2192          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2193          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2194    
2195          return iMinSAD;          return iMinSAD;
2196  }  }
2197    
2198  int32_t EPZSSearch16(  int32_t
2199                                          const uint8_t * const pRef,  EPZSSearch16(const uint8_t * const pRef,
2200                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2201                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2202                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2203                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2204                                          const int x, const int y,                           const int x,
2205                             const int y,
2206                            const int start_x,
2207                            const int start_y,
2208                            const int center_x,
2209                            const int center_y,
2210                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2211                                          const uint32_t iQuant,                                          const uint32_t iQuant,
2212                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1496  Line 2237 
2237          int32_t psad[8];          int32_t psad[8];
2238    
2239          static MACROBLOCK * oldMBs = NULL;          static MACROBLOCK * oldMBs = NULL;
2240          const MACROBLOCK * const pMB = pMBs + x + y * iWcount;  
2241    //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
2242          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
2243          MACROBLOCK * oldMB = NULL;          MACROBLOCK * oldMB = NULL;
2244    
2245          static int32_t thresh2;           int32_t thresh2;
2246          int32_t bPredEq;          int32_t bPredEq;
2247          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2248    
2249          MainSearch16FuncPtr EPZSMainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
2250    
2251          if (oldMBs == NULL)          if (oldMBs == NULL) {
2252          {       oldMBs = (MACROBLOCK*) calloc(iWcount*iHcount,sizeof(MACROBLOCK));                  oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
2253  //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));  //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
2254          }          }
2255          oldMB = oldMBs + x + y * iWcount;          oldMB = oldMBs + x + y * iWcount;
2256    
2257  /* Get maximum range */  /* Get maximum range */
2258          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2259                          x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
2260    
2261          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
2262          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2263            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2264            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2265            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2266          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2267            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2268          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
2269            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2270    
2271  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2272          MinSAD=SAD          MinSAD=SAD
# Line 1534  Line 2277 
2277    
2278  // Prepare for main loop  // Prepare for main loop
2279    
2280          *currMV=pmv[0];         /* current best := median prediction */          currMV->x = start_x;
2281          if (!(MotionFlags & PMV_HALFPEL16))          currMV->y = start_y;
2282          {  
2283            if (!(MotionFlags & PMV_HALFPEL16)) {
2284                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2285                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2286          }          }
# Line 1552  Line 2296 
2296    
2297  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2298    
2299          iMinSAD = sad16( cur,          iMinSAD =
2300                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
2301                  iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2302          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2303            iMinSAD +=
2304                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2305                                              (uint8_t) iFcode, iQuant);
2306    
2307  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2308          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV, prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ((iMinSAD < 256) ||
2309                  {                  ((MVequal(*currMV, prevMB->mvs[0])) &&
2310                     ((int32_t) iMinSAD < prevMB->sad16))) {
2311                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2312                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2313                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1574  Line 2322 
2322  // set threshhold based on Min of Prediction and SAD of collocated block  // set threshhold based on Min of Prediction and SAD of collocated block
2323  // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want  // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
2324    
2325          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
2326                  thresh2 =  512;                  thresh2 =  512;
2327          }          } else {
         else  
         {  
2328  /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */  /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */
2329    
2330                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
# Line 1591  Line 2336 
2336    
2337    
2338  // left neighbour, if allowed  // left neighbour, if allowed
2339          if (x != 0)          if (x != 0) {
2340          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2341                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2342                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2343                  }                  }
2344                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
2345          }          }
   
2346  // top neighbour, if allowed  // top neighbour, if allowed
2347          if (y != 0)          if (y != 0) {
2348          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2349                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2350                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2351                  }                  }
2352                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
2353    
2354  // top right neighbour, if allowed  // top right neighbour, if allowed
2355                  if ((uint32_t)x != (iWcount-1))                  if ((uint32_t) x != (iWcount - 1)) {
2356                  {                          if (!(MotionFlags & PMV_HALFPEL16)) {
2357                          if (!(MotionFlags & PMV_HALFPEL16 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2358                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2359                          }                          }
2360                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
# Line 1625  Line 2366 
2366  */  */
2367    
2368          if ( (iMinSAD <= thresh2)          if ( (iMinSAD <= thresh2)
2369                  || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )                  || (MVequal(*currMV, prevMB->mvs[0]) &&
2370                  {                          ((int32_t) iMinSAD <= prevMB->sad16))) {
2371                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2372                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2373                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1647  Line 2388 
2388    
2389  // top neighbour  // top neighbour
2390          if (y != 0)          if (y != 0)
2391                  CHECK_MV16_CANDIDATE((prevMB-iWcount)->mvs[0].x,(prevMB-iWcount)->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,
2392                                                             (prevMB - iWcount)->mvs[0].y);
2393    
2394  // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs  // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
2395    
# Line 1656  Line 2398 
2398    
2399  // bottom neighbour, dito  // bottom neighbour, dito
2400          if ((uint32_t)y != iHcount-1)          if ((uint32_t)y != iHcount-1)
2401                  CHECK_MV16_CANDIDATE((prevMB+iWcount)->mvs[0].x,(prevMB+iWcount)->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,
2402                                                             (prevMB + iWcount)->mvs[0].y);
2403    
2404  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
2405          if (iMinSAD <= thresh2)          if (iMinSAD <= thresh2) {
                 {  
2406                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2407                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2408                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1671  Line 2413 
2413    
2414          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2415    
 /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  
   
2416          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
2417                  EPZSMainSearchPtr = Square16_MainSearch;                  MainSearchPtr = Square16_MainSearch;
2418            else
2419             if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2420                    MainSearchPtr = AdvDiamond16_MainSearch;
2421          else          else
2422                  EPZSMainSearchPtr = Diamond16_MainSearch;                  MainSearchPtr = Diamond16_MainSearch;
2423    
2424          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
                         x, y,  
                         currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,  
                         2, iFcode, iQuant, 0);  
2425    
2426          if (iSAD < iMinSAD)          iSAD =
2427          {                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2428                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2429                                                      min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2430    
2431            if (iSAD < iMinSAD) {
2432                  *currMV = newMV;                  *currMV = newMV;
2433                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2434          }          }
2435    
2436    
2437          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
2438  /* 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) */
2439    
2440                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2441                  {                          iSAD =
2442                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2443                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2444                                  pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2445                                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    2, iFcode, iQuant, 0);
2446                  }                  }
2447    
2448                  if (iSAD < iMinSAD)                  if (iSAD < iMinSAD) {
                 {  
2449                          *currMV = newMV;                          *currMV = newMV;
2450                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2451                  }                  }
2452    
2453                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2454                  {                          iSAD =
2455                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2456                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2457                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
                         pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);  
2458    
2459                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2460                                  *currMV = newMV;                                  *currMV = newMV;
2461                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2462                          }                          }
# Line 1727  Line 2467 
2467    
2468  EPZS16_Terminate_with_Refine:  EPZS16_Terminate_with_Refine:
2469          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
2470                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2471                                  x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2472                                  currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2473                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
2474    
2475  EPZS16_Terminate_without_Refine:  EPZS16_Terminate_without_Refine:
2476    
2477          *oldMB = *prevMB;          *oldMB = *prevMB;
2478    
2479          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2480          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2481          return iMinSAD;          return iMinSAD;
2482  }  }
2483    
2484    
2485  int32_t EPZSSearch8(  int32_t
2486                                          const uint8_t * const pRef,  EPZSSearch8(const uint8_t * const pRef,
2487                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2488                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2489                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2490                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2491                                          const int x, const int y,                          const int x,
2492                                          const int start_x, const int start_y,                          const int y,
2493                            const int start_x,
2494                            const int start_y,
2495                            const int center_x,
2496                            const int center_y,
2497                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2498                                          const uint32_t iQuant,                                          const uint32_t iQuant,
2499                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1783  Line 2527 
2527    
2528          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);
2529    
2530          const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2531          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
2532    
2533          int32_t bPredEq;          int32_t bPredEq;
2534          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2535    
2536          MainSearch8FuncPtr EPZSMainSearchPtr;          MainSearch8FuncPtr MainSearchPtr;
2537    
2538  /* Get maximum range */  /* Get maximum range */
2539          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,
2540                          x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2541    
2542  /* 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 */
2543    
2544          if (!(MotionFlags & PMV_HALFPEL8 ))          if (!(MotionFlags & PMV_HALFPEL8)) {
2545          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2546            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2547            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2548            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2549          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2550            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2551          bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);          //bPredEq = get_pmvdata(pMBs, x >> 1, y >> 1, iWcount, iSubBlock, pmv[0].x, pmv[0].y, psad);
2552            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2553    
2554    
2555  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
# Line 1817  Line 2562 
2562  // Prepare for main loop  // Prepare for main loop
2563    
2564    
2565          if (!(MotionFlags & PMV_HALFPEL8))          if (!(MotionFlags & PMV_HALFPEL8)) {
         {  
2566                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2567                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2568          }          }
# Line 1835  Line 2579 
2579  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2580    
2581    
2582          iMinSAD = sad8( cur,          iMinSAD =
2583                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  sad8(cur,
2584                  iEdgedWidth);                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2585          iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);                                                  iEdgedWidth), iEdgedWidth);
2586            iMinSAD +=
2587                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2588                                             (uint8_t) iFcode, iQuant);
2589    
2590    
2591  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2592          if (iMinSAD < 256/4 )          if (iMinSAD < 256 / 4) {
                 {  
2593                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2594                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2595                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
# Line 1860  Line 2606 
2606          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
2607    
2608  // left neighbour, if allowed  // left neighbour, if allowed
2609          if (psad[1] != MV_MAX_ERROR)          if (psad[1] != MV_MAX_ERROR) {
2610          {                  if (!(MotionFlags & PMV_HALFPEL8)) {
2611                  if (!(MotionFlags & PMV_HALFPEL8 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2612                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2613                  }                  }
2614                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
2615          }          }
   
2616  // top neighbour, if allowed  // top neighbour, if allowed
2617          if (psad[2] != MV_MAX_ERROR)          if (psad[2] != MV_MAX_ERROR) {
2618          {                  if (!(MotionFlags & PMV_HALFPEL8)) {
2619                  if (!(MotionFlags & PMV_HALFPEL8 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2620                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2621                  }                  }
2622                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
2623    
2624  // top right neighbour, if allowed  // top right neighbour, if allowed
2625                  if (psad[3] != MV_MAX_ERROR)                  if (psad[3] != MV_MAX_ERROR) {
2626                  {                          if (!(MotionFlags & PMV_HALFPEL8)) {
2627                          if (!(MotionFlags & PMV_HALFPEL8 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2628                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2629                          }                          }
2630                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);
# Line 1900  Line 2642 
2642     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
2643  */  */
2644    
2645          if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */          if (iMinSAD < 512 / 4) {        /* T_2 == 512/4 hardcoded */
                 {  
2646                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2647                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2648                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
# Line 1917  Line 2658 
2658    
2659  /* default: use best prediction as starting point for one call of EPZS_MainSearch */  /* default: use best prediction as starting point for one call of EPZS_MainSearch */
2660    
2661  /* // there is no EPZS^2 for inter4v at the moment  // there is no EPZS^2 for inter4v at the moment
2662    
2663          if (MotionFlags & PMV_USESQUARES8)          if (MotionFlags & PMV_USESQUARES8)
2664                  EPZSMainSearchPtr = Square8_MainSearch;        MainSearchPtr = Square8_MainSearch;
2665          else          else
 */  
2666    
2667          EPZSMainSearchPtr = Diamond8_MainSearch;          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2668                    MainSearchPtr = AdvDiamond8_MainSearch;
2669            else
2670                    MainSearchPtr = Diamond8_MainSearch;
2671    
2672          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2673                  x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2674                  currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2675                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2676                  iDiamondSize, iFcode, iQuant, 0);                                                    iQuant, 0);
2677    
2678    
2679          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2680                  *currMV = newMV;                  *currMV = newMV;
2681                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2682          }          }
2683    
2684          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2685  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2686    
2687                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2688                  {                          iSAD =
2689                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2690                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2691                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2692                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, 0);
2693    
2694                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2695                                  *currMV = newMV;                                  *currMV = newMV;
2696                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2697                          }                          }
2698                  }                  }
2699    
2700                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2701                  {                          iSAD =
2702                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2703                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2704                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2705                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iQuant, 0);
2706    
2707                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2708                                  *currMV = newMV;                                  *currMV = newMV;
2709                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2710                          }                          }
# Line 1976  Line 2715 
2715    
2716  EPZS8_Terminate_with_Refine:  EPZS8_Terminate_with_Refine:
2717          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2718                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2719                                  x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2720                                  currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2721                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2722    
2723  EPZS8_Terminate_without_Refine:  EPZS8_Terminate_without_Refine:
2724    
2725          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2726          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2727          return iMinSAD;          return iMinSAD;
2728  }  }
2729    
2730    
2731    
2732    int32_t
2733    PMVfastIntSearch16(const uint8_t * const pRef,
2734                                    const uint8_t * const pRefH,
2735                                    const uint8_t * const pRefV,
2736                                    const uint8_t * const pRefHV,
2737                                    const IMAGE * const pCur,
2738                                    const int x,
2739                                    const int y,
2740                            const int start_x,
2741                            const int start_y,
2742                            const int center_x,
2743                            const int center_y,
2744                                    const uint32_t MotionFlags,
2745                                    const uint32_t iQuant,
2746                                    const uint32_t iFcode,
2747                                    const MBParam * const pParam,
2748                                    const MACROBLOCK * const pMBs,
2749                                    const MACROBLOCK * const prevMBs,
2750                                    VECTOR * const currMV,
2751                                    VECTOR * const currPMV)
2752    {
2753            const uint32_t iWcount = pParam->mb_width;
2754            const int32_t iWidth = pParam->width;
2755            const int32_t iHeight = pParam->height;
2756            const int32_t iEdgedWidth = pParam->edged_width;
2757    
2758            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
2759            const VECTOR zeroMV = { 0, 0 };
2760    
2761            int32_t iDiamondSize;
2762    
2763            int32_t min_dx;
2764            int32_t max_dx;
2765            int32_t min_dy;
2766            int32_t max_dy;
2767    
2768            int32_t iFound;
2769    
2770            VECTOR newMV;
2771            VECTOR backupMV;                        /* just for PMVFAST */
2772    
2773            VECTOR pmv[4];
2774            int32_t psad[4];
2775    
2776            MainSearch16FuncPtr MainSearchPtr;
2777    
2778            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2779            MACROBLOCK *const pMB = pMBs + x + y * iWcount;
2780    
2781            int32_t threshA, threshB;
2782            int32_t bPredEq;
2783            int32_t iMinSAD, iSAD;
2784    
2785    
2786    /* Get maximum range */
2787            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2788                              iFcode);
2789    
2790    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2791    
2792            if ((x == 0) && (y == 0)) {
2793                    threshA = 512;
2794                    threshB = 1024;
2795    
2796                    bPredEq = 0;
2797                    psad[0] = psad[1] = psad[2] = psad[3] = 0;
2798                    *currMV = pmv[0] = pmv[1] = pmv[2] = pmv[3] = zeroMV;
2799    
2800            } else {
2801                    threshA = psad[0];
2802                    threshB = threshA + 256;
2803                    if (threshA < 512)
2804                            threshA = 512;
2805                    if (threshA > 1024)
2806                            threshA = 1024;
2807                    if (threshB > 1792)
2808                            threshB = 1792;
2809    
2810                    bPredEq = get_ipmvdata(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2811                    *currMV = pmv[0];                       /* current best := prediction */
2812            }
2813    
2814            iFound = 0;
2815    
2816    /* Step 4: Calculate SAD around the Median prediction.
2817       MinSAD=SAD
2818       If Motion Vector equal to Previous frame motion vector
2819       and MinSAD<PrevFrmSAD goto Step 10.
2820       If SAD<=256 goto Step 10.
2821    */
2822    
2823            if (currMV->x > max_dx) {
2824                    currMV->x = EVEN(max_dx);
2825            }
2826            if (currMV->x < min_dx) {
2827                    currMV->x = EVEN(min_dx);
2828            }
2829            if (currMV->y > max_dy) {
2830                    currMV->y = EVEN(max_dy);
2831            }
2832            if (currMV->y < min_dy) {
2833                    currMV->y = EVEN(min_dy);
2834            }
2835    
2836            iMinSAD =
2837                    sad16(cur,
2838                              get_iref_mv(pRef, x, y, 16, currMV,
2839                                                     iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2840            iMinSAD +=
2841                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2842                                              (uint8_t) iFcode, iQuant);
2843    
2844            if ((iMinSAD < 256) ||
2845                    ((MVequal(*currMV, prevMB->i_mvs[0])) &&
2846                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2847                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
2848                    {
2849                            if (!MVzero(*currMV)) {
2850                                    iMinSAD += MV16_00_BIAS;
2851                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
2852                                    iMinSAD -= MV16_00_BIAS;
2853                            }
2854                    }
2855    
2856                    if (MotionFlags & PMV_EARLYSTOP16)
2857                            goto PMVfastInt16_Terminate_with_Refine;
2858            }
2859    
2860    
2861    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2862       vector of the median.
2863       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2864    */
2865    
2866            if ((bPredEq) && (MVequal(pmv[0], prevMB->i_mvs[0])))
2867                    iFound = 2;
2868    
2869    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2870       Otherwise select large Diamond Search.
2871    */
2872    
2873            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
2874                    iDiamondSize = 2;               // halfpel units!
2875            else
2876                    iDiamondSize = 4;               // halfpel units!
2877    
2878    /*
2879       Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
2880       Also calculate (0,0) but do not subtract offset.
2881       Let MinSAD be the smallest SAD up to this point.
2882       If MV is (0,0) subtract offset.
2883    */
2884    
2885    // (0,0) is often a good choice
2886    
2887            if (!MVzero(pmv[0]))
2888                    CHECK_MV16_ZERO;
2889    
2890    // previous frame MV is always possible
2891    
2892            if (!MVzero(prevMB->i_mvs[0]))
2893                    if (!MVequal(prevMB->i_mvs[0], pmv[0]))
2894                            CHECK_MV16_CANDIDATE(prevMB->i_mvs[0].x, prevMB->i_mvs[0].y);
2895    
2896    // left neighbour, if allowed
2897    
2898            if (!MVzero(pmv[1]))
2899                    if (!MVequal(pmv[1], prevMB->i_mvs[0]))
2900                            if (!MVequal(pmv[1], pmv[0]))
2901                                    CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
2902    
2903    // top neighbour, if allowed
2904            if (!MVzero(pmv[2]))
2905                    if (!MVequal(pmv[2], prevMB->i_mvs[0]))
2906                            if (!MVequal(pmv[2], pmv[0]))
2907                                    if (!MVequal(pmv[2], pmv[1]))
2908                                            CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
2909    
2910    // top right neighbour, if allowed
2911                                            if (!MVzero(pmv[3]))
2912                                                    if (!MVequal(pmv[3], prevMB->i_mvs[0]))
2913                                                            if (!MVequal(pmv[3], pmv[0]))
2914                                                                    if (!MVequal(pmv[3], pmv[1]))
2915                                                                            if (!MVequal(pmv[3], pmv[2]))
2916                                                                                    CHECK_MV16_CANDIDATE(pmv[3].x,
2917                                                                                                                             pmv[3].y);
2918    
2919            if ((MVzero(*currMV)) &&
2920                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2921                    iMinSAD -= MV16_00_BIAS;
2922    
2923    
2924    /* Step 6: If MinSAD <= thresa goto Step 10.
2925       If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
2926    */
2927    
2928            if ((iMinSAD <= threshA) ||
2929                    (MVequal(*currMV, prevMB->i_mvs[0]) &&
2930                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2931    
2932                    if (MotionFlags & PMV_EARLYSTOP16)
2933                            goto PMVfastInt16_Terminate_with_Refine;
2934            }
2935    
2936    
2937    /************ (Diamond Search)  **************/
2938    /*
2939       Step 7: Perform Diamond search, with either the small or large diamond.
2940       If Found=2 only examine one Diamond pattern, and afterwards goto step 10
2941       Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
2942       If center then goto step 10.
2943       Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
2944       Refine by using small diamond and goto step 10.
2945    */
2946    
2947            if (MotionFlags & PMV_USESQUARES16)
2948                    MainSearchPtr = Square16_MainSearch;
2949            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2950                    MainSearchPtr = AdvDiamond16_MainSearch;
2951            else
2952                    MainSearchPtr = Diamond16_MainSearch;
2953    
2954            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2955    
2956    
2957    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2958            iSAD =
2959                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2960                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2961                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2962                                                      iQuant, iFound);
2963    
2964            if (iSAD < iMinSAD) {
2965                    *currMV = newMV;
2966                    iMinSAD = iSAD;
2967            }
2968    
2969            if (MotionFlags & PMV_EXTSEARCH16) {
2970    /* extended: search (up to) two more times: orignal prediction and (0,0) */
2971    
2972                    if (!(MVequal(pmv[0], backupMV))) {
2973                            iSAD =
2974                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2975                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2976                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2977                                                                      iDiamondSize, iFcode, iQuant, iFound);
2978    
2979                            if (iSAD < iMinSAD) {
2980                                    *currMV = newMV;
2981                                    iMinSAD = iSAD;
2982                            }
2983                    }
2984    
2985                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2986                            iSAD =
2987                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2988                                                                      iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2989                                                                      max_dy, iEdgedWidth, iDiamondSize, iFcode,
2990                                                                      iQuant, iFound);
2991    
2992                            if (iSAD < iMinSAD) {
2993                                    *currMV = newMV;
2994                                    iMinSAD = iSAD;
2995                            }