[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 344, Sat Jul 27 23:07:33 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_DIR(backupMV.x - iDiamondSize,
567                                                                                     backupMV.y - iDiamondSize, 5);
568                                    CHECK_MV16_CANDIDATE_DIR(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_DIR(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_DIR(backupMV.x - iDiamondSize,
575                                                                                     backupMV.y + iDiamondSize, 6);
576                                    CHECK_MV16_CANDIDATE_DIR(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_DIR(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_DIR(backupMV.x + iDiamondSize,
584                                                                                     backupMV.y - iDiamondSize, 7);
585                                    CHECK_MV16_CANDIDATE_DIR(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_DIR(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_DIR(backupMV.x - iDiamondSize,
593                                                                                     backupMV.y - iDiamondSize, 5);
594                                    CHECK_MV16_CANDIDATE_DIR(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_DIR(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_DIR(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_DIR(backupMV.x - iDiamondSize,
604                                                                                     backupMV.y - iDiamondSize, 5);
605                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
606                                                                                     backupMV.y + iDiamondSize, 6);
607                                    CHECK_MV16_CANDIDATE_DIR(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_DIR(backupMV.x + iDiamondSize, backupMV.y,
613                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   2);
614                                    CHECK_MV16_CANDIDATE_DIR(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_DIR(backupMV.x - iDiamondSize,
618                                                                                     backupMV.y - iDiamondSize, 5);
619                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
620                                                                                     backupMV.y + iDiamondSize, 6);
621                                    CHECK_MV16_CANDIDATE_DIR(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_DIR(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_DIR(backupMV.x - iDiamondSize,
632                                                                                     backupMV.y - iDiamondSize, 5);
633                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
634                                                                                     backupMV.y - iDiamondSize, 7);
635                                    CHECK_MV16_CANDIDATE_DIR(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_DIR(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_DIR(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_DIR(backupMV.x - iDiamondSize,
645                                                                                     backupMV.y + iDiamondSize, 6);
646                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
647                                                                                     backupMV.y - iDiamondSize, 7);
648                                    CHECK_MV16_CANDIDATE_DIR(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_DIR(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_DIR(backupMV.x + iDiamondSize, backupMV.y,
655                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
656                                    CHECK_MV16_CANDIDATE_DIR(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_DIR(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_DIR(backupMV.x - iDiamondSize,
662                                                                                     backupMV.y - iDiamondSize, 5);
663                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
664                                                                                     backupMV.y + iDiamondSize, 6);
665                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
666                                                                                     backupMV.y - iDiamondSize, 7);
667                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
668                                                                                     backupMV.y + iDiamondSize, 8);
669                                          break;                                          break;
670                          }                          }
671                  }          } else {
672          else                  currMV->x = start_x;
673                  {                  currMV->y = start_y;
                         currMV->x = startx;  
                         currMV->y = starty;  
674                  }                  }
675          return iMinSAD;          return iMinSAD;
676  }  }
677    
678    
679  int32_t Full16_MainSearch(  int32_t
680                                          const uint8_t * const pRef,  Full16_MainSearch(const uint8_t * const pRef,
681                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
682                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
683                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
684                                          const uint8_t * const cur,                                          const uint8_t * const cur,
685                                          const int x, const int y,                                    const int x,
686                                          int32_t startx, int32_t starty,                                    const int y,
687                                          int32_t iMinSAD,                                     const int start_x,
688                                       const int start_y,
689                                       int iMinSAD,
690                                          VECTOR * const currMV,                                          VECTOR * const currMV,
691                                          const VECTOR * const pmv,                                     const int center_x,
692                                          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
693                                          const int32_t min_dy, const int32_t max_dy,                                    const int32_t min_dx,
694                                      const int32_t max_dx,
695                                      const int32_t min_dy,
696                                      const int32_t max_dy,
697                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
698                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
699                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 743  Line 703 
703          int32_t iSAD;          int32_t iSAD;
704          int32_t dx,dy;          int32_t dx,dy;
705          VECTOR backupMV;          VECTOR backupMV;
706          backupMV.x = startx;  
707          backupMV.y = starty;          backupMV.x = start_x;
708            backupMV.y = start_y;
709    
710          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
711                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
# Line 753  Line 714 
714          return iMinSAD;          return iMinSAD;
715  }  }
716    
717  int32_t Full8_MainSearch(  int32_t
718                                          const uint8_t * const pRef,  AdvDiamond16_MainSearch(const uint8_t * const pRef,
719                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
720                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
721                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
722                                          const uint8_t * const cur,                                          const uint8_t * const cur,
723                                          const int x, const int y,                                                  const int x,
724                                          int32_t startx, int32_t starty,                                                  const int y,
725                                          int32_t iMinSAD,                                             int start_x,
726                                               int start_y,
727                                               int iMinSAD,
728                                          VECTOR * const currMV,                                          VECTOR * const currMV,
729                                          const VECTOR * const pmv,                                             const int center_x,
730                                          const int32_t min_dx, const int32_t max_dx,                                             const int center_y,
731                                          const int32_t min_dy, const int32_t max_dy,                                                  const int32_t min_dx,
732                                                    const int32_t max_dx,
733                                                    const int32_t min_dy,
734                                                    const int32_t max_dy,
735                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
736                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
737                                          const int32_t iFcode,                                          const int32_t iFcode,
738                                          const int32_t iQuant,                                          const int32_t iQuant,
739                                          int iFound)                                                  int iDirection)
740  {  {
741    
742          int32_t iSAD;          int32_t iSAD;
         int32_t dx,dy;  
         VECTOR backupMV;  
         backupMV.x = startx;  
         backupMV.y = starty;  
743    
744          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);  
745    
746          return iMinSAD;          if (iDirection) {
747  }                  CHECK_MV16_CANDIDATE(start_x - iDiamondSize, start_y);
748                    CHECK_MV16_CANDIDATE(start_x + iDiamondSize, start_y);
749                    CHECK_MV16_CANDIDATE(start_x, start_y - iDiamondSize);
750                    CHECK_MV16_CANDIDATE(start_x, start_y + iDiamondSize);
751            } else {
752                    int bDirection = 1 + 2 + 4 + 8;
753    
754                    do {
755                            iDirection = 0;
756                            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)
757                                    CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
758    
759                            if (bDirection & 2)
760                                    CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
761    
762  int32_t Halfpel16_Refine(                          if (bDirection & 4)
763          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) */  
764    
765          int32_t iSAD;                          if (bDirection & 8)
766          VECTOR backupMV = *currMV;                                  CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
767    
768          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);  
769    
770          return iMinSAD;                          if (iDirection)         //checking if anything found
771                            {
772                                    bDirection = iDirection;
773                                    iDirection = 0;
774                                    start_x = currMV->x;
775                                    start_y = currMV->y;
776                                    if (bDirection & 3)     //our candidate is left or right
777                                    {
778                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
779                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
780                                    } else                  // what remains here is up or down
781                                    {
782                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
783                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
784  }  }
785    
786  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)                                  if (iDirection) {
787                                            bDirection += iDirection;
788                                            start_x = currMV->x;
789                                            start_y = currMV->y;
790                                    }
791                            } else                          //about to quit, eh? not so fast....
792                            {
793                                    switch (bDirection) {
794                                    case 2:
795                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
796                                                                                             start_y - iDiamondSize, 2 + 4);
797                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
798                                                                                             start_y + iDiamondSize, 2 + 8);
799                                            break;
800                                    case 1:
801    
802                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
803                                                                                             start_y - iDiamondSize, 1 + 4);
804                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
805                                                                                             start_y + iDiamondSize, 1 + 8);
806                                            break;
807                                    case 2 + 4:
808                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
809                                                                                             start_y - iDiamondSize, 1 + 4);
810                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
811                                                                                             start_y - iDiamondSize, 2 + 4);
812                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
813                                                                                             start_y + iDiamondSize, 2 + 8);
814                                            break;
815                                    case 4:
816                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
817                                                                                             start_y - iDiamondSize, 2 + 4);
818                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
819                                                                                             start_y - iDiamondSize, 1 + 4);
820                                            break;
821                                    case 8:
822                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
823                                                                                             start_y + iDiamondSize, 2 + 8);
824                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
825                                                                                             start_y + iDiamondSize, 1 + 8);
826                                            break;
827                                    case 1 + 4:
828                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
829                                                                                             start_y + iDiamondSize, 1 + 8);
830                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
831                                                                                             start_y - iDiamondSize, 1 + 4);
832                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
833                                                                                             start_y - iDiamondSize, 2 + 4);
834                                            break;
835                                    case 2 + 8:
836                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
837                                                                                             start_y - iDiamondSize, 1 + 4);
838                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
839                                                                                             start_y + iDiamondSize, 1 + 8);
840                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
841                                                                                             start_y + iDiamondSize, 2 + 8);
842                                            break;
843                                    case 1 + 8:
844                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
845                                                                                             start_y - iDiamondSize, 2 + 4);
846                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
847                                                                                             start_y + iDiamondSize, 2 + 8);
848                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
849                                                                                             start_y + iDiamondSize, 1 + 8);
850                                            break;
851                                    default:                //1+2+4+8 == we didn't find anything at all
852                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
853                                                                                             start_y - iDiamondSize, 1 + 4);
854                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
855                                                                                             start_y + iDiamondSize, 1 + 8);
856                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
857                                                                                             start_y - iDiamondSize, 2 + 4);
858                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
859                                                                                             start_y + iDiamondSize, 2 + 8);
860                                            break;
861                                    }
862                                    if (!iDirection)
863                                            break;          //ok, the end. really
864                                    else {
865                                            bDirection = iDirection;
866                                            start_x = currMV->x;
867                                            start_y = currMV->y;
868                                    }
869                            }
870                    }
871                    while (1);                              //forever
872            }
873            return iMinSAD;
874    }
875    
876  int32_t PMVfastSearch16(  
877                                          const uint8_t * const pRef,  #define CHECK_MV16_F_INTERPOL(X,Y,BX,BY) { \
878      if ( ((X) <= max_dx) && ((X) >= min_dx) \
879        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
880      { \
881        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
882        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
883        if (iSAD < iMinSAD) \
884        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
885    }
886    
887    #define CHECK_MV16_F_INTERPOL_DIR(X,Y,BX,BY,D) { \
888      if ( ((X) <= max_dx) && ((X) >= min_dx) \
889        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
890      { \
891        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
892        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
893        if (iSAD < iMinSAD) \
894        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
895    }
896    
897    #define CHECK_MV16_F_INTERPOL_FOUND(X,Y,BX,BY,D) { \
898      if ( ((X) <= max_dx) && ((X) >= min_dx) \
899        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
900      { \
901        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
902        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
903        if (iSAD < iMinSAD) \
904        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
905    }
906    
907    
908    #define CHECK_MV16_B_INTERPOL(FX,FY,X,Y) { \
909      if ( ((X) <= max_dx) && ((X) >= min_dx) \
910        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
911      { \
912        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
913        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
914        if (iSAD < iMinSAD) \
915        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
916    }
917    
918    
919    #define CHECK_MV16_B_INTERPOL_DIR(FX,FY,X,Y,D) { \
920      if ( ((X) <= max_dx) && ((X) >= min_dx) \
921        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
922      { \
923        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
924        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
925        if (iSAD < iMinSAD) \
926        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
927    }
928    
929    
930    #define CHECK_MV16_B_INTERPOL_FOUND(FX,FY,X,Y,D) { \
931      if ( ((X) <= max_dx) && ((X) >= min_dx) \
932        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
933      { \
934        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
935        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
936        if (iSAD < iMinSAD) \
937        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
938    }
939    
940    
941    #if (0==1)
942    int32_t
943    Diamond16_InterpolMainSearch(
944                                            const uint8_t * const f_pRef,
945                                             const uint8_t * const f_pRefH,
946                                             const uint8_t * const f_pRefV,
947                                             const uint8_t * const f_pRefHV,
948                                             const uint8_t * const cur,
949    
950                                            const uint8_t * const b_pRef,
951                                             const uint8_t * const b_pRefH,
952                                             const uint8_t * const b_pRefV,
953                                             const uint8_t * const b_pRefHV,
954    
955                                             const int x,
956                                             const int y,
957    
958                                       const int f_start_x,
959                                       const int f_start_y,
960                                       const int b_start_x,
961                                       const int b_start_y,
962    
963                                       int iMinSAD,
964                                       VECTOR * const f_currMV,
965                                       VECTOR * const b_currMV,
966    
967                                       const int f_center_x,
968                                       const int f_center_y,
969                                       const int b_center_x,
970                                       const int b_center_y,
971    
972                                             const int32_t min_dx,
973                                             const int32_t max_dx,
974                                             const int32_t min_dy,
975                                             const int32_t max_dy,
976                                             const int32_t iEdgedWidth,
977                                             const int32_t iDiamondSize,
978    
979                                             const int32_t f_iFcode,
980                                             const int32_t b_iFcode,
981    
982                                             const int32_t iQuant,
983                                             int iFound)
984    {
985    /* Do a diamond search around given starting point, return SAD of best */
986    
987            int32_t f_iDirection = 0;
988            int32_t b_iDirection = 0;
989            int32_t iSAD;
990    
991            VECTOR f_backupMV;
992            VECTOR b_backupMV;
993    
994            f_backupMV.x = start_x;
995            f_backupMV.y = start_y;
996            b_backupMV.x = start_x;
997            b_backupMV.y = start_y;
998    
999    /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1000    
1001            CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1002            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1003            CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1004            CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1005    
1006            if (iDirection)
1007                    while (!iFound) {
1008                            iFound = 1;
1009                            backupMV = *currMV;
1010    
1011                            if (iDirection != 2)
1012                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1013                                                                                       backupMV.y, 1);
1014                            if (iDirection != 1)
1015                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1016                                                                                       backupMV.y, 2);
1017                            if (iDirection != 4)
1018                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
1019                                                                                       backupMV.y - iDiamondSize, 3);
1020                            if (iDirection != 3)
1021                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
1022                                                                                       backupMV.y + iDiamondSize, 4);
1023            } else {
1024                    currMV->x = start_x;
1025                    currMV->y = start_y;
1026            }
1027            return iMinSAD;
1028    }
1029    #endif
1030    
1031    
1032    int32_t
1033    AdvDiamond8_MainSearch(const uint8_t * const pRef,
1034                                               const uint8_t * const pRefH,
1035                                               const uint8_t * const pRefV,
1036                                               const uint8_t * const pRefHV,
1037                                               const uint8_t * const cur,
1038                                               const int x,
1039                                               const int y,
1040                                               int start_x,
1041                                               int start_y,
1042                                               int iMinSAD,
1043                                               VECTOR * const currMV,
1044                                               const int center_x,
1045                                               const int center_y,
1046                                               const int32_t min_dx,
1047                                               const int32_t max_dx,
1048                                               const int32_t min_dy,
1049                                               const int32_t max_dy,
1050                                               const int32_t iEdgedWidth,
1051                                               const int32_t iDiamondSize,
1052                                               const int32_t iFcode,
1053                                               const int32_t iQuant,
1054                                               int iDirection)
1055    {
1056    
1057            int32_t iSAD;
1058    
1059    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
1060    
1061            if (iDirection) {
1062                    CHECK_MV8_CANDIDATE(start_x - iDiamondSize, start_y);
1063                    CHECK_MV8_CANDIDATE(start_x + iDiamondSize, start_y);
1064                    CHECK_MV8_CANDIDATE(start_x, start_y - iDiamondSize);
1065                    CHECK_MV8_CANDIDATE(start_x, start_y + iDiamondSize);
1066            } else {
1067                    int bDirection = 1 + 2 + 4 + 8;
1068    
1069                    do {
1070                            iDirection = 0;
1071                            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)
1072                                    CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1073    
1074                            if (bDirection & 2)
1075                                    CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1076    
1077                            if (bDirection & 4)
1078                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1079    
1080                            if (bDirection & 8)
1081                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1082    
1083                            /* now we're doing diagonal checks near our candidate */
1084    
1085                            if (iDirection)         //checking if anything found
1086                            {
1087                                    bDirection = iDirection;
1088                                    iDirection = 0;
1089                                    start_x = currMV->x;
1090                                    start_y = currMV->y;
1091                                    if (bDirection & 3)     //our candidate is left or right
1092                                    {
1093                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1094                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1095                                    } else                  // what remains here is up or down
1096                                    {
1097                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1098                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1099                                    }
1100    
1101                                    if (iDirection) {
1102                                            bDirection += iDirection;
1103                                            start_x = currMV->x;
1104                                            start_y = currMV->y;
1105                                    }
1106                            } else                          //about to quit, eh? not so fast....
1107                            {
1108                                    switch (bDirection) {
1109                                    case 2:
1110                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1111                                                                                            start_y - iDiamondSize, 2 + 4);
1112                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1113                                                                                            start_y + iDiamondSize, 2 + 8);
1114                                            break;
1115                                    case 1:
1116                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1117                                                                                            start_y - iDiamondSize, 1 + 4);
1118                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1119                                                                                            start_y + iDiamondSize, 1 + 8);
1120                                            break;
1121                                    case 2 + 4:
1122                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1123                                                                                            start_y - iDiamondSize, 1 + 4);
1124                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1125                                                                                            start_y - iDiamondSize, 2 + 4);
1126                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1127                                                                                            start_y + iDiamondSize, 2 + 8);
1128                                            break;
1129                                    case 4:
1130                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1131                                                                                            start_y - iDiamondSize, 2 + 4);
1132                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1133                                                                                            start_y - iDiamondSize, 1 + 4);
1134                                            break;
1135                                    case 8:
1136                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1137                                                                                            start_y + iDiamondSize, 2 + 8);
1138                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1139                                                                                            start_y + iDiamondSize, 1 + 8);
1140                                            break;
1141                                    case 1 + 4:
1142                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1143                                                                                            start_y + iDiamondSize, 1 + 8);
1144                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1145                                                                                            start_y - iDiamondSize, 1 + 4);
1146                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1147                                                                                            start_y - iDiamondSize, 2 + 4);
1148                                            break;
1149                                    case 2 + 8:
1150                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1151                                                                                            start_y - iDiamondSize, 1 + 4);
1152                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1153                                                                                            start_y + iDiamondSize, 1 + 8);
1154                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1155                                                                                            start_y + iDiamondSize, 2 + 8);
1156                                            break;
1157                                    case 1 + 8:
1158                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1159                                                                                            start_y - iDiamondSize, 2 + 4);
1160                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1161                                                                                            start_y + iDiamondSize, 2 + 8);
1162                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1163                                                                                            start_y + iDiamondSize, 1 + 8);
1164                                            break;
1165                                    default:                //1+2+4+8 == we didn't find anything at all
1166                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1167                                                                                            start_y - iDiamondSize, 1 + 4);
1168                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1169                                                                                            start_y + iDiamondSize, 1 + 8);
1170                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1171                                                                                            start_y - iDiamondSize, 2 + 4);
1172                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1173                                                                                            start_y + iDiamondSize, 2 + 8);
1174                                            break;
1175                                    }
1176                                    if (!(iDirection))
1177                                            break;          //ok, the end. really
1178                                    else {
1179                                            bDirection = iDirection;
1180                                            start_x = currMV->x;
1181                                            start_y = currMV->y;
1182                                    }
1183                            }
1184                    }
1185                    while (1);                              //forever
1186            }
1187            return iMinSAD;
1188    }
1189    
1190    
1191    int32_t
1192    Full8_MainSearch(const uint8_t * const pRef,
1193                                     const uint8_t * const pRefH,
1194                                     const uint8_t * const pRefV,
1195                                     const uint8_t * const pRefHV,
1196                                     const uint8_t * const cur,
1197                                     const int x,
1198                                     const int y,
1199                               const int start_x,
1200                               const int start_y,
1201                               int iMinSAD,
1202                               VECTOR * const currMV,
1203                               const int center_x,
1204                               const int center_y,
1205                                     const int32_t min_dx,
1206                                     const int32_t max_dx,
1207                                     const int32_t min_dy,
1208                                     const int32_t max_dy,
1209                                     const int32_t iEdgedWidth,
1210                                     const int32_t iDiamondSize,
1211                                     const int32_t iFcode,
1212                                     const int32_t iQuant,
1213                                     int iFound)
1214    {
1215            int32_t iSAD;
1216            int32_t dx, dy;
1217            VECTOR backupMV;
1218    
1219            backupMV.x = start_x;
1220            backupMV.y = start_y;
1221    
1222            for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
1223                    for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
1224                            NOCHECK_MV8_CANDIDATE(dx, dy);
1225    
1226            return iMinSAD;
1227    }
1228    
1229    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1230    
1231    int32_t
1232    Halfpel16_Refine(const uint8_t * const pRef,
1233                                     const uint8_t * const pRefH,
1234                                     const uint8_t * const pRefV,
1235                                     const uint8_t * const pRefHV,
1236                                     const uint8_t * const cur,
1237                                     const int x,
1238                                     const int y,
1239                                     VECTOR * const currMV,
1240                                     int32_t iMinSAD,
1241                               const int center_x,
1242                               const int center_y,
1243                                     const int32_t min_dx,
1244                                     const int32_t max_dx,
1245                                     const int32_t min_dy,
1246                                     const int32_t max_dy,
1247                                     const int32_t iFcode,
1248                                     const int32_t iQuant,
1249                                     const int32_t iEdgedWidth)
1250    {
1251    /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
1252    
1253            int32_t iSAD;
1254            VECTOR backupMV = *currMV;
1255    
1256            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y - 1);
1257            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y - 1);
1258            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y - 1);
1259            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y);
1260            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y);
1261            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y + 1);
1262            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y + 1);
1263            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y + 1);
1264    
1265            return iMinSAD;
1266    }
1267    
1268    #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1269    
1270    
1271    
1272    int32_t
1273    PMVfastSearch16(const uint8_t * const pRef,
1274                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1275                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1276                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1277                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1278                                          const int x, const int y,                                  const int x,
1279                                    const int y,
1280                                    const int start_x,
1281                                    const int start_y,
1282                                    const int center_x,
1283                                    const int center_y,
1284                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1285                                          const uint32_t iQuant,                                          const uint32_t iQuant,
1286                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 861  Line 1312 
1312          VECTOR pmv[4];          VECTOR pmv[4];
1313          int32_t psad[4];          int32_t psad[4];
1314    
1315          const MACROBLOCK * const pMB = pMBs + x + y * iWcount;          MainSearch16FuncPtr MainSearchPtr;
1316    
1317          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1318    
1319          static int32_t threshA,threshB;          int32_t threshA, threshB;
1320          int32_t bPredEq;          int32_t bPredEq;
1321          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1322    
1323  /* Get maximum range */  /* Get maximum range */
1324          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,
1325                    x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
1326    
1327  /* 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 */
1328    
1329          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
1330          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1331          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1332          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1333          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1334          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
   
1335    
1336          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1337            //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1338            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1339    
1340          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1341                  threshA =  512;                  threshA =  512;
1342                  threshB = 1024;                  threshB = 1024;
1343            } else {
         }  
         else  
         {  
1344                  threshA = psad[0];                  threshA = psad[0];
1345                  threshB = threshA+256;                  threshB = threshA+256;
1346                  if (threshA< 512) threshA =  512;                  if (threshA < 512)
1347                  if (threshA>1024) threshA = 1024;                          threshA = 512;
1348                  if (threshB>1792) threshB = 1792;                  if (threshA > 1024)
1349                            threshA = 1024;
1350                    if (threshB > 1792)
1351                            threshB = 1792;
1352          }          }
1353    
1354          iFound=0;          iFound=0;
1355    
 /* 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;  
   
1356  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1357     MinSAD=SAD     MinSAD=SAD
1358     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 928  Line 1360 
1360     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
1361  */  */
1362    
1363            currMV->x = start_x;
1364            currMV->y = start_y;
1365    
1366  // 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! */  
1367                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1368                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
1369          }          }
1370    
1371          if (currMV->x > max_dx)          if (currMV->x > max_dx) {
         {  
1372                  currMV->x=max_dx;                  currMV->x=max_dx;
1373          }          }
1374          if (currMV->x < min_dx)          if (currMV->x < min_dx) {
         {  
1375                  currMV->x=min_dx;                  currMV->x=min_dx;
1376          }          }
1377          if (currMV->y > max_dy)          if (currMV->y > max_dy) {
         {  
1378                  currMV->y=max_dy;                  currMV->y=max_dy;
1379          }          }
1380          if (currMV->y < min_dy)          if (currMV->y < min_dy) {
         {  
1381                  currMV->y=min_dy;                  currMV->y=min_dy;
1382          }          }
1383    
1384          iMinSAD = sad16( cur,          iMinSAD =
1385                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1386                           iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1387          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1388            iMinSAD +=
1389          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
1390          {                                            (uint8_t) iFcode, iQuant);
1391    
1392            if ((iMinSAD < 256) ||
1393                    ((MVequal(*currMV, prevMB->mvs[0])) &&
1394                     ((int32_t) iMinSAD < prevMB->sad16))) {
1395                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
1396                    {
1397                            if (!MVzero(*currMV)) {
1398                                    iMinSAD += MV16_00_BIAS;
1399                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
1400                                    iMinSAD -= MV16_00_BIAS;
1401                            }
1402                    }
1403    
1404                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1405                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
# Line 969  Line 1407 
1407                          goto PMVfast16_Terminate_with_Refine;                          goto PMVfast16_Terminate_with_Refine;
1408          }          }
1409    
1410    
1411    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1412       vector of the median.
1413       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1414    */
1415    
1416            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[0])))
1417                    iFound = 2;
1418    
1419    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1420       Otherwise select large Diamond Search.
1421    */
1422    
1423            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
1424                    iDiamondSize = 1;               // halfpel!
1425            else
1426                    iDiamondSize = 2;               // halfpel!
1427    
1428            if (!(MotionFlags & PMV_HALFPELDIAMOND16))
1429                    iDiamondSize *= 2;
1430    
1431  /*  /*
1432     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.
1433     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
# Line 978  Line 1437 
1437    
1438  // (0,0) is always possible  // (0,0) is always possible
1439    
1440            if (!MVzero(pmv[0]))
1441          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1442    
1443  // previous frame MV is always possible  // previous frame MV is always possible
1444    
1445            if (!MVzero(prevMB->mvs[0]))
1446                    if (!MVequal(prevMB->mvs[0], pmv[0]))
1447          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1448    
1449  // left neighbour, if allowed  // left neighbour, if allowed
1450          if (x != 0)  
1451          {          if (!MVzero(pmv[1]))
1452                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!MVequal(pmv[1], prevMB->mvs[0]))
1453                  {       pmv[1].x = EVEN(pmv[1].x);                          if (!MVequal(pmv[1], pmv[0])) {
1454                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1455                                            pmv[1].x = EVEN(pmv[1].x);
1456                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1457                  }                  }
1458    
1459                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1460          }          }
   
1461  // top neighbour, if allowed  // top neighbour, if allowed
1462          if (y != 0)          if (!MVzero(pmv[2]))
1463          {                  if (!MVequal(pmv[2], prevMB->mvs[0]))
1464                  if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!MVequal(pmv[2], pmv[0]))
1465                  {       pmv[2].x = EVEN(pmv[2].x);                                  if (!MVequal(pmv[2], pmv[1])) {
1466                                            if (!(MotionFlags & PMV_HALFPEL16)) {
1467                                                    pmv[2].x = EVEN(pmv[2].x);
1468                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
1469                  }                  }
1470                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1471    
1472  // top right neighbour, if allowed  // top right neighbour, if allowed
1473                  if ((uint32_t)x != (iWcount-1))                                          if (!MVzero(pmv[3]))
1474                  {                                                  if (!MVequal(pmv[3], prevMB->mvs[0]))
1475                          if (!(MotionFlags & PMV_HALFPEL16 ))                                                          if (!MVequal(pmv[3], pmv[0]))
1476                          {       pmv[3].x = EVEN(pmv[3].x);                                                                  if (!MVequal(pmv[3], pmv[1]))
1477                                                                            if (!MVequal(pmv[3], pmv[2])) {
1478                                                                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1479                                                                                            pmv[3].x = EVEN(pmv[3].x);
1480                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1481                          }                          }
1482                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                  CHECK_MV16_CANDIDATE(pmv[3].x,
1483                                                                                                                             pmv[3].y);
1484                  }                  }
1485          }          }
1486    
1487          if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96)*/ )          if ((MVzero(*currMV)) &&
1488                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1489                  iMinSAD -= MV16_00_BIAS;                  iMinSAD -= MV16_00_BIAS;
1490    
1491    
# Line 1021  Line 1493 
1493     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.
1494  */  */
1495    
1496          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ((iMinSAD <= threshA) ||
1497          {                  (MVequal(*currMV, prevMB->mvs[0]) &&
1498                     ((int32_t) iMinSAD < prevMB->sad16))) {
1499                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1500                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
1501                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1040  Line 1513 
1513     Refine by using small diamond and goto step 10.     Refine by using small diamond and goto step 10.
1514  */  */
1515    
1516            if (MotionFlags & PMV_USESQUARES16)
1517                    MainSearchPtr = Square16_MainSearch;
1518            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
1519                    MainSearchPtr = AdvDiamond16_MainSearch;
1520            else
1521                    MainSearchPtr = Diamond16_MainSearch;
1522    
1523          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1524    
1525    
1526  /* 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 */
1527          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1528                                            x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1529                                            currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->x, currMV->y, iMinSAD, &newMV, center_x, center_y,
1530                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dx, max_dx,
1531                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1532                                                      iQuant, iFound);
1533    
1534          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1535                  *currMV = newMV;                  *currMV = newMV;
1536                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1537          }          }
1538    
1539          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
1540  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1541    
1542                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1543                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1544                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1545                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    center_x, center_y, iMinSAD, &newMV, center_x, center_y,
1546                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1547                                                                      iDiamondSize, iFcode, iQuant, iFound);
1548    
1549                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1550                          *currMV = newMV;                          *currMV = newMV;
1551                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1552                  }                  }
1553                  }                  }
1554    
1555                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1556                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1557                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1558                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y,
1559                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy,
1560                                                                      iEdgedWidth, iDiamondSize, iFcode,
1561                                                                      iQuant, iFound);
1562    
1563                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1564                          *currMV = newMV;                          *currMV = newMV;
1565                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1566                  }                  }
# Line 1091  Line 1573 
1573    
1574  PMVfast16_Terminate_with_Refine:  PMVfast16_Terminate_with_Refine:
1575          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1576                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1577                                    x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1578                                    currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1579                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1580    
1581  PMVfast16_Terminate_without_Refine:  PMVfast16_Terminate_without_Refine:
1582          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
1583          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
1584          return iMinSAD;          return iMinSAD;
1585  }  }
1586    
# Line 1107  Line 1589 
1589    
1590    
1591    
1592  int32_t Diamond8_MainSearch(  int32_t
1593          const uint8_t * const pRef,  Diamond8_MainSearch(const uint8_t * const pRef,
1594          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1595          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1596          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1597          const uint8_t * const cur,          const uint8_t * const cur,
1598          const int x, const int y,                                          const int x,
1599          int32_t startx, int32_t starty,                                          const int y,
1600                                            int32_t start_x,
1601                                            int32_t start_y,
1602          int32_t iMinSAD,          int32_t iMinSAD,
1603          VECTOR * const currMV,          VECTOR * const currMV,
1604          const VECTOR * const pmv,                                     const int center_x,
1605          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
1606          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
1607                                            const int32_t max_dx,
1608                                            const int32_t min_dy,
1609                                            const int32_t max_dy,
1610          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
1611          const int32_t iDiamondSize,          const int32_t iDiamondSize,
1612          const int32_t iFcode,          const int32_t iFcode,
# Line 1129  Line 1616 
1616  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
1617    
1618          int32_t iDirection=0;          int32_t iDirection=0;
1619            int32_t iDirectionBackup;
1620          int32_t iSAD;          int32_t iSAD;
1621          VECTOR backupMV;          VECTOR backupMV;
1622          backupMV.x = startx;  
1623          backupMV.y = starty;          backupMV.x = start_x;
1624            backupMV.y = start_y;
1625    
1626  /* 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 */
1627    
# Line 1141  Line 1630 
1630          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
1631          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1632    
1633          if (iDirection)          if (iDirection) {
1634                  while (!iFound)                  while (!iFound) {
                 {  
1635                          iFound = 1;                          iFound = 1;
1636                          backupMV=*currMV;       // since iDirection!=0, this is well defined!                          backupMV=*currMV;       // since iDirection!=0, this is well defined!
1637                            iDirectionBackup = iDirection;
1638    
1639                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
1640                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1641                          if ( iDirection != 1)                                                                                    backupMV.y, 1);
1642                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
1643                          if ( iDirection != 4)                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1644                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                    backupMV.y, 2);
1645                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
1646                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1647                                                                                      backupMV.y - iDiamondSize, 3);
1648                            if (iDirectionBackup != 3)
1649                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1650                                                                                      backupMV.y + iDiamondSize, 4);
1651                  }                  }
1652          else          } else {
1653          {                  currMV->x = start_x;
1654                  currMV->x = startx;                  currMV->y = start_y;
                 currMV->y = starty;  
1655          }          }
1656          return iMinSAD;          return iMinSAD;
1657  }  }
1658    
1659  int32_t Halfpel8_Refine(  int32_t
1660          const uint8_t * const pRef,  Halfpel8_Refine_c(const uint8_t * const pRef,
1661          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1662          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1663          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1664          const uint8_t * const cur,          const uint8_t * const cur,
1665          const int x, const int y,                                  const int x,
1666                                    const int y,
1667          VECTOR * const currMV,          VECTOR * const currMV,
1668          int32_t iMinSAD,          int32_t iMinSAD,
1669          const VECTOR * const pmv,                             const int center_x,
1670          const int32_t min_dx, const int32_t max_dx,                             const int center_y,
1671          const int32_t min_dy, const int32_t max_dy,                                  const int32_t min_dx,
1672                                    const int32_t max_dx,
1673                                    const int32_t min_dy,
1674                                    const int32_t max_dy,
1675          const int32_t iFcode,          const int32_t iFcode,
1676          const int32_t iQuant,          const int32_t iQuant,
1677          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 1200  Line 1696 
1696    
1697  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1698    
1699  int32_t PMVfastSearch8(  int32_t
1700                                          const uint8_t * const pRef,  PMVfastSearch8(const uint8_t * const pRef,
1701                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1702                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1703                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1704                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1705                                          const int x, const int y,                             const int x,
1706                                          const int start_x, const int start_y,                             const int y,
1707                               const int start_x,
1708                               const int start_y,
1709                                    const int center_x,
1710                                    const int center_y,
1711                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1712                                          const uint32_t iQuant,                                          const uint32_t iQuant,
1713                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1235  Line 1735 
1735          int32_t psad[4];          int32_t psad[4];
1736          VECTOR newMV;          VECTOR newMV;
1737          VECTOR backupMV;          VECTOR backupMV;
1738            VECTOR startMV;
1739    
1740          const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1741          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1742    
1743          static int32_t threshA,threshB;           int32_t threshA, threshB;
1744          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
1745          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1746    
1747          int32_t iSubBlock = ((y&1)<<1) + (x&1);          int32_t iSubBlock = (y & 1) + (y & 1) + (x & 1);
1748    
1749            MainSearch8FuncPtr MainSearchPtr;
1750    
1751            /* Init variables */
1752            startMV.x = start_x;
1753            startMV.y = start_y;
1754    
1755  /* Get maximum range */  /* Get maximum range */
1756          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,
1757                    x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
1758    
1759          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
1760          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1761          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1762          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1763          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1764          }               /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          }
   
1765    
1766          bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
1767            //bPredEq = get_pmvdata(pMBs, (x >> 1), (y >> 1), iWcount, iSubBlock, pmv, psad);
1768            bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
1769    
1770          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1771                  threshA =  512/4;                  threshA =  512/4;
1772                  threshB = 1024/4;                  threshB = 1024/4;
1773    
1774          }          } else {
1775          else                  threshA = psad[0] / 4;  /* good estimate? */
         {  
                 threshA = psad[0]/4;                    /* good estimate */  
1776                  threshB = threshA+256/4;                  threshB = threshA+256/4;
1777                  if (threshA< 512/4) threshA =  512/4;                  if (threshA < 512 / 4)
1778                  if (threshA>1024/4) threshA = 1024/4;                          threshA = 512 / 4;
1779                  if (threshB>1792/4) threshB = 1792/4;                  if (threshA > 1024 / 4)
1780                            threshA = 1024 / 4;
1781                    if (threshB > 1792 / 4)
1782                            threshB = 1792 / 4;
1783          }          }
1784    
1785          iFound=0;          iFound=0;
1786    
 /* 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;  
   
1787  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1788     MinSAD=SAD     MinSAD=SAD
1789     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 1306  Line 1794 
1794    
1795  // Prepare for main loop  // Prepare for main loop
1796    
1797          currMV->x=start_x;              /* start with mv16 */  //  if (MotionFlags & PMV_USESQUARES8)
1798          currMV->y=start_y;  //      MainSearchPtr = Square8_MainSearch;
1799    //  else
1800    
1801          iMinSAD = sad8( cur,          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
1802                          get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  MainSearchPtr = AdvDiamond8_MainSearch;
1803                          iEdgedWidth);          else
1804          iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode, iQuant);                  MainSearchPtr = Diamond8_MainSearch;
1805    
1806          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock])) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )  
1807          {          *currMV = startMV;
1808    
1809            iMinSAD =
1810                    sad8(cur,
1811                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
1812                                                    iEdgedWidth), iEdgedWidth);
1813            iMinSAD +=
1814                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
1815                                             (uint8_t) iFcode, iQuant);
1816    
1817            if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))
1818                                                                    && ((int32_t) iMinSAD <
1819                                                                            prevMB->sad8[iSubBlock]))) {
1820                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1821                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
1822                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
1823                          goto PMVfast8_Terminate_with_Refine;                          goto PMVfast8_Terminate_with_Refine;
1824          }          }
1825    
1826    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1827       vector of the median.
1828       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1829    */
1830    
1831            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[iSubBlock])))
1832                    iFound = 2;
1833    
1834    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1835       Otherwise select large Diamond Search.
1836    */
1837    
1838            if ((!MVzero(pmv[0])) || (threshB < 1536 / 4) || (bPredEq))
1839                    iDiamondSize = 1;               // 1 halfpel!
1840            else
1841                    iDiamondSize = 2;               // 2 halfpel = 1 full pixel!
1842    
1843            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
1844                    iDiamondSize *= 2;
1845    
1846    
1847  /*  /*
1848     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 1851 
1851     If MV is (0,0) subtract offset.     If MV is (0,0) subtract offset.
1852  */  */
1853    
1854  // 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);  
1855    
1856  // (0,0) is always possible          if (!MVequal(pmv[0], startMV))
1857                    CHECK_MV8_CANDIDATE(center_x, center_y);
1858    
1859    // (0,0) if needed
1860            if (!MVzero(pmv[0]))
1861                    if (!MVzero(startMV))
1862          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
1863    
1864  // previous frame MV is always possible  // previous frame MV if needed
1865          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);          if (!MVzero(prevMB->mvs[iSubBlock]))
1866                    if (!MVequal(prevMB->mvs[iSubBlock], startMV))
1867                            if (!MVequal(prevMB->mvs[iSubBlock], pmv[0]))
1868                                    CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,
1869                                                                            prevMB->mvs[iSubBlock].y);
1870    
1871            if ((iMinSAD <= threshA) ||
1872                    (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
1873                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
1874                    if (MotionFlags & PMV_QUICKSTOP16)
1875                            goto PMVfast8_Terminate_without_Refine;
1876                    if (MotionFlags & PMV_EARLYSTOP16)
1877                            goto PMVfast8_Terminate_with_Refine;
1878            }
1879    
1880  // left neighbour, if allowed  // left neighbour, if allowed and needed
1881          if (psad[1] != MV_MAX_ERROR)          if (!MVzero(pmv[1]))
1882          {                  if (!MVequal(pmv[1], startMV))
1883                  if (!(MotionFlags & PMV_HALFPEL8 ))                          if (!MVequal(pmv[1], prevMB->mvs[iSubBlock]))
1884                  {       pmv[1].x = EVEN(pmv[1].x);                                  if (!MVequal(pmv[1], pmv[0])) {
1885                                            if (!(MotionFlags & PMV_HALFPEL8)) {
1886                                                    pmv[1].x = EVEN(pmv[1].x);
1887                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1888                  }                  }
1889                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1890          }          }
1891    // top neighbour, if allowed and needed
1892  // top neighbour, if allowed          if (!MVzero(pmv[2]))
1893          if (psad[2] != MV_MAX_ERROR)                  if (!MVequal(pmv[2], startMV))
1894          {                          if (!MVequal(pmv[2], prevMB->mvs[iSubBlock]))
1895                  if (!(MotionFlags & PMV_HALFPEL8 ))                                  if (!MVequal(pmv[2], pmv[0]))
1896                  {       pmv[2].x = EVEN(pmv[2].x);                                          if (!MVequal(pmv[2], pmv[1])) {
1897                                                    if (!(MotionFlags & PMV_HALFPEL8)) {
1898                                                            pmv[2].x = EVEN(pmv[2].x);
1899                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
1900                  }                  }
1901                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1902    
1903  // top right neighbour, if allowed  // top right neighbour, if allowed and needed
1904                  if (psad[3] != MV_MAX_ERROR)                                                  if (!MVzero(pmv[3]))
1905                  {                                                          if (!MVequal(pmv[3], startMV))
1906                          if (!(MotionFlags & PMV_HALFPEL8 ))                                                                  if (!MVequal(pmv[3], prevMB->mvs[iSubBlock]))
1907                          {       pmv[3].x = EVEN(pmv[3].x);                                                                          if (!MVequal(pmv[3], pmv[0]))
1908                                                                                    if (!MVequal(pmv[3], pmv[1]))
1909                                                                                            if (!MVequal(pmv[3], pmv[2])) {
1910                                                                                                    if (!
1911                                                                                                            (MotionFlags &
1912                                                                                                             PMV_HALFPEL8)) {
1913                                                                                                            pmv[3].x = EVEN(pmv[3].x);
1914                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1915                          }                          }
1916                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                                  CHECK_MV8_CANDIDATE(pmv[3].x,
1917                                                                                                                                            pmv[3].y);
1918                  }                  }
1919          }          }
1920    
1921          if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )          if ((MVzero(*currMV)) &&
1922                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1923                  iMinSAD -= MV8_00_BIAS;                  iMinSAD -= MV8_00_BIAS;
1924    
1925    
# Line 1377  Line 1927 
1927     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.
1928  */  */
1929    
1930          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
1931          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
1932                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
1933                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1934                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
1935                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1398  Line 1949 
1949          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1950    
1951  /* 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 */
1952          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1953                                           x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
1954                                           currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
1955                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1956                                                      iQuant, iFound);
1957    
1958          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1959                  *currMV = newMV;                  *currMV = newMV;
1960                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1961          }          }
1962    
1963          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
1964  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1965    
1966                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1967                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1968                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1969                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
1970                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1971                                                                      iDiamondSize, iFcode, iQuant, iFound);
1972    
1973                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1974                          *currMV = newMV;                          *currMV = newMV;
1975                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1976                  }                  }
1977                  }                  }
1978    
1979                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1980                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1981                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1982                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
1983                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
1984                                                                      iQuant, iFound);
1985    
1986                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1987                          *currMV = newMV;                          *currMV = newMV;
1988                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1989                  }                  }
# Line 1446  Line 1996 
1996    
1997  PMVfast8_Terminate_with_Refine:  PMVfast8_Terminate_with_Refine:
1998          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
1999                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2000                                                   x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2001                                                   currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2002                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2003    
2004    
2005  PMVfast8_Terminate_without_Refine:  PMVfast8_Terminate_without_Refine:
2006          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2007          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2008    
2009          return iMinSAD;          return iMinSAD;
2010  }  }
2011    
2012  int32_t EPZSSearch16(  int32_t
2013                                          const uint8_t * const pRef,  EPZSSearch16(const uint8_t * const pRef,
2014                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2015                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2016                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2017                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2018                                          const int x, const int y,                           const int x,
2019                             const int y,
2020                            const int start_x,
2021                            const int start_y,
2022                            const int center_x,
2023                            const int center_y,
2024                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2025                                          const uint32_t iQuant,                                          const uint32_t iQuant,
2026                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1496  Line 2051 
2051          int32_t psad[8];          int32_t psad[8];
2052    
2053          static MACROBLOCK * oldMBs = NULL;          static MACROBLOCK * oldMBs = NULL;
2054          const MACROBLOCK * const pMB = pMBs + x + y * iWcount;  
2055    //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
2056          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
2057          MACROBLOCK * oldMB = NULL;          MACROBLOCK * oldMB = NULL;
2058    
2059          static int32_t thresh2;           int32_t thresh2;
2060          int32_t bPredEq;          int32_t bPredEq;
2061          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2062    
2063          MainSearch16FuncPtr EPZSMainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
2064    
2065          if (oldMBs == NULL)          if (oldMBs == NULL) {
2066          {       oldMBs = (MACROBLOCK*) calloc(iWcount*iHcount,sizeof(MACROBLOCK));                  oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
2067  //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));  //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
2068          }          }
2069          oldMB = oldMBs + x + y * iWcount;          oldMB = oldMBs + x + y * iWcount;
2070    
2071  /* Get maximum range */  /* Get maximum range */
2072          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,
2073                          x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
2074    
2075          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
2076          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2077            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2078            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2079            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2080          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2081            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2082          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
2083            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2084    
2085  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2086          MinSAD=SAD          MinSAD=SAD
# Line 1534  Line 2091 
2091    
2092  // Prepare for main loop  // Prepare for main loop
2093    
2094          *currMV=pmv[0];         /* current best := median prediction */          currMV->x = start_x;
2095          if (!(MotionFlags & PMV_HALFPEL16))          currMV->y = start_y;
2096          {  
2097            if (!(MotionFlags & PMV_HALFPEL16)) {
2098                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2099                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2100          }          }
# Line 1552  Line 2110 
2110    
2111  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2112    
2113          iMinSAD = sad16( cur,          iMinSAD =
2114                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
2115                  iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2116          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2117            iMinSAD +=
2118                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2119                                              (uint8_t) iFcode, iQuant);
2120    
2121  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2122          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV, prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ((iMinSAD < 256) ||
2123                  {                  ((MVequal(*currMV, prevMB->mvs[0])) &&
2124                     ((int32_t) iMinSAD < prevMB->sad16))) {
2125                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2126                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2127                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1574  Line 2136 
2136  // set threshhold based on Min of Prediction and SAD of collocated block  // set threshhold based on Min of Prediction and SAD of collocated block
2137  // 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
2138    
2139          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
2140                  thresh2 =  512;                  thresh2 =  512;
2141          }          } else {
         else  
         {  
2142  /* 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] */
2143    
2144                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
# Line 1591  Line 2150 
2150    
2151    
2152  // left neighbour, if allowed  // left neighbour, if allowed
2153          if (x != 0)          if (x != 0) {
2154          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2155                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2156                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2157                  }                  }
2158                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
2159          }          }
   
2160  // top neighbour, if allowed  // top neighbour, if allowed
2161          if (y != 0)          if (y != 0) {
2162          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2163                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2164                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2165                  }                  }
2166                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
2167    
2168  // top right neighbour, if allowed  // top right neighbour, if allowed
2169                  if ((uint32_t)x != (iWcount-1))                  if ((uint32_t) x != (iWcount - 1)) {
2170                  {                          if (!(MotionFlags & PMV_HALFPEL16)) {
2171                          if (!(MotionFlags & PMV_HALFPEL16 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2172                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2173                          }                          }
2174                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
# Line 1625  Line 2180 
2180  */  */
2181    
2182          if ( (iMinSAD <= thresh2)          if ( (iMinSAD <= thresh2)
2183                  || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )                  || (MVequal(*currMV, prevMB->mvs[0]) &&
2184                  {                          ((int32_t) iMinSAD <= prevMB->sad16))) {
2185                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2186                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2187                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1647  Line 2202 
2202    
2203  // top neighbour  // top neighbour
2204          if (y != 0)          if (y != 0)
2205                  CHECK_MV16_CANDIDATE((prevMB-iWcount)->mvs[0].x,(prevMB-iWcount)->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,
2206                                                             (prevMB - iWcount)->mvs[0].y);
2207    
2208  // 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
2209    
# Line 1656  Line 2212 
2212    
2213  // bottom neighbour, dito  // bottom neighbour, dito
2214          if ((uint32_t)y != iHcount-1)          if ((uint32_t)y != iHcount-1)
2215                  CHECK_MV16_CANDIDATE((prevMB+iWcount)->mvs[0].x,(prevMB+iWcount)->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,
2216                                                             (prevMB + iWcount)->mvs[0].y);
2217    
2218  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
2219          if (iMinSAD <= thresh2)          if (iMinSAD <= thresh2) {
                 {  
2220                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2221                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2222                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1671  Line 2227 
2227    
2228          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2229    
 /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  
   
2230          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
2231                  EPZSMainSearchPtr = Square16_MainSearch;                  MainSearchPtr = Square16_MainSearch;
2232          else          else
2233                  EPZSMainSearchPtr = Diamond16_MainSearch;           if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2234                    MainSearchPtr = AdvDiamond16_MainSearch;
2235            else
2236                    MainSearchPtr = Diamond16_MainSearch;
2237    
2238          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);  
2239    
2240          if (iSAD < iMinSAD)          iSAD =
2241          {                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2242                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2243                                                      min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2244    
2245            if (iSAD < iMinSAD) {
2246                  *currMV = newMV;                  *currMV = newMV;
2247                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2248          }          }
2249    
2250    
2251          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
2252  /* 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) */
2253    
2254                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2255                  {                          iSAD =
2256                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2257                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2258                                  pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2259                                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    2, iFcode, iQuant, 0);
2260                  }                  }
2261    
2262                  if (iSAD < iMinSAD)                  if (iSAD < iMinSAD) {
                 {  
2263                          *currMV = newMV;                          *currMV = newMV;
2264                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2265                  }                  }
2266    
2267                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2268                  {                          iSAD =
2269                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2270                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2271                          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);  
2272    
2273                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2274                                  *currMV = newMV;                                  *currMV = newMV;
2275                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2276                          }                          }
# Line 1727  Line 2281 
2281    
2282  EPZS16_Terminate_with_Refine:  EPZS16_Terminate_with_Refine:
2283          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
2284                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2285                                  x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2286                                  currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2287                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
2288    
2289  EPZS16_Terminate_without_Refine:  EPZS16_Terminate_without_Refine:
2290    
2291          *oldMB = *prevMB;          *oldMB = *prevMB;
2292    
2293          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2294          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2295          return iMinSAD;          return iMinSAD;
2296  }  }
2297    
2298    
2299  int32_t EPZSSearch8(  int32_t
2300                                          const uint8_t * const pRef,  EPZSSearch8(const uint8_t * const pRef,
2301                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2302                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2303                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2304                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2305                                          const int x, const int y,                          const int x,
2306                                          const int start_x, const int start_y,                          const int y,
2307                            const int start_x,
2308                            const int start_y,
2309                            const int center_x,
2310                            const int center_y,
2311                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2312                                          const uint32_t iQuant,                                          const uint32_t iQuant,
2313                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1783  Line 2341 
2341    
2342          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);
2343    
2344          const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2345          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
2346    
2347          int32_t bPredEq;          int32_t bPredEq;
2348          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2349    
2350          MainSearch8FuncPtr EPZSMainSearchPtr;          MainSearch8FuncPtr MainSearchPtr;
2351    
2352  /* Get maximum range */  /* Get maximum range */
2353          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,
2354                          x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2355    
2356  /* 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 */
2357    
2358          if (!(MotionFlags & PMV_HALFPEL8 ))          if (!(MotionFlags & PMV_HALFPEL8)) {
2359          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2360            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2361            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2362            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2363          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2364            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2365          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);
2366            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2367    
2368    
2369  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
# Line 1817  Line 2376 
2376  // Prepare for main loop  // Prepare for main loop
2377    
2378    
2379          if (!(MotionFlags & PMV_HALFPEL8))          if (!(MotionFlags & PMV_HALFPEL8)) {
         {  
2380                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2381                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2382          }          }
# Line 1835  Line 2393 
2393  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2394    
2395    
2396          iMinSAD = sad8( cur,          iMinSAD =
2397                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  sad8(cur,
2398                  iEdgedWidth);                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2399          iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);                                                  iEdgedWidth), iEdgedWidth);
2400            iMinSAD +=
2401                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2402                                             (uint8_t) iFcode, iQuant);
2403    
2404    
2405  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2406          if (iMinSAD < 256/4 )          if (iMinSAD < 256 / 4) {
                 {  
2407                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2408                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2409                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
# Line 1860  Line 2420 
2420          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
2421    
2422  // left neighbour, if allowed  // left neighbour, if allowed
2423          if (psad[1] != MV_MAX_ERROR)          if (psad[1] != MV_MAX_ERROR) {
2424          {                  if (!(MotionFlags & PMV_HALFPEL8)) {
2425                  if (!(MotionFlags & PMV_HALFPEL8 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2426                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2427                  }                  }
2428                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
2429          }          }
   
2430  // top neighbour, if allowed  // top neighbour, if allowed
2431          if (psad[2] != MV_MAX_ERROR)          if (psad[2] != MV_MAX_ERROR) {
2432          {                  if (!(MotionFlags & PMV_HALFPEL8)) {
2433                  if (!(MotionFlags & PMV_HALFPEL8 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2434                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2435                  }                  }
2436                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
2437    
2438  // top right neighbour, if allowed  // top right neighbour, if allowed
2439                  if (psad[3] != MV_MAX_ERROR)                  if (psad[3] != MV_MAX_ERROR) {
2440                  {                          if (!(MotionFlags & PMV_HALFPEL8)) {
2441                          if (!(MotionFlags & PMV_HALFPEL8 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2442                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2443                          }                          }
2444                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);
# Line 1900  Line 2456 
2456     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]
2457  */  */
2458    
2459          if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */          if (iMinSAD < 512 / 4) {        /* T_2 == 512/4 hardcoded */
                 {  
2460                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2461                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2462                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
# Line 1917  Line 2472 
2472    
2473  /* 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 */
2474    
2475  /* // there is no EPZS^2 for inter4v at the moment  // there is no EPZS^2 for inter4v at the moment
2476    
2477          if (MotionFlags & PMV_USESQUARES8)  //  if (MotionFlags & PMV_USESQUARES8)
2478                  EPZSMainSearchPtr = Square8_MainSearch;  //      MainSearchPtr = Square8_MainSearch;
2479          else  //  else
 */  
2480    
2481          EPZSMainSearchPtr = Diamond8_MainSearch;          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2482                    MainSearchPtr = AdvDiamond8_MainSearch;
2483            else
2484                    MainSearchPtr = Diamond8_MainSearch;
2485    
2486          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2487                  x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2488                  currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2489                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2490                  iDiamondSize, iFcode, iQuant, 0);                                                    iQuant, 0);
2491    
2492    
2493          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2494                  *currMV = newMV;                  *currMV = newMV;
2495                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2496          }          }
2497    
2498          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2499  /* 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) */
2500    
2501                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2502                  {                          iSAD =
2503                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2504                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2505                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2506                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, 0);
2507    
2508                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2509                                  *currMV = newMV;                                  *currMV = newMV;
2510                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2511                          }                          }
2512                  }                  }
2513    
2514                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2515                  {                          iSAD =
2516                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2517                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2518                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2519                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iQuant, 0);
2520    
2521                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2522                                  *currMV = newMV;                                  *currMV = newMV;
2523                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2524                          }                          }
# Line 1976  Line 2529 
2529    
2530  EPZS8_Terminate_with_Refine:  EPZS8_Terminate_with_Refine:
2531          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2532                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2533                                  x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2534                                  currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2535                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2536    
2537  EPZS8_Terminate_without_Refine:  EPZS8_Terminate_without_Refine:
2538    
2539          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2540          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2541          return iMinSAD;          return iMinSAD;
2542  }  }
2543    
2544    
2545    
2546    int32_t
2547    PMVfastIntSearch16(const uint8_t * const pRef,
2548                                    const uint8_t * const pRefH,
2549                                    const uint8_t * const pRefV,
2550                                    const uint8_t * const pRefHV,
2551                                    const IMAGE * const pCur,
2552                                    const int x,
2553                                    const int y,
2554                            const int start_x,
2555                            const int start_y,
2556                            const int center_x,
2557                            const int center_y,
2558                                    const uint32_t MotionFlags,
2559                                    const uint32_t iQuant,
2560                                    const uint32_t iFcode,
2561                                    const MBParam * const pParam,
2562                                    const MACROBLOCK * const pMBs,
2563                                    const MACROBLOCK * const prevMBs,
2564                                    VECTOR * const currMV,
2565                                    VECTOR * const currPMV)
2566    {
2567            const uint32_t iWcount = pParam->mb_width;
2568            const int32_t iWidth = pParam->width;
2569            const int32_t iHeight = pParam->height;
2570            const int32_t iEdgedWidth = pParam->edged_width;
2571    
2572            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
2573            const VECTOR zeroMV = { 0, 0 };
2574    
2575            int32_t iDiamondSize;
2576    
2577            int32_t min_dx;
2578            int32_t max_dx;
2579            int32_t min_dy;
2580            int32_t max_dy;
2581    
2582            int32_t iFound;
2583    
2584            VECTOR newMV;
2585            VECTOR backupMV;                        /* just for PMVFAST */
2586    
2587            VECTOR pmv[4];
2588            int32_t psad[4];
2589    
2590            MainSearch16FuncPtr MainSearchPtr;
2591    
2592            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2593            MACROBLOCK *const pMB = pMBs + x + y * iWcount;
2594    
2595            int32_t threshA, threshB;
2596            int32_t bPredEq;
2597            int32_t iMinSAD, iSAD;
2598    
2599    
2600    /* Get maximum range */
2601            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2602                              iFcode);
2603    
2604    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2605    
2606            if ((x == 0) && (y == 0)) {
2607                    threshA = 512;
2608                    threshB = 1024;
2609    
2610                    bPredEq = 0;
2611                    psad[0] = psad[1] = psad[2] = psad[3] = 0;
2612                    *currMV = pmv[0] = pmv[1] = pmv[2] = pmv[3] = zeroMV;
2613    
2614            } else {
2615                    threshA = psad[0];
2616                    threshB = threshA + 256;
2617                    if (threshA < 512)
2618                            threshA = 512;
2619                    if (threshA > 1024)
2620                            threshA = 1024;
2621                    if (threshB > 1792)
2622                            threshB = 1792;
2623    
2624                    bPredEq = get_ipmvdata(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2625                    *currMV = pmv[0];                       /* current best := prediction */
2626            }
2627    
2628            iFound = 0;
2629    
2630    /* Step 4: Calculate SAD around the Median prediction.
2631       MinSAD=SAD
2632       If Motion Vector equal to Previous frame motion vector
2633       and MinSAD<PrevFrmSAD goto Step 10.
2634       If SAD<=256 goto Step 10.
2635    */
2636    
2637            if (currMV->x > max_dx) {
2638                    currMV->x = EVEN(max_dx);
2639            }
2640            if (currMV->x < min_dx) {
2641                    currMV->x = EVEN(min_dx);
2642            }
2643            if (currMV->y > max_dy) {
2644                    currMV->y = EVEN(max_dy);
2645            }
2646            if (currMV->y < min_dy) {
2647                    currMV->y = EVEN(min_dy);
2648            }
2649    
2650            iMinSAD =
2651                    sad16(cur,
2652                              get_iref_mv(pRef, x, y, 16, currMV,
2653                                                     iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2654            iMinSAD +=
2655                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2656                                              (uint8_t) iFcode, iQuant);
2657    
2658            if ((iMinSAD < 256) ||
2659                    ((MVequal(*currMV, prevMB->i_mvs[0])) &&
2660                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2661                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
2662                    {
2663                            if (!MVzero(*currMV)) {
2664                                    iMinSAD += MV16_00_BIAS;
2665                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
2666                                    iMinSAD -= MV16_00_BIAS;
2667                            }
2668                    }
2669    
2670                    if (MotionFlags & PMV_EARLYSTOP16)
2671                            goto PMVfastInt16_Terminate_with_Refine;
2672            }
2673    
2674    
2675    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2676       vector of the median.
2677       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2678    */
2679    
2680            if ((bPredEq) && (MVequal(pmv[0], prevMB->i_mvs[0])))
2681                    iFound = 2;
2682    
2683    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2684       Otherwise select large Diamond Search.
2685    */
2686    
2687            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
2688                    iDiamondSize = 2;               // halfpel units!
2689            else
2690                    iDiamondSize = 4;               // halfpel units!
2691    
2692    /*
2693       Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
2694       Also calculate (0,0) but do not subtract offset.
2695       Let MinSAD be the smallest SAD up to this point.
2696       If MV is (0,0) subtract offset.
2697    */
2698    
2699    // (0,0) is often a good choice
2700    
2701            if (!MVzero(pmv[0]))
2702                    CHECK_MV16_ZERO;
2703    
2704    // previous frame MV is always possible
2705    
2706            if (!MVzero(prevMB->i_mvs[0]))
2707                    if (!MVequal(prevMB->i_mvs[0], pmv[0]))
2708                            CHECK_MV16_CANDIDATE(prevMB->i_mvs[0].x, prevMB->i_mvs[0].y);
2709    
2710    // left neighbour, if allowed
2711    
2712            if (!MVzero(pmv[1]))
2713                    if (!MVequal(pmv[1], prevMB->i_mvs[0]))
2714                            if (!MVequal(pmv[1], pmv[0]))
2715                                    CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
2716    
2717    // top neighbour, if allowed
2718            if (!MVzero(pmv[2]))
2719                    if (!MVequal(pmv[2], prevMB->i_mvs[0]))
2720                            if (!MVequal(pmv[2], pmv[0]))
2721                                    if (!MVequal(pmv[2], pmv[1]))
2722                                            CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
2723    
2724    // top right neighbour, if allowed
2725                                            if (!MVzero(pmv[3]))
2726                                                    if (!MVequal(pmv[3], prevMB->i_mvs[0]))
2727                                                            if (!MVequal(pmv[3], pmv[0]))
2728                                                                    if (!MVequal(pmv[3], pmv[1]))
2729                                                                            if (!MVequal(pmv[3], pmv[2]))
2730                                                                                    CHECK_MV16_CANDIDATE(pmv[3].x,
2731                                                                                                                             pmv[3].y);
2732    
2733            if ((MVzero(*currMV)) &&
2734                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2735                    iMinSAD -= MV16_00_BIAS;
2736    
2737    
2738    /* Step 6: If MinSAD <= thresa goto Step 10.
2739       If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
2740    */
2741    
2742            if ((iMinSAD <= threshA) ||
2743                    (MVequal(*currMV, prevMB->i_mvs[0]) &&
2744                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2745    
2746                    if (MotionFlags & PMV_EARLYSTOP16)
2747                            goto PMVfastInt16_Terminate_with_Refine;
2748            }
2749    
2750    
2751    /************ (Diamond Search)  **************/
2752    /*
2753       Step 7: Perform Diamond search, with either the small or large diamond.
2754       If Found=2 only examine one Diamond pattern, and afterwards goto step 10
2755       Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
2756       If center then goto step 10.
2757       Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
2758       Refine by using small diamond and goto step 10.
2759    */
2760    
2761            if (MotionFlags & PMV_USESQUARES16)
2762                    MainSearchPtr = Square16_MainSearch;
2763            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2764                    MainSearchPtr = AdvDiamond16_MainSearch;
2765            else
2766                    MainSearchPtr = Diamond16_MainSearch;
2767    
2768            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2769    
2770    
2771    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2772            iSAD =
2773                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2774                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2775                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2776                                                      iQuant, iFound);
2777    
2778            if (iSAD < iMinSAD) {
2779                    *currMV = newMV;
2780                    iMinSAD = iSAD;
2781            }
2782    
2783            if (MotionFlags & PMV_EXTSEARCH16) {
2784    /* extended: search (up to) two more times: orignal prediction and (0,0) */
2785    
2786                    if (!(MVequal(pmv[0], backupMV))) {
2787                            iSAD =
2788                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2789                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2790                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2791                                                                      iDiamondSize, iFcode, iQuant, iFound);
2792    
2793                            if (iSAD < iMinSAD) {
2794                                    *currMV = newMV;
2795                                    iMinSAD = iSAD;
2796                            }
2797                    }
2798    
2799                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2800                            iSAD =
2801                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2802                                                                      iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2803                                                                      max_dy, iEdgedWidth, iDiamondSize, iFcode,
2804                                                                      iQuant, iFound);
2805    
2806                            if (iSAD < iMinSAD) {
2807                                    *currMV = newMV;
2808                                    iMinSAD = iSAD;
2809                            }
2810                    }
2811            }
2812    
2813    /*
2814       Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.
2815    */
2816    
2817    PMVfastInt16_Terminate_with_Refine:
2818    
2819            pMB->i_mvs[0] = pMB->i_mvs[1] = pMB->i_mvs[2] = pMB->i_mvs[3] = pMB->i_mv16 = *currMV;
2820            pMB->i_sad8[0] = pMB->i_sad8[1] = pMB->i_sad8[2] = pMB->i_sad8[3] = pMB->i_sad16 = iMinSAD;
2821    
2822            if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
2823                    iMinSAD =
2824                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2825                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2826                                                             iFcode, iQuant, iEdgedWidth);
2827    
2828            pmv[0] = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          // get _REAL_ prediction (halfpel possible)
2829    
2830    PMVfastInt16_Terminate_without_Refine:
2831            currPMV->x = currMV->x - center_x;
2832            currPMV->y = currMV->y - center_y;
2833            return iMinSAD;
2834    }
2835    
2836    
2837    
2838  /* ***********************************************************  /* ***********************************************************
# Line 1998  Line 2841 
2841  ***************************************************************/  ***************************************************************/
2842    
2843    
2844  void MotionEstimationBVOP(  #define DIRECT_PENALTY 0
2845                          MBParam * const pParam,  #define DIRECT_UPPERLIMIT 256   // never use direct mode if SAD is larger than this
                         FRAMEINFO * const frame,  
2846    
2847    void
2848    MotionEstimationBVOP(MBParam * const pParam,
2849                                             FRAMEINFO * const frame,
2850                                             const int32_t time_bp,
2851                                             const int32_t time_pp,
2852                          // forward (past) reference                          // forward (past) reference
2853                          const MACROBLOCK * const f_mbs,                          const MACROBLOCK * const f_mbs,
2854                      const IMAGE * const f_ref,                      const IMAGE * const f_ref,
# Line 2015  Line 2862 
2862                      const IMAGE * const b_refV,                      const IMAGE * const b_refV,
2863                          const IMAGE * const b_refHV)                          const IMAGE * const b_refHV)
2864  {  {
2865      const uint32_t mb_width = pParam->mb_width;          const int mb_width = pParam->mb_width;
2866      const uint32_t mb_height = pParam->mb_height;          const int mb_height = pParam->mb_height;
2867          const int32_t edged_width = pParam->edged_width;          const int edged_width = pParam->edged_width;
2868    
2869          uint32_t i,j;          int i, j, k;
2870    
2871          int32_t f_sad16;          static const VECTOR zeroMV={0,0};
2872          int32_t b_sad16;  
2873          int32_t i_sad16;          int f_sad16;    /* forward (as usual) search */
2874          int32_t d_sad16;          int b_sad16;    /* backward (only in b-frames) search */
2875          int32_t best_sad;          int i_sad16;    /* interpolated (both direction, b-frames only) */
2876            int d_sad16;    /* direct mode (assume linear motion) */
2877    
2878            int best_sad;
2879    
2880            VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/
2881          VECTOR pmv_dontcare;          VECTOR pmv_dontcare;
2882    
2883            int f_count=0;
2884            int b_count=0;
2885            int i_count=0;
2886            int d_count=0;
2887            int s_count=0;
2888    
2889            const int64_t TRB = (int32_t)time_pp - (int32_t)time_bp;
2890        const int64_t TRD = (int32_t)time_pp;
2891    
2892            // fprintf(stderr,"TRB = %lld  TRD = %lld  time_bp =%d time_pp =%d\n\n",TRB,TRD,time_bp,time_pp);
2893          // note: i==horizontal, j==vertical          // note: i==horizontal, j==vertical
2894      for (j = 0; j < mb_height; j++)          for (j = 0; j < mb_height; j++) {
2895          {  
2896                  for (i = 0; i < mb_width; i++)                  f_predMV = zeroMV;      /* prediction is reset at left boundary */
2897                  {                  b_predMV = zeroMV;
2898    
2899                    for (i = 0; i < mb_width; i++) {
2900                          MACROBLOCK *mb = &frame->mbs[i + j*mb_width];                          MACROBLOCK *mb = &frame->mbs[i + j*mb_width];
2901                          const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];                          const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];
2902                          const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];                          const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];
2903    
2904                          if (b_mb->mode == MODE_INTER                          mb->deltamv=zeroMV;
2905                                  && b_mb->cbp == 0  
2906                                  && b_mb->mvs[0].x == 0  /* special case, if collocated block is SKIPed: encoding is forward(0,0)  */
2907                                  && b_mb->mvs[0].y == 0)  
2908                          {  #ifndef _DISABLE_SKIP
2909                            if (b_mb->mode == MODE_INTER && b_mb->cbp == 0 &&
2910                                    b_mb->mvs[0].x == 0 && b_mb->mvs[0].y == 0) {
2911                                  mb->mode = MODE_NOT_CODED;                                  mb->mode = MODE_NOT_CODED;
2912                                  mb->mvs[0].x = 0;                                  mb->mvs[0].x = 0;
2913                                  mb->mvs[0].y = 0;                                  mb->mvs[0].y = 0;
# Line 2050  Line 2915 
2915                                  mb->b_mvs[0].y = 0;                                  mb->b_mvs[0].y = 0;
2916                                  continue;                                  continue;
2917                          }                          }
2918    #endif
2919    
2920                            d_sad16 = DIRECT_PENALTY;
2921    
2922                            if (b_mb->mode == MODE_INTER4V)
2923                            {
2924    
2925                            /* same method of scaling as in decoder.c, so we copy from there */
2926                        for (k = 0; k < 4; k++) {
2927    
2928                                            mb->directmv[k] = b_mb->mvs[k];
2929    
2930                                            mb->mvs[k].x = (int32_t) ((TRB * mb->directmv[k].x) / TRD + mb->deltamv.x);
2931                        mb->b_mvs[k].x = (int32_t) ((mb->deltamv.x == 0)
2932                                                                                    ? ((TRB - TRD) * mb->directmv[k].x) / TRD
2933                                                : mb->mvs[k].x - mb->directmv[k].x);
2934    
2935                        mb->mvs[k].y = (int32_t) ((TRB * mb->directmv[k].y) / TRD + mb->deltamv.y);
2936                            mb->b_mvs[k].y = (int32_t) ((mb->directmv[k].y == 0)
2937                                                                                    ? ((TRB - TRD) * mb->directmv[k].y) / TRD
2938                                                : mb->mvs[k].y - mb->directmv[k].y);
2939    
2940                                            d_sad16 +=
2941                                                    sad8bi(frame->image.y + 2*(i+(k&1))*8 + 2*(j+(k>>1))*8*edged_width,
2942                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2943                                                                    2*(i+(k&1)), 2*(j+(k>>1)), 8, &mb->mvs[k], edged_width),
2944                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2945                                                                    2*(i+(k&1)), 2*(j+(k>>1)), 8, &mb->b_mvs[k], edged_width),
2946                                                      edged_width);
2947                                    }
2948                            }
2949                            else
2950                            {
2951                                    mb->directmv[3] = mb->directmv[2] = mb->directmv[1] =
2952                                    mb->directmv[0] = b_mb->mvs[0];
2953    
2954                                    mb->mvs[0].x = (int32_t) ((TRB * mb->directmv[0].x) / TRD + mb->deltamv.x);
2955                        mb->b_mvs[0].x = (int32_t) ((mb->deltamv.x == 0)
2956                                                                            ? ((TRB - TRD) * mb->directmv[0].x) / TRD
2957                                        : mb->mvs[0].x - mb->directmv[0].x);
2958    
2959                        mb->mvs[0].y = (int32_t) ((TRB * mb->directmv[0].y) / TRD + mb->deltamv.y);
2960                    mb->b_mvs[0].y = (int32_t) ((mb->directmv[0].y == 0)
2961                                                                            ? ((TRB - TRD) * mb->directmv[0].y) / TRD
2962                                        : mb->mvs[0].y - mb->directmv[0].y);
2963    
2964                                    d_sad16 += sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,
2965                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2966                                                                    i, j, 16, &mb->mvs[0], edged_width),
2967                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2968                                                                    i, j, 16, &mb->b_mvs[0], edged_width),
2969                                                      edged_width);
2970    
2971                }
2972                        d_sad16 += calc_delta_16(mb->deltamv.x, mb->deltamv.y, 1, frame->quant);
2973    
2974                          // forward search                          // forward search
2975                          f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                          f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2976                                                  &frame->image,                                                  &frame->image, i, j,
2977                                                  i, j,                                                  mb->mvs[0].x, mb->mvs[0].y,                     /* start point f_directMV */
2978                                                  frame->motion_flags,  frame->quant, frame->fcode,                                                  f_predMV.x, f_predMV.y,                         /* center is f-prediction */
2979                                                  pParam,                                                  frame->motion_flags,
2980                                                  f_mbs, f_mbs /* todo */,                                                  frame->quant, frame->fcode, pParam,
2981                                                  &mb->mvs[0], &pmv_dontcare);    // ignore pmv                                                  f_mbs, f_mbs,
2982                                                    &mb->mvs[0], &pmv_dontcare);
2983    
2984    
2985                          // backward search                          // backward search
2986                          b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,                          b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2987                                                  &frame->image,                                                  &frame->image, i, j,
2988                                                  i, j,                                                  mb->b_mvs[0].x, mb->b_mvs[0].y,         /* start point b_directMV */
2989                                                  frame->motion_flags,  frame->quant, frame->bcode,                                                  b_predMV.x, b_predMV.y,                         /* center is b-prediction */
2990                                                  pParam,                                                  frame->motion_flags,
2991                                                  b_mbs, b_mbs, /* todo */                                                  frame->quant, frame->bcode, pParam,
2992                                                  &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv                                                  b_mbs, b_mbs,
2993                                                    &mb->b_mvs[0], &pmv_dontcare);
2994                          // interpolate search (simple, but effective)  
2995                          i_sad16 = sad16bi_c(                          i_sad16 =
2996                                          frame->image.y + i*16 + j*16*edged_width,                                  sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,
2997                                          get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                                                    get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2998                                                  i, j, 16, mb->mvs[0].x, mb->mvs[0].y, edged_width),                                                                  i, j, 16, &mb->mvs[0], edged_width),
2999                                          get_ref(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,                                                    get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3000                                                  i, j, 16, mb->b_mvs[0].x, mb->b_mvs[0].x, edged_width),                                                                  i, j, 16, &mb->b_mvs[0], edged_width),
3001                                          edged_width);                                          edged_width);
3002                        i_sad16 += calc_delta_16(mb->mvs[0].x-f_predMV.x, mb->mvs[0].y-f_predMV.y,
3003                                                                    frame->fcode, frame->quant);
3004                        i_sad16 += calc_delta_16(mb->b_mvs[0].x-b_predMV.x, mb->b_mvs[0].y-b_predMV.y,
3005                                                                    frame->bcode, frame->quant);
3006