[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 370, Mon Aug 12 10:07:16 2002 UTC
# Line 1  Line 1 
1  /**************************************************************************  /**************************************************************************
2   *   *
3     *      XVID MPEG-4 VIDEO CODEC
4     *      motion estimation
5     *
6     *      This program is an implementation of a part of one or more MPEG-4
7     *      Video tools as specified in ISO/IEC 14496-2 standard.  Those intending
8     *      to use this software module in hardware or software products are
9     *      advised that its use may infringe existing patents or copyrights, and
10     *      any such use would be at such party's own risk.  The original
11     *      developer of this software module and his/her company, and subsequent
12     *      editors and their companies, will have no liability for use of this
13     *      software or modifications or derivatives thereof.
14     *
15     *      This program is free software; you can redistribute it and/or modify
16     *      it under the terms of the GNU General Public License as published by
17     *      the Free Software Foundation; either version 2 of the License, or
18     *      (at your option) any later version.
19     *
20     *      This program is distributed in the hope that it will be useful,
21     *      but WITHOUT ANY WARRANTY; without even the implied warranty of
22     *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23     *      GNU General Public License for more details.
24     *
25     *      You should have received a copy of the GNU General Public License
26     *      along with this program; if not, write to the Free Software
27     *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28     *
29     *************************************************************************/
30    
31    /**************************************************************************
32     *
33   *  Modifications:   *  Modifications:
34   *   *
35   *      01.05.2002      updated MotionEstimationBVOP   *      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                            if (pMB->mode == MODE_NOT_CODED)
190                                    continue;
191    
192                          /* decide: MODE_INTER or MODE_INTRA                          predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
                            if (dev_intra < sad_inter - 2 * nb) use_intra  
                         */  
193    
194                          deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width);                          pMB->sad16 =
195                                    SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
196                                                     x, y, predMV.x, predMV.y, predMV.x, predMV.y,
197                                                     current->motion_flags, current->quant,
198                                                     current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,
199                                                     &pMB->pmvs[0]);
200    
201                          if (deviation < (sad16 - INTER_BIAS))                          if (0 < (pMB->sad16 - MV16_INTER_BIAS)) {
202                          {                                  int32_t deviation;
                                 pMB->mode = MODE_INTRA;  
                                 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;  
203    
204                                  pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = 0;                                  deviation =
205                                            dev16(pCurrent->y + x * 16 + y * 16 * pParam->edged_width,
206                                                      pParam->edged_width);
207    
208                                    if (deviation < (pMB->sad16 - MV16_INTER_BIAS)) {
209                                            pMB->mode = MODE_INTRA;
210                                            pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
211                                                    pMB->mvs[3] = zeroMV;
212                                            pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
213                                                    pMB->sad8[3] = 0;
214    
215                                  iIntra++;                                  iIntra++;
216                                  if(iIntra >= iLimit)                                  if(iIntra >= iLimit)
# Line 323  Line 218 
218    
219                                  continue;                                  continue;
220                          }                          }
221                            }
222    
223                            pmv = pMB->pmvs[0];
224                          if (current->global_flags & XVID_INTER4V)                          if (current->global_flags & XVID_INTER4V)
225                          {                                  if ((!(current->global_flags & XVID_LUMIMASKING) ||
226                                  pMB->sad8[0] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                           pMB->dquant == NO_CHANGE)) {
227                                                         2 * j, 2 * i, mv16.x, mv16.y,                                          int32_t sad8 = IMV16X16 * current->quant;
228                                                             current->motion_flags, current->quant, current->fcode,  
229                                                         pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]);                                          if (sad8 < pMB->sad16) {
230                                                    sad8 += pMB->sad8[0] =
231                                  pMB->sad8[1] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
232                                                         2 * j + 1, 2 * i, mv16.x, mv16.y,                                                                          pCurrent, 2 * x, 2 * y,
233                                                             current->motion_flags, current->quant, current->fcode,                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
234                                                         pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]);                                                                          current->motion_flags,
235                                                                            current->quant, current->fcode, pParam,
236                                  pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                                          pMBs, prevMBs, &pMB->mvs[0],
237                                                         2 * j, 2 * i + 1, mv16.x, mv16.y,                                                                          &pMB->pmvs[0]);
238                                                             current->motion_flags, current->quant, current->fcode,                                          }
239                                                         pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]);                                          if (sad8 < pMB->sad16) {
240    
241                                  pMB->sad8[3] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                  predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 1);
242                                                         2 * j + 1, 2 * i + 1, mv16.x, mv16.y,                                                  sad8 += pMB->sad8[1] =
243                                                             current->motion_flags, current->quant, current->fcode,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
244                                                         pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]);                                                                          pCurrent, 2 * x + 1, 2 * y,
245                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
246                                  sad8 = pMB->sad8[0] + pMB->sad8[1] + pMB->sad8[2] + pMB->sad8[3];                                                                          current->motion_flags,
247                                                                            current->quant, current->fcode, pParam,
248                                                                            pMBs, prevMBs, &pMB->mvs[1],
249                                                                            &pMB->pmvs[1]);
250                                            }
251                                            if (sad8 < pMB->sad16) {
252                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 2);
253                                                    sad8 += pMB->sad8[2] =
254                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
255                                                                            pCurrent, 2 * x, 2 * y + 1,
256                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
257                                                                            current->motion_flags,
258                                                                            current->quant, current->fcode, pParam,
259                                                                            pMBs, prevMBs, &pMB->mvs[2],
260                                                                            &pMB->pmvs[2]);
261                                            }
262                                            if (sad8 < pMB->sad16) {
263                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 3);
264                                                    sad8 += pMB->sad8[3] =
265                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
266                                                                            pCurrent, 2 * x + 1, 2 * y + 1,
267                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
268                                                                            current->motion_flags,
269                                                                            current->quant, current->fcode, pParam,
270                                                                            pMBs, prevMBs,
271                                                                            &pMB->mvs[3],
272                                                                            &pMB->pmvs[3]);
273                          }                          }
274    
   
275                          /* decide: MODE_INTER or MODE_INTER4V                          /* decide: MODE_INTER or MODE_INTER4V
276                             mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v                                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
277                          */                          */
278    
279                          if (!(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  
                                 {  
280                                          pMB->mode = MODE_INTER4V;                                          pMB->mode = MODE_INTER4V;
281                                          pMB->sad8[0] *= 4;                                          pMB->sad8[0] *= 4;
282                                          pMB->sad8[1] *= 4;                                          pMB->sad8[1] *= 4;
283                                          pMB->sad8[2] *= 4;                                          pMB->sad8[2] *= 4;
284                                          pMB->sad8[3] *= 4;                                          pMB->sad8[3] *= 4;
285                                                    continue;
286                                  }                                  }
287    
288                          }                          }
                         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;  
289    
290                                  pMB->pmvs[0].x = pmv16.x;                          pMB->mode = MODE_INTER;
291                                  pMB->pmvs[0].y = pmv16.y;                          pMB->pmvs[0] = pmv;     /* pMB->pmvs[1] = pMB->pmvs[2] = pMB->pmvs[3]  are not needed for INTER */
292                            pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
293                            pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =
294                                    pMB->sad16;
295                          }                          }
296                  }                  }
297    
298          return 0;          return 0;
299  }  }
300    
 #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )  
   
 #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )  
   
301    
302  #define CHECK_MV16_ZERO {\  #define CHECK_MV16_ZERO {\
303    if ( (0 <= max_dx) && (0 >= min_dx) \    if ( (0 <= max_dx) && (0 >= min_dx) \
304      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
305    { \    { \
306      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \
307      iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16(-center_x, -center_y, (uint8_t)iFcode, iQuant);\
308      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
309      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
310  }  }
311    
312  #define NOCHECK_MV16_CANDIDATE(X,Y) { \  #define NOCHECK_MV16_CANDIDATE(X,Y) { \
313      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
314      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
315      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
316      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
317  }  }
# Line 420  Line 321 
321      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
322    { \    { \
323      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
324      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
325      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
326      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
327  }  }
# Line 430  Line 331 
331      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
332    { \    { \
333      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
334      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
335      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
336      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
337  }  }
# Line 440  Line 341 
341      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
342    { \    { \
343      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
344      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
345      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
346      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
347  }  }
# Line 448  Line 349 
349    
350  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
351    iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \    iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \
352    iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\    iSAD += calc_delta_8(-center_x, -center_y, (uint8_t)iFcode, iQuant);\
353    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
354    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
355  }  }
# Line 456  Line 357 
357  #define NOCHECK_MV8_CANDIDATE(X,Y) \  #define NOCHECK_MV8_CANDIDATE(X,Y) \
358    { \    { \
359      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
360      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
361      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
362      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
363  }  }
# Line 466  Line 367 
367      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
368    { \    { \
369      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
370      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
371      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
372      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
373  }  }
# Line 476  Line 377 
377      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
378    { \    { \
379      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
380      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
381      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
382      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
383  }  }
# Line 486  Line 387 
387      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
388    { \    { \
389      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
390      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
391      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
392      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
393  }  }
# Line 512  Line 413 
413          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
414          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
415          int32_t iSAD;          int32_t iSAD;
416          int32_t pred_x,pred_y;          VECTOR pred;
417    
418    
419          get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);          pred = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
420    
421          iSAD = sad16( cur,          iSAD = sad16( cur,
422                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),
# Line 524  Line 426 
426    
427          currMV->x = 0;          currMV->x = 0;
428          currMV->y = 0;          currMV->y = 0;
429          currPMV->x = -pred_x;          currPMV->x = -pred.x;
430          currPMV->y = -pred_y;          currPMV->y = -pred.y;
431    
432          return iSAD;          return iSAD;
433    
434  }  }
435  */  */
436    
437  int32_t Diamond16_MainSearch(  int32_t
438          const uint8_t * const pRef,  Diamond16_MainSearch(const uint8_t * const pRef,
439          const uint8_t * const pRefH,          const uint8_t * const pRefH,
440          const uint8_t * const pRefV,          const uint8_t * const pRefV,
441          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
442          const uint8_t * const cur,          const uint8_t * const cur,
443          const int x, const int y,                                           const int x,
444          int32_t startx, int32_t starty,                                           const int y,
445          int32_t iMinSAD,                                     const int start_x,
446                                       const int start_y,
447                                       int iMinSAD,
448          VECTOR * const currMV,          VECTOR * const currMV,
449          const VECTOR * const pmv,                                     const int center_x,
450          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
451          const int32_t min_dy, const int32_t max_dy,                                           const int32_t min_dx,
452                                             const int32_t max_dx,
453                                             const int32_t min_dy,
454                                             const int32_t max_dy,
455          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
456          const int32_t iDiamondSize,          const int32_t iDiamondSize,
457          const int32_t iFcode,          const int32_t iFcode,
# Line 554  Line 461 
461  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
462    
463          int32_t iDirection=0;          int32_t iDirection=0;
464            int32_t iDirectionBackup;
465          int32_t iSAD;          int32_t iSAD;
466          VECTOR backupMV;          VECTOR backupMV;
467          backupMV.x = startx;  
468          backupMV.y = starty;          backupMV.x = start_x;
469            backupMV.y = start_y;
470    
471  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
472    
# Line 566  Line 475 
475          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
476          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
477    
478          if (iDirection)          if (iDirection) {
479                  while (!iFound)                  while (!iFound) {
                 {  
480                          iFound = 1;                          iFound = 1;
481                          backupMV=*currMV;                          backupMV=*currMV;
482                            iDirectionBackup = iDirection;
483    
484                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
485                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
486                          if ( iDirection != 1)                                                                                     backupMV.y, 1);
487                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
488                          if ( iDirection != 4)                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
489                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                     backupMV.y, 2);
490                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
491                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
492                                                                                       backupMV.y - iDiamondSize, 3);
493                            if (iDirectionBackup != 3)
494                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
495                                                                                       backupMV.y + iDiamondSize, 4);
496                  }                  }
497          else          } else {
498          {                  currMV->x = start_x;
499                  currMV->x = startx;                  currMV->y = start_y;
                 currMV->y = starty;  
500          }          }
501          return iMinSAD;          return iMinSAD;
502  }  }
503    
504  int32_t Square16_MainSearch(  int32_t
505                                          const uint8_t * const pRef,  Square16_MainSearch(const uint8_t * const pRef,
506                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
507                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
508                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
509                                          const uint8_t * const cur,                                          const uint8_t * const cur,
510                                          const int x, const int y,                                          const int x,
511                                          int32_t startx, int32_t starty,                                          const int y,
512                                          int32_t iMinSAD,                                     const int start_x,
513                                       const int start_y,
514                                       int iMinSAD,
515                                          VECTOR * const currMV,                                          VECTOR * const currMV,
516                                          const VECTOR * const pmv,                                     const int center_x,
517                                          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
518                                          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
519                                            const int32_t max_dx,
520                                            const int32_t min_dy,
521                                            const int32_t max_dy,
522                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
523                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
524                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 613  Line 530 
530          int32_t iDirection=0;          int32_t iDirection=0;
531          int32_t iSAD;          int32_t iSAD;
532          VECTOR backupMV;          VECTOR backupMV;
533          backupMV.x = startx;  
534          backupMV.y = starty;          backupMV.x = start_x;
535            backupMV.y = start_y;
536    
537  /* It's one search with full square pattern, and new parts for all following diamonds */  /* It's one search with full square pattern, and new parts for all following diamonds */
538    
# Line 629  Line 547 
547          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
548          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
549    
550          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
551          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                           backupMV.y - iDiamondSize, 5);
552          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
553          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                                           backupMV.y + iDiamondSize, 6);
554            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
555                                                             backupMV.y - iDiamondSize, 7);
556            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
557                                                             backupMV.y + iDiamondSize, 8);
558    
559    
560          if (iDirection)          if (iDirection) {
561                  while (!iFound)                  while (!iFound) {
                 {  
562                          iFound = 1;                          iFound = 1;
563                          backupMV=*currMV;                          backupMV=*currMV;
564    
565                          switch (iDirection)                          switch (iDirection) {
                         {  
566                                  case 1:                                  case 1:
567                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
568                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                     backupMV.y, 1);
569                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
570                                                                                     backupMV.y - iDiamondSize, 5);
571                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
572                                                                                     backupMV.y - iDiamondSize, 7);
573                                          break;                                          break;
574                                  case 2:                                  case 2:
575                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
576                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   2);
577                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
578                                                                                     backupMV.y + iDiamondSize, 6);
579                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
580                                                                                     backupMV.y + iDiamondSize, 8);
581                                          break;                                          break;
582    
583                                  case 3:                                  case 3:
584                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
585                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
586                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
587                                                                                     backupMV.y - iDiamondSize, 7);
588                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
589                                                                                     backupMV.y + iDiamondSize, 8);
590                                          break;                                          break;
591    
592                                  case 4:                                  case 4:
593                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
594                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
595                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
596                                                                                     backupMV.y - iDiamondSize, 5);
597                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
598                                                                                     backupMV.y + iDiamondSize, 6);
599                                          break;                                          break;
600    
601                                  case 5:                                  case 5:
602                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
603                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   1);
604                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
605                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   3);
606                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
607                                                                                     backupMV.y - iDiamondSize, 5);
608                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
609                                                                                     backupMV.y + iDiamondSize, 6);
610                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
611                                                                                     backupMV.y - iDiamondSize, 7);
612                                          break;                                          break;
613    
614                                  case 6:                                  case 6:
615                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
616                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   2);
617                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
618                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
619                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);  
620                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
621                                                                                     backupMV.y - iDiamondSize, 5);
622                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
623                                                                                     backupMV.y + iDiamondSize, 6);
624                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
625                                                                                     backupMV.y + iDiamondSize, 8);
626    
627                                          break;                                          break;
628    
629                                  case 7:                                  case 7:
630                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
631                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                     backupMV.y, 1);
632                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
633                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
634                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
635                                                                                     backupMV.y - iDiamondSize, 5);
636                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
637                                                                                     backupMV.y - iDiamondSize, 7);
638                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
639                                                                                     backupMV.y + iDiamondSize, 8);
640                                          break;                                          break;
641    
642                                  case 8:                                  case 8:
643                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
644                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
645                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
646                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
647                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
648                                                                                     backupMV.y + iDiamondSize, 6);
649                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
650                                                                                     backupMV.y - iDiamondSize, 7);
651                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
652                                                                                     backupMV.y + iDiamondSize, 8);
653                                          break;                                          break;
654                          default:                          default:
655                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
656                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                                                                   1);
657                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
658                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
659                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
660                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
661                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
662                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
663                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);  
664                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
665                                                                                     backupMV.y - iDiamondSize, 5);
666                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
667                                                                                     backupMV.y + iDiamondSize, 6);
668                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
669                                                                                     backupMV.y - iDiamondSize, 7);
670                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
671                                                                                     backupMV.y + iDiamondSize, 8);
672                                          break;                                          break;
673                          }                          }
674                  }                  }
675          else          } else {
676                  {                  currMV->x = start_x;
677                          currMV->x = startx;                  currMV->y = start_y;
                         currMV->y = starty;  
678                  }                  }
679          return iMinSAD;          return iMinSAD;
680  }  }
681    
682    
683  int32_t Full16_MainSearch(  int32_t
684                                          const uint8_t * const pRef,  Full16_MainSearch(const uint8_t * const pRef,
685                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
686                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
687                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
688                                          const uint8_t * const cur,                                          const uint8_t * const cur,
689                                          const int x, const int y,                                    const int x,
690                                          int32_t startx, int32_t starty,                                    const int y,
691                                          int32_t iMinSAD,                                     const int start_x,
692                                       const int start_y,
693                                       int iMinSAD,
694                                          VECTOR * const currMV,                                          VECTOR * const currMV,
695                                          const VECTOR * const pmv,                                     const int center_x,
696                                          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
697                                          const int32_t min_dy, const int32_t max_dy,                                    const int32_t min_dx,
698                                      const int32_t max_dx,
699                                      const int32_t min_dy,
700                                      const int32_t max_dy,
701                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
702                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
703                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 743  Line 707 
707          int32_t iSAD;          int32_t iSAD;
708          int32_t dx,dy;          int32_t dx,dy;
709          VECTOR backupMV;          VECTOR backupMV;
710          backupMV.x = startx;  
711          backupMV.y = starty;          backupMV.x = start_x;
712            backupMV.y = start_y;
713    
714          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
715                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
# Line 753  Line 718 
718          return iMinSAD;          return iMinSAD;
719  }  }
720    
721  int32_t Full8_MainSearch(  int32_t
722                                          const uint8_t * const pRef,  AdvDiamond16_MainSearch(const uint8_t * const pRef,
723                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
724                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
725                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
726                                          const uint8_t * const cur,                                          const uint8_t * const cur,
727                                          const int x, const int y,                                                  const int x,
728                                          int32_t startx, int32_t starty,                                                  const int y,
729                                          int32_t iMinSAD,                                             int start_x,
730                                               int start_y,
731                                               int iMinSAD,
732                                          VECTOR * const currMV,                                          VECTOR * const currMV,
733                                          const VECTOR * const pmv,                                             const int center_x,
734                                          const int32_t min_dx, const int32_t max_dx,                                             const int center_y,
735                                          const int32_t min_dy, const int32_t max_dy,                                                  const int32_t min_dx,
736                                                    const int32_t max_dx,
737                                                    const int32_t min_dy,
738                                                    const int32_t max_dy,
739                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
740                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
741                                          const int32_t iFcode,                                          const int32_t iFcode,
742                                          const int32_t iQuant,                                          const int32_t iQuant,
743                                          int iFound)                                                  int iDirection)
744  {  {
745    
746          int32_t iSAD;          int32_t iSAD;
         int32_t dx,dy;  
         VECTOR backupMV;  
         backupMV.x = startx;  
         backupMV.y = starty;  
747    
748          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
                 for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)  
                         NOCHECK_MV8_CANDIDATE(dx,dy);  
749    
750          return iMinSAD;          if (iDirection) {
751  }                  CHECK_MV16_CANDIDATE(start_x - iDiamondSize, start_y);
752                    CHECK_MV16_CANDIDATE(start_x + iDiamondSize, start_y);
753                    CHECK_MV16_CANDIDATE(start_x, start_y - iDiamondSize);
754                    CHECK_MV16_CANDIDATE(start_x, start_y + iDiamondSize);
755            } else {
756                    int bDirection = 1 + 2 + 4 + 8;
757    
758                    do {
759                            iDirection = 0;
760                            if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
761                                    CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
762    
763                            if (bDirection & 2)
764                                    CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
765    
766  int32_t Halfpel16_Refine(                          if (bDirection & 4)
767          const uint8_t * const pRef,                                  CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
         const uint8_t * const pRefH,  
         const uint8_t * const pRefV,  
         const uint8_t * const pRefHV,  
         const uint8_t * const cur,  
         const int x, const int y,  
         VECTOR * const currMV,  
         int32_t iMinSAD,  
         const VECTOR * const pmv,  
         const int32_t min_dx, const int32_t max_dx,  
         const int32_t min_dy, const int32_t max_dy,  
         const int32_t iFcode,  
         const int32_t iQuant,  
         const int32_t iEdgedWidth)  
 {  
 /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  
768    
769          int32_t iSAD;                          if (bDirection & 8)
770          VECTOR backupMV = *currMV;                                  CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
771    
772          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y-1);                          /* now we're doing diagonal checks near our candidate */
         CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y-1);  
         CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y-1);  
         CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y);  
         CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y);  
         CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y+1);  
         CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y+1);  
         CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y+1);  
773    
774          return iMinSAD;                          if (iDirection)         //checking if anything found
775                            {
776                                    bDirection = iDirection;
777                                    iDirection = 0;
778                                    start_x = currMV->x;
779                                    start_y = currMV->y;
780                                    if (bDirection & 3)     //our candidate is left or right
781                                    {
782                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
783                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
784                                    } else                  // what remains here is up or down
785                                    {
786                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
787                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
788  }  }
789    
790  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)                                  if (iDirection) {
791                                            bDirection += iDirection;
792                                            start_x = currMV->x;
793  int32_t PMVfastSearch16(                                          start_y = currMV->y;
794                                          const uint8_t * const pRef,                                  }
795                                          const uint8_t * const pRefH,                          } else                          //about to quit, eh? not so fast....
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const uint32_t MotionFlags,  
                                         const 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)  
796  {  {
797      const uint32_t iWcount = pParam->mb_width;                                  switch (bDirection) {
798          const int32_t iWidth = pParam->width;                                  case 2:
799          const int32_t iHeight = pParam->height;                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
800          const int32_t iEdgedWidth = pParam->edged_width;                                                                                           start_y - iDiamondSize, 2 + 4);
801                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
802          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;                                                                                           start_y + iDiamondSize, 2 + 8);
803                                            break;
804                                    case 1:
805    
806          int32_t iDiamondSize;                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
807                                                                                             start_y - iDiamondSize, 1 + 4);
808                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
809                                                                                             start_y + iDiamondSize, 1 + 8);
810                                            break;
811                                    case 2 + 4:
812                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
813                                                                                             start_y - iDiamondSize, 1 + 4);
814                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
815                                                                                             start_y - iDiamondSize, 2 + 4);
816                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
817                                                                                             start_y + iDiamondSize, 2 + 8);
818                                            break;
819                                    case 4:
820                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
821                                                                                             start_y - iDiamondSize, 2 + 4);
822                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
823                                                                                             start_y - iDiamondSize, 1 + 4);
824                                            break;
825                                    case 8:
826                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
827                                                                                             start_y + iDiamondSize, 2 + 8);
828                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
829                                                                                             start_y + iDiamondSize, 1 + 8);
830                                            break;
831                                    case 1 + 4:
832                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
833                                                                                             start_y + iDiamondSize, 1 + 8);
834                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
835                                                                                             start_y - iDiamondSize, 1 + 4);
836                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
837                                                                                             start_y - iDiamondSize, 2 + 4);
838                                            break;
839                                    case 2 + 8:
840                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
841                                                                                             start_y - iDiamondSize, 1 + 4);
842                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
843                                                                                             start_y + iDiamondSize, 1 + 8);
844                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
845                                                                                             start_y + iDiamondSize, 2 + 8);
846                                            break;
847                                    case 1 + 8:
848                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
849                                                                                             start_y - iDiamondSize, 2 + 4);
850                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
851                                                                                             start_y + iDiamondSize, 2 + 8);
852                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
853                                                                                             start_y + iDiamondSize, 1 + 8);
854                                            break;
855                                    default:                //1+2+4+8 == we didn't find anything at all
856                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
857                                                                                             start_y - iDiamondSize, 1 + 4);
858                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
859                                                                                             start_y + iDiamondSize, 1 + 8);
860                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
861                                                                                             start_y - iDiamondSize, 2 + 4);
862                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
863                                                                                             start_y + iDiamondSize, 2 + 8);
864                                            break;
865                                    }
866                                    if (!iDirection)
867                                            break;          //ok, the end. really
868                                    else {
869                                            bDirection = iDirection;
870                                            start_x = currMV->x;
871                                            start_y = currMV->y;
872                                    }
873                            }
874                    }
875                    while (1);                              //forever
876            }
877            return iMinSAD;
878    }
879    
880    #define CHECK_MV16_F_INTERPOL(X,Y) { \
881      if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
882        && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
883      { \
884        iSAD = sad16bi( cur, \
885                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
886                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
887                            iEdgedWidth); \
888        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
889        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
890        if (iSAD < iMinSAD) \
891        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); } } \
892    }
893    
894    #define CHECK_MV16_F_INTERPOL_FOUND(X,Y) { \
895      if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
896        && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
897      { \
898        iSAD = sad16bi( cur, \
899                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
900                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
901                            iEdgedWidth); \
902        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
903        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
904        if (iSAD < iMinSAD) \
905        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); iFound=0;} } \
906    }
907    
908    #define CHECK_MV16_B_INTERPOL(X,Y) { \
909      if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
910        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
911      { \
912        iSAD = sad16bi( cur, \
913                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
914                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
915                            iEdgedWidth); \
916        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
917        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
918        if (iSAD < iMinSAD) \
919        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); } } \
920    }
921    
922    #define CHECK_MV16_B_INTERPOL_FOUND(X,Y) { \
923      if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
924        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
925      { \
926        iSAD = sad16bi( cur, \
927                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
928                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
929                            iEdgedWidth); \
930        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
931        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
932        if (iSAD < iMinSAD) \
933        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); iFound=0;} } \
934    }
935    
936    int32_t
937    Diamond16_InterpolMainSearch(
938                                            const uint8_t * const f_pRef,
939                                             const uint8_t * const f_pRefH,
940                                             const uint8_t * const f_pRefV,
941                                             const uint8_t * const f_pRefHV,
942    
943                                             const uint8_t * const cur,
944    
945                                            const uint8_t * const b_pRef,
946                                             const uint8_t * const b_pRefH,
947                                             const uint8_t * const b_pRefV,
948                                             const uint8_t * const b_pRefHV,
949    
950                                             const int x,
951                                             const int y,
952    
953                                       const int f_start_x,
954                                       const int f_start_y,
955                                       const int b_start_x,
956                                       const int b_start_y,
957    
958                                       int iMinSAD,
959                                       VECTOR * const f_currMV,
960                                       VECTOR * const b_currMV,
961    
962                                       const int f_center_x,
963                                       const int f_center_y,
964                                       const int b_center_x,
965                                       const int b_center_y,
966    
967                                        const int32_t f_min_dx,
968                                            const int32_t f_max_dx,
969                                            const int32_t f_min_dy,
970                                            const int32_t f_max_dy,
971    
972                                        const int32_t b_min_dx,
973                                            const int32_t b_max_dx,
974                                            const int32_t b_min_dy,
975                                            const int32_t b_max_dy,
976    
977                                            const int32_t iEdgedWidth,
978                                            const int32_t iDiamondSize,
979    
980                                            const int32_t f_iFcode,
981                                            const int32_t b_iFcode,
982    
983                                            const int32_t iQuant,
984                                            int iFound)
985    {
986    /* Do a diamond search around given starting point, return SAD of best */
987    
988            int32_t iSAD;
989    
990            VECTOR f_backupMV;
991            VECTOR b_backupMV;
992    
993            f_currMV->x = f_start_x;
994            f_currMV->y = f_start_y;
995            b_currMV->x = b_start_x;
996            b_currMV->y = b_start_y;
997    
998            do
999            {
1000                    iFound = 1;
1001    
1002                    f_backupMV = *f_currMV;
1003    
1004                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x - iDiamondSize, f_backupMV.y);
1005                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x + iDiamondSize, f_backupMV.y);
1006                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y - iDiamondSize);
1007                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y + iDiamondSize);
1008    
1009                    b_backupMV = *b_currMV;
1010    
1011                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x - iDiamondSize, b_backupMV.y);
1012                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x + iDiamondSize, b_backupMV.y);
1013                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y - iDiamondSize);
1014                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y + iDiamondSize);
1015    
1016            } while (!iFound);
1017    
1018            return iMinSAD;
1019    }
1020    
1021    /* Sorry, these MACROS really got too large... I'll turn them into function soon! */
1022    
1023    #define CHECK_MV16_DIRECT_FOUND(X,Y) \
1024            if ( (X)>=(-32) && (X)<=(31) && ((Y)>=-32) && ((Y)<=31) ) \
1025            { int k;\
1026            VECTOR mvs,b_mvs;       \
1027            iSAD = 0;\
1028            for (k = 0; k < 4; k++) {       \
1029                                            mvs.x = (int32_t) ((TRB * directmv[k].x) / TRD + (X));          \
1030                        b_mvs.x = (int32_t) (((X) == 0)                                                     \
1031                                                                                    ? ((TRB - TRD) * directmv[k].x) / TRD   \
1032                                                : mvs.x - directmv[k].x);                           \
1033                                                                                                                                                                    \
1034                        mvs.y = (int32_t) ((TRB * directmv[k].y) / TRD + (Y));              \
1035                            b_mvs.y = (int32_t) (((Y) == 0)                                                         \
1036                                                                                    ? ((TRB - TRD) * directmv[k].y) / TRD   \
1037                                                : mvs.y - directmv[k].y);                           \
1038                                                                                                                                                                    \
1039      if ( (mvs.x <= max_dx) && (mvs.x >= min_dx) \
1040        && (mvs.y <= max_dy) && (mvs.y >= min_dy)  \
1041            && (b_mvs.x <= max_dx) && (b_mvs.x >= min_dx)  \
1042        && (b_mvs.y <= max_dy) && (b_mvs.y >= min_dy) ) { \
1043                iSAD += sad8bi( cur + 8*(k&1) + 8*(k>>1)*iEdgedWidth,                                                                                                       \
1044                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \
1045                                            mvs.x, mvs.y, iEdgedWidth),                                                             \
1046                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \
1047                                            b_mvs.x, b_mvs.y, iEdgedWidth),                                                         \
1048                            iEdgedWidth); \
1049                    }       \
1050            else    \
1051                    iSAD = 65535;   \
1052            } \
1053            iSAD += calc_delta_16((X),(Y), 1, iQuant);\
1054            if (iSAD < iMinSAD) \
1055                {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iFound=0; } \
1056    }
1057    
1058    
1059    
1060    int32_t
1061    Diamond16_DirectMainSearch(
1062                                            const uint8_t * const f_pRef,
1063                                            const uint8_t * const f_pRefH,
1064                                            const uint8_t * const f_pRefV,
1065                                            const uint8_t * const f_pRefHV,
1066    
1067                                            const uint8_t * const cur,
1068    
1069                                            const uint8_t * const b_pRef,
1070                                            const uint8_t * const b_pRefH,
1071                                            const uint8_t * const b_pRefV,
1072                                            const uint8_t * const b_pRefHV,
1073    
1074                                            const int x,
1075                                            const int y,
1076    
1077                                            const int TRB,
1078                                            const int TRD,
1079    
1080                                        const int start_x,
1081                                        const int start_y,
1082    
1083                                        int iMinSAD,
1084                                        VECTOR * const currMV,
1085                                            const VECTOR * const directmv,
1086    
1087                                        const int32_t min_dx,
1088                                            const int32_t max_dx,
1089                                            const int32_t min_dy,
1090                                            const int32_t max_dy,
1091    
1092                                            const int32_t iEdgedWidth,
1093                                            const int32_t iDiamondSize,
1094    
1095                                            const int32_t iQuant,
1096                                            int iFound)
1097    {
1098    /* Do a diamond search around given starting point, return SAD of best */
1099    
1100            int32_t iSAD;
1101    
1102            VECTOR backupMV;
1103    
1104            currMV->x = start_x;
1105            currMV->y = start_y;
1106    
1107    /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1108    
1109            do
1110            {
1111                    iFound = 1;
1112    
1113                    backupMV = *currMV;
1114    
1115                    CHECK_MV16_DIRECT_FOUND(backupMV.x - iDiamondSize, backupMV.y);
1116                    CHECK_MV16_DIRECT_FOUND(backupMV.x + iDiamondSize, backupMV.y);
1117                    CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y - iDiamondSize);
1118                    CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y + iDiamondSize);
1119    
1120            } while (!iFound);
1121    
1122            return iMinSAD;
1123    }
1124    
1125    
1126    int32_t
1127    AdvDiamond8_MainSearch(const uint8_t * const pRef,
1128                                               const uint8_t * const pRefH,
1129                                               const uint8_t * const pRefV,
1130                                               const uint8_t * const pRefHV,
1131                                               const uint8_t * const cur,
1132                                               const int x,
1133                                               const int y,
1134                                               int start_x,
1135                                               int start_y,
1136                                               int iMinSAD,
1137                                               VECTOR * const currMV,
1138                                               const int center_x,
1139                                               const int center_y,
1140                                               const int32_t min_dx,
1141                                               const int32_t max_dx,
1142                                               const int32_t min_dy,
1143                                               const int32_t max_dy,
1144                                               const int32_t iEdgedWidth,
1145                                               const int32_t iDiamondSize,
1146                                               const int32_t iFcode,
1147                                               const int32_t iQuant,
1148                                               int iDirection)
1149    {
1150    
1151            int32_t iSAD;
1152    
1153    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
1154    
1155            if (iDirection) {
1156                    CHECK_MV8_CANDIDATE(start_x - iDiamondSize, start_y);
1157                    CHECK_MV8_CANDIDATE(start_x + iDiamondSize, start_y);
1158                    CHECK_MV8_CANDIDATE(start_x, start_y - iDiamondSize);
1159                    CHECK_MV8_CANDIDATE(start_x, start_y + iDiamondSize);
1160            } else {
1161                    int bDirection = 1 + 2 + 4 + 8;
1162    
1163                    do {
1164                            iDirection = 0;
1165                            if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
1166                                    CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1167    
1168                            if (bDirection & 2)
1169                                    CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1170    
1171                            if (bDirection & 4)
1172                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1173    
1174                            if (bDirection & 8)
1175                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1176    
1177                            /* now we're doing diagonal checks near our candidate */
1178    
1179                            if (iDirection)         //checking if anything found
1180                            {
1181                                    bDirection = iDirection;
1182                                    iDirection = 0;
1183                                    start_x = currMV->x;
1184                                    start_y = currMV->y;
1185                                    if (bDirection & 3)     //our candidate is left or right
1186                                    {
1187                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1188                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1189                                    } else                  // what remains here is up or down
1190                                    {
1191                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1192                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1193                                    }
1194    
1195                                    if (iDirection) {
1196                                            bDirection += iDirection;
1197                                            start_x = currMV->x;
1198                                            start_y = currMV->y;
1199                                    }
1200                            } else                          //about to quit, eh? not so fast....
1201                            {
1202                                    switch (bDirection) {
1203                                    case 2:
1204                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1205                                                                                            start_y - iDiamondSize, 2 + 4);
1206                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1207                                                                                            start_y + iDiamondSize, 2 + 8);
1208                                            break;
1209                                    case 1:
1210                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1211                                                                                            start_y - iDiamondSize, 1 + 4);
1212                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1213                                                                                            start_y + iDiamondSize, 1 + 8);
1214                                            break;
1215                                    case 2 + 4:
1216                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1217                                                                                            start_y - iDiamondSize, 1 + 4);
1218                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1219                                                                                            start_y - iDiamondSize, 2 + 4);
1220                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1221                                                                                            start_y + iDiamondSize, 2 + 8);
1222                                            break;
1223                                    case 4:
1224                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1225                                                                                            start_y - iDiamondSize, 2 + 4);
1226                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1227                                                                                            start_y - iDiamondSize, 1 + 4);
1228                                            break;
1229                                    case 8:
1230                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1231                                                                                            start_y + iDiamondSize, 2 + 8);
1232                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1233                                                                                            start_y + iDiamondSize, 1 + 8);
1234                                            break;
1235                                    case 1 + 4:
1236                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1237                                                                                            start_y + iDiamondSize, 1 + 8);
1238                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1239                                                                                            start_y - iDiamondSize, 1 + 4);
1240                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1241                                                                                            start_y - iDiamondSize, 2 + 4);
1242                                            break;
1243                                    case 2 + 8:
1244                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1245                                                                                            start_y - iDiamondSize, 1 + 4);
1246                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1247                                                                                            start_y + iDiamondSize, 1 + 8);
1248                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1249                                                                                            start_y + iDiamondSize, 2 + 8);
1250                                            break;
1251                                    case 1 + 8:
1252                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1253                                                                                            start_y - iDiamondSize, 2 + 4);
1254                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1255                                                                                            start_y + iDiamondSize, 2 + 8);
1256                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1257                                                                                            start_y + iDiamondSize, 1 + 8);
1258                                            break;
1259                                    default:                //1+2+4+8 == we didn't find anything at all
1260                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1261                                                                                            start_y - iDiamondSize, 1 + 4);
1262                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1263                                                                                            start_y + iDiamondSize, 1 + 8);
1264                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1265                                                                                            start_y - iDiamondSize, 2 + 4);
1266                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1267                                                                                            start_y + iDiamondSize, 2 + 8);
1268                                            break;
1269                                    }
1270                                    if (!(iDirection))
1271                                            break;          //ok, the end. really
1272                                    else {
1273                                            bDirection = iDirection;
1274                                            start_x = currMV->x;
1275                                            start_y = currMV->y;
1276                                    }
1277                            }
1278                    }
1279                    while (1);                              //forever
1280            }
1281            return iMinSAD;
1282    }
1283    
1284    
1285    int32_t
1286    Full8_MainSearch(const uint8_t * const pRef,
1287                                     const uint8_t * const pRefH,
1288                                     const uint8_t * const pRefV,
1289                                     const uint8_t * const pRefHV,
1290                                     const uint8_t * const cur,
1291                                     const int x,
1292                                     const int y,
1293                               const int start_x,
1294                               const int start_y,
1295                               int iMinSAD,
1296                               VECTOR * const currMV,
1297                               const int center_x,
1298                               const int center_y,
1299                                     const int32_t min_dx,
1300                                     const int32_t max_dx,
1301                                     const int32_t min_dy,
1302                                     const int32_t max_dy,
1303                                     const int32_t iEdgedWidth,
1304                                     const int32_t iDiamondSize,
1305                                     const int32_t iFcode,
1306                                     const int32_t iQuant,
1307                                     int iFound)
1308    {
1309            int32_t iSAD;
1310            int32_t dx, dy;
1311            VECTOR backupMV;
1312    
1313            backupMV.x = start_x;
1314            backupMV.y = start_y;
1315    
1316            for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
1317                    for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
1318                            NOCHECK_MV8_CANDIDATE(dx, dy);
1319    
1320            return iMinSAD;
1321    }
1322    
1323    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1324    
1325    int32_t
1326    Halfpel16_Refine(const uint8_t * const pRef,
1327                                     const uint8_t * const pRefH,
1328                                     const uint8_t * const pRefV,
1329                                     const uint8_t * const pRefHV,
1330                                     const uint8_t * const cur,
1331                                     const int x,
1332                                     const int y,
1333                                     VECTOR * const currMV,
1334                                     int32_t iMinSAD,
1335                               const int center_x,
1336                               const int center_y,
1337                                     const int32_t min_dx,
1338                                     const int32_t max_dx,
1339                                     const int32_t min_dy,
1340                                     const int32_t max_dy,
1341                                     const int32_t iFcode,
1342                                     const int32_t iQuant,
1343                                     const int32_t iEdgedWidth)
1344    {
1345    /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
1346    
1347            int32_t iSAD;
1348            VECTOR backupMV = *currMV;
1349    
1350            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y - 1);
1351            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y - 1);
1352            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y - 1);
1353            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y);
1354            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y);
1355            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y + 1);
1356            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y + 1);
1357            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y + 1);
1358    
1359            return iMinSAD;
1360    }
1361    
1362    #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1363    
1364    
1365    
1366    int32_t
1367    PMVfastSearch16(const uint8_t * const pRef,
1368                                    const uint8_t * const pRefH,
1369                                    const uint8_t * const pRefV,
1370                                    const uint8_t * const pRefHV,
1371                                    const IMAGE * const pCur,
1372                                    const int x,
1373                                    const int y,
1374                                    const int start_x,      /* start is searched first, so it should contain the most */
1375                                    const int start_y,  /* likely motion vector for this block */
1376                                    const int center_x,     /* center is from where length of MVs is measured */
1377                                    const int center_y,
1378                                    const uint32_t MotionFlags,
1379                                    const uint32_t iQuant,
1380                                    const uint32_t iFcode,
1381                                    const MBParam * const pParam,
1382                                    const MACROBLOCK * const pMBs,
1383                                    const MACROBLOCK * const prevMBs,
1384                                    VECTOR * const currMV,
1385                                    VECTOR * const currPMV)
1386    {
1387            const uint32_t iWcount = pParam->mb_width;
1388            const int32_t iWidth = pParam->width;
1389            const int32_t iHeight = pParam->height;
1390            const int32_t iEdgedWidth = pParam->edged_width;
1391    
1392            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
1393    
1394            int32_t iDiamondSize;
1395    
1396          int32_t min_dx;          int32_t min_dx;
1397          int32_t max_dx;          int32_t max_dx;
# Line 861  Line 1406 
1406          VECTOR pmv[4];          VECTOR pmv[4];
1407          int32_t psad[4];          int32_t psad[4];
1408    
1409          const MACROBLOCK * const pMB = pMBs + x + y * iWcount;          MainSearch16FuncPtr MainSearchPtr;
1410    
1411          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1412    
1413          static int32_t threshA,threshB;          int32_t threshA, threshB;
1414          int32_t bPredEq;          int32_t bPredEq;
1415          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1416    
1417  /* Get maximum range */  /* Get maximum range */
1418          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
1419                    x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
1420    
1421  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1422    
1423          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
1424          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1425          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1426          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1427          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1428          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
   
1429    
1430          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1431            //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1432            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1433    
1434          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1435                  threshA =  512;                  threshA =  512;
1436                  threshB = 1024;                  threshB = 1024;
1437            } else {
         }  
         else  
         {  
1438                  threshA = psad[0];                  threshA = psad[0];
1439                  threshB = threshA+256;                  threshB = threshA+256;
1440                  if (threshA< 512) threshA =  512;                  if (threshA < 512)
1441                  if (threshA>1024) threshA = 1024;                          threshA = 512;
1442                  if (threshB>1792) threshB = 1792;                  if (threshA > 1024)
1443                            threshA = 1024;
1444                    if (threshB > 1792)
1445                            threshB = 1792;
1446          }          }
1447    
1448          iFound=0;          iFound=0;
1449    
 /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  
    vector of the median.  
    If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2  
 */  
   
         if ((bPredEq) && (MVequal(pmv[0],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;  
   
1450  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1451     MinSAD=SAD     MinSAD=SAD
1452     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 928  Line 1454 
1454     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
1455  */  */
1456    
1457            currMV->x = start_x;
1458            currMV->y = start_y;
1459    
1460  // Prepare for main loop          if (!(MotionFlags & PMV_HALFPEL16)) {   /* This should NOT be necessary! */
   
         *currMV=pmv[0];         /* current best := prediction */  
         if (!(MotionFlags & PMV_HALFPEL16 ))  
         {       /* This should NOT be necessary! */  
1461                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1462                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
1463          }          }
1464    
1465          if (currMV->x > max_dx)          if (currMV->x > max_dx) {
         {  
1466                  currMV->x=max_dx;                  currMV->x=max_dx;
1467          }          }
1468          if (currMV->x < min_dx)          if (currMV->x < min_dx) {
         {  
1469                  currMV->x=min_dx;                  currMV->x=min_dx;
1470          }          }
1471          if (currMV->y > max_dy)          if (currMV->y > max_dy) {
         {  
1472                  currMV->y=max_dy;                  currMV->y=max_dy;
1473          }          }
1474          if (currMV->y < min_dy)          if (currMV->y < min_dy) {
         {  
1475                  currMV->y=min_dy;                  currMV->y=min_dy;
1476          }          }
1477    
1478          iMinSAD = sad16( cur,          iMinSAD =
1479                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1480                           iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1481          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1482            iMinSAD +=
1483          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
1484          {                                            (uint8_t) iFcode, iQuant);
1485    
1486            if ((iMinSAD < 256) ||
1487                    ((MVequal(*currMV, prevMB->mvs[0])) &&
1488                     ((int32_t) iMinSAD < prevMB->sad16))) {
1489                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
1490                    {
1491                            if (!MVzero(*currMV)) {
1492                                    iMinSAD += MV16_00_BIAS;
1493                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
1494                                    iMinSAD -= MV16_00_BIAS;
1495                            }
1496                    }
1497    
1498                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1499                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
# Line 969  Line 1501 
1501                          goto PMVfast16_Terminate_with_Refine;                          goto PMVfast16_Terminate_with_Refine;
1502          }          }
1503    
1504    
1505    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1506       vector of the median.
1507       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1508    */
1509    
1510            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[0])))
1511                    iFound = 2;
1512    
1513    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1514       Otherwise select large Diamond Search.
1515    */
1516    
1517            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
1518                    iDiamondSize = 1;               // halfpel!
1519            else
1520                    iDiamondSize = 2;               // halfpel!
1521    
1522            if (!(MotionFlags & PMV_HALFPELDIAMOND16))
1523                    iDiamondSize *= 2;
1524    
1525  /*  /*
1526     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
1527     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
# Line 978  Line 1531 
1531    
1532  // (0,0) is always possible  // (0,0) is always possible
1533    
1534            if (!MVzero(pmv[0]))
1535          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1536    
1537  // previous frame MV is always possible  // previous frame MV is always possible
1538    
1539            if (!MVzero(prevMB->mvs[0]))
1540                    if (!MVequal(prevMB->mvs[0], pmv[0]))
1541          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1542    
1543  // left neighbour, if allowed  // left neighbour, if allowed
1544          if (x != 0)  
1545          {          if (!MVzero(pmv[1]))
1546                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!MVequal(pmv[1], prevMB->mvs[0]))
1547                  {       pmv[1].x = EVEN(pmv[1].x);                          if (!MVequal(pmv[1], pmv[0])) {
1548                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1549                                            pmv[1].x = EVEN(pmv[1].x);
1550                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1551                  }                  }
1552    
1553                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1554          }          }
   
1555  // top neighbour, if allowed  // top neighbour, if allowed
1556          if (y != 0)          if (!MVzero(pmv[2]))
1557          {                  if (!MVequal(pmv[2], prevMB->mvs[0]))
1558                  if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!MVequal(pmv[2], pmv[0]))
1559                  {       pmv[2].x = EVEN(pmv[2].x);                                  if (!MVequal(pmv[2], pmv[1])) {
1560                                            if (!(MotionFlags & PMV_HALFPEL16)) {
1561                                                    pmv[2].x = EVEN(pmv[2].x);
1562                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
1563                  }                  }
1564                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1565    
1566  // top right neighbour, if allowed  // top right neighbour, if allowed
1567                  if ((uint32_t)x != (iWcount-1))                                          if (!MVzero(pmv[3]))
1568                  {                                                  if (!MVequal(pmv[3], prevMB->mvs[0]))
1569                          if (!(MotionFlags & PMV_HALFPEL16 ))                                                          if (!MVequal(pmv[3], pmv[0]))
1570                          {       pmv[3].x = EVEN(pmv[3].x);                                                                  if (!MVequal(pmv[3], pmv[1]))
1571                                                                            if (!MVequal(pmv[3], pmv[2])) {
1572                                                                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1573                                                                                            pmv[3].x = EVEN(pmv[3].x);
1574                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1575                          }                          }
1576                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                  CHECK_MV16_CANDIDATE(pmv[3].x,
1577                                                                                                                             pmv[3].y);
1578                  }                  }
1579          }          }
1580    
1581          if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96)*/ )          if ((MVzero(*currMV)) &&
1582                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1583                  iMinSAD -= MV16_00_BIAS;                  iMinSAD -= MV16_00_BIAS;
1584    
1585    
# Line 1021  Line 1587 
1587     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
1588  */  */
1589    
1590          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ((iMinSAD <= threshA) ||
1591          {                  (MVequal(*currMV, prevMB->mvs[0]) &&
1592                     ((int32_t) iMinSAD < prevMB->sad16))) {
1593                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1594                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
1595                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1040  Line 1607 
1607     Refine by using small diamond and goto step 10.     Refine by using small diamond and goto step 10.
1608  */  */
1609    
1610            if (MotionFlags & PMV_USESQUARES16)
1611                    MainSearchPtr = Square16_MainSearch;
1612            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
1613                    MainSearchPtr = AdvDiamond16_MainSearch;
1614            else
1615                    MainSearchPtr = Diamond16_MainSearch;
1616    
1617          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1618    
1619    
1620  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1621          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1622                                            x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1623                                            currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->x, currMV->y, iMinSAD, &newMV, center_x, center_y,
1624                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dx, max_dx,
1625                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1626                                                      iQuant, iFound);
1627    
1628          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1629                  *currMV = newMV;                  *currMV = newMV;
1630                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1631          }          }
1632    
1633          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
1634  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1635    
1636                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1637                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1638                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1639                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    center_x, center_y, iMinSAD, &newMV, center_x, center_y,
1640                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1641                                                                      iDiamondSize, iFcode, iQuant, iFound);
1642    
1643                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1644                          *currMV = newMV;                          *currMV = newMV;
1645                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1646                  }                  }
1647                  }                  }
1648    
1649                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1650                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1651                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1652                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y,
1653                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy,
1654                                                                      iEdgedWidth, iDiamondSize, iFcode,
1655                                                                      iQuant, iFound);
1656    
1657                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1658                          *currMV = newMV;                          *currMV = newMV;
1659                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1660                  }                  }
# Line 1091  Line 1667 
1667    
1668  PMVfast16_Terminate_with_Refine:  PMVfast16_Terminate_with_Refine:
1669          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1670                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1671                                    x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1672                                    currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1673                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1674    
1675  PMVfast16_Terminate_without_Refine:  PMVfast16_Terminate_without_Refine:
1676          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
1677          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
1678          return iMinSAD;          return iMinSAD;
1679  }  }
1680    
# Line 1107  Line 1683 
1683    
1684    
1685    
1686  int32_t Diamond8_MainSearch(  int32_t
1687          const uint8_t * const pRef,  Diamond8_MainSearch(const uint8_t * const pRef,
1688          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1689          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1690          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1691          const uint8_t * const cur,          const uint8_t * const cur,
1692          const int x, const int y,                                          const int x,
1693          int32_t startx, int32_t starty,                                          const int y,
1694                                            int32_t start_x,
1695                                            int32_t start_y,
1696          int32_t iMinSAD,          int32_t iMinSAD,
1697          VECTOR * const currMV,          VECTOR * const currMV,
1698          const VECTOR * const pmv,                                     const int center_x,
1699          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
1700          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
1701                                            const int32_t max_dx,
1702                                            const int32_t min_dy,
1703                                            const int32_t max_dy,
1704          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
1705          const int32_t iDiamondSize,          const int32_t iDiamondSize,
1706          const int32_t iFcode,          const int32_t iFcode,
# Line 1129  Line 1710 
1710  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
1711    
1712          int32_t iDirection=0;          int32_t iDirection=0;
1713            int32_t iDirectionBackup;
1714          int32_t iSAD;          int32_t iSAD;
1715          VECTOR backupMV;          VECTOR backupMV;
1716          backupMV.x = startx;  
1717          backupMV.y = starty;          backupMV.x = start_x;
1718            backupMV.y = start_y;
1719    
1720  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1721    
# Line 1141  Line 1724 
1724          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
1725          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1726    
1727          if (iDirection)          if (iDirection) {
1728                  while (!iFound)                  while (!iFound) {
                 {  
1729                          iFound = 1;                          iFound = 1;
1730                          backupMV=*currMV;       // since iDirection!=0, this is well defined!                          backupMV=*currMV;       // since iDirection!=0, this is well defined!
1731                            iDirectionBackup = iDirection;
1732    
1733                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
1734                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1735                          if ( iDirection != 1)                                                                                    backupMV.y, 1);
1736                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
1737                          if ( iDirection != 4)                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1738                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                    backupMV.y, 2);
1739                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
1740                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1741                                                                                      backupMV.y - iDiamondSize, 3);
1742                            if (iDirectionBackup != 3)
1743                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1744                                                                                      backupMV.y + iDiamondSize, 4);
1745                  }                  }
1746          else          } else {
1747                    currMV->x = start_x;
1748                    currMV->y = start_y;
1749            }
1750            return iMinSAD;
1751    }
1752    
1753    
1754    
1755    
1756    int32_t
1757    Square8_MainSearch(const uint8_t * const pRef,
1758                                            const uint8_t * const pRefH,
1759                                            const uint8_t * const pRefV,
1760                                            const uint8_t * const pRefHV,
1761                                            const uint8_t * const cur,
1762                                            const int x,
1763                                            const int y,
1764                                            int32_t start_x,
1765                                            int32_t start_y,
1766                                            int32_t iMinSAD,
1767                                            VECTOR * const currMV,
1768                                       const int center_x,
1769                                       const int center_y,
1770                                            const int32_t min_dx,
1771                                            const int32_t max_dx,
1772                                            const int32_t min_dy,
1773                                            const int32_t max_dy,
1774                                            const int32_t iEdgedWidth,
1775                                            const int32_t iDiamondSize,
1776                                            const int32_t iFcode,
1777                                            const int32_t iQuant,
1778                                            int iFound)
1779          {          {
1780                  currMV->x = startx;  /* Do a square search around given starting point, return SAD of best */
1781                  currMV->y = starty;  
1782            int32_t iDirection = 0;
1783            int32_t iSAD;
1784            VECTOR backupMV;
1785    
1786            backupMV.x = start_x;
1787            backupMV.y = start_y;
1788    
1789    /* It's one search with full square pattern, and new parts for all following diamonds */
1790    
1791    /*   new direction are extra, so 1-4 is normal diamond
1792          537
1793          1*2
1794          648
1795    */
1796    
1797            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1798            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1799            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1800            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1801    
1802            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1803                                                             backupMV.y - iDiamondSize, 5);
1804            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1805                                                             backupMV.y + iDiamondSize, 6);
1806            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1807                                                             backupMV.y - iDiamondSize, 7);
1808            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1809                                                             backupMV.y + iDiamondSize, 8);
1810    
1811    
1812            if (iDirection) {
1813                    while (!iFound) {
1814                            iFound = 1;
1815                            backupMV = *currMV;
1816    
1817                            switch (iDirection) {
1818                            case 1:
1819                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1820                                                                                       backupMV.y, 1);
1821                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1822                                                                                     backupMV.y - iDiamondSize, 5);
1823                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1824                                                                                     backupMV.y - iDiamondSize, 7);
1825                                    break;
1826                            case 2:
1827                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1828                                                                                     2);
1829                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1830                                                                                     backupMV.y + iDiamondSize, 6);
1831                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1832                                                                                     backupMV.y + iDiamondSize, 8);
1833                                    break;
1834    
1835                            case 3:
1836                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1837                                                                                     4);
1838                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1839                                                                                     backupMV.y - iDiamondSize, 7);
1840                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1841                                                                                     backupMV.y + iDiamondSize, 8);
1842                                    break;
1843    
1844                            case 4:
1845                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1846                                                                                     3);
1847                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1848                                                                                     backupMV.y - iDiamondSize, 5);
1849                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1850                                                                                     backupMV.y + iDiamondSize, 6);
1851                                    break;
1852    
1853                            case 5:
1854                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1855                                                                                     1);
1856                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1857                                                                                     3);
1858                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1859                                                                                     backupMV.y - iDiamondSize, 5);
1860                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1861                                                                                     backupMV.y + iDiamondSize, 6);
1862                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1863                                                                                     backupMV.y - iDiamondSize, 7);
1864                                    break;
1865    
1866                            case 6:
1867                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1868                                                                                     2);
1869                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1870                                                                                     3);
1871    
1872                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1873                                                                                     backupMV.y - iDiamondSize, 5);
1874                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1875                                                                                     backupMV.y + iDiamondSize, 6);
1876                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1877                                                                                     backupMV.y + iDiamondSize, 8);
1878    
1879                                    break;
1880    
1881                            case 7:
1882                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1883                                                                                       backupMV.y, 1);
1884                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1885                                                                                     4);
1886                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1887                                                                                     backupMV.y - iDiamondSize, 5);
1888                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1889                                                                                     backupMV.y - iDiamondSize, 7);
1890                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1891                                                                                     backupMV.y + iDiamondSize, 8);
1892                                    break;
1893    
1894                            case 8:
1895                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1896                                                                                     2);
1897                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1898                                                                                     4);
1899                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1900                                                                                     backupMV.y + iDiamondSize, 6);
1901                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1902                                                                                     backupMV.y - iDiamondSize, 7);
1903                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1904                                                                                     backupMV.y + iDiamondSize, 8);
1905                                    break;
1906                            default:
1907                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1908                                                                                     1);
1909                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1910                                                                                     2);
1911                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1912                                                                                     3);
1913                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1914                                                                                     4);
1915    
1916                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1917                                                                                     backupMV.y - iDiamondSize, 5);
1918                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1919                                                                                     backupMV.y + iDiamondSize, 6);
1920                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1921                                                                                     backupMV.y - iDiamondSize, 7);
1922                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1923                                                                                     backupMV.y + iDiamondSize, 8);
1924                                    break;
1925                            }
1926                    }
1927            } else {
1928                    currMV->x = start_x;
1929                    currMV->y = start_y;
1930          }          }
1931          return iMinSAD;          return iMinSAD;
1932  }  }
1933    
1934  int32_t Halfpel8_Refine(  
1935          const uint8_t * const pRef,  
1936    
1937    
1938    int32_t
1939    Halfpel8_Refine_c(const uint8_t * const pRef,
1940          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1941          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1942          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1943          const uint8_t * const cur,          const uint8_t * const cur,
1944          const int x, const int y,                                  const int x,
1945                                    const int y,
1946          VECTOR * const currMV,          VECTOR * const currMV,
1947          int32_t iMinSAD,          int32_t iMinSAD,
1948          const VECTOR * const pmv,                             const int center_x,
1949          const int32_t min_dx, const int32_t max_dx,                             const int center_y,
1950          const int32_t min_dy, const int32_t max_dy,                                  const int32_t min_dx,
1951                                    const int32_t max_dx,
1952                                    const int32_t min_dy,
1953                                    const int32_t max_dy,
1954          const int32_t iFcode,          const int32_t iFcode,
1955          const int32_t iQuant,          const int32_t iQuant,
1956          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 1200  Line 1975 
1975    
1976  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1977    
1978  int32_t PMVfastSearch8(  int32_t
1979                                          const uint8_t * const pRef,  PMVfastSearch8(const uint8_t * const pRef,
1980                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1981                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1982                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1983                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1984                                          const int x, const int y,                             const int x,
1985                                          const int start_x, const int start_y,                             const int y,
1986                               const int start_x,
1987                               const int start_y,
1988                                    const int center_x,
1989                                    const int center_y,
1990                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1991                                          const uint32_t iQuant,                                          const uint32_t iQuant,
1992                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1235  Line 2014 
2014          int32_t psad[4];          int32_t psad[4];
2015          VECTOR newMV;          VECTOR newMV;
2016          VECTOR backupMV;          VECTOR backupMV;
2017            VECTOR startMV;
2018    
2019          const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2020          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
2021    
2022          static int32_t threshA,threshB;           int32_t threshA, threshB;
2023          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
2024          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
2025    
2026          int32_t iSubBlock = ((y&1)<<1) + (x&1);          int32_t iSubBlock = (y & 1) + (y & 1) + (x & 1);
2027    
2028            MainSearch8FuncPtr MainSearchPtr;
2029    
2030            /* Init variables */
2031            startMV.x = start_x;
2032            startMV.y = start_y;
2033    
2034  /* Get maximum range */  /* Get maximum range */
2035          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,
2036                    x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2037    
2038          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
2039          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2040          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
2041          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
2042          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
2043          }               /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          }
   
2044    
2045          bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
2046            //bPredEq = get_pmvdata(pMBs, (x >> 1), (y >> 1), iWcount, iSubBlock, pmv, psad);
2047            bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
2048    
2049          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
2050                  threshA =  512/4;                  threshA =  512/4;
2051                  threshB = 1024/4;                  threshB = 1024/4;
2052    
2053          }          } else {
2054          else                  threshA = psad[0] / 4;  /* good estimate? */
         {  
                 threshA = psad[0]/4;                    /* good estimate */  
2055                  threshB = threshA+256/4;                  threshB = threshA+256/4;
2056                  if (threshA< 512/4) threshA =  512/4;                  if (threshA < 512 / 4)
2057                  if (threshA>1024/4) threshA = 1024/4;                          threshA = 512 / 4;
2058                  if (threshB>1792/4) threshB = 1792/4;                  if (threshA > 1024 / 4)
2059          }                          threshA = 1024 / 4;
2060                    if (threshB > 1792 / 4)
2061          iFound=0;                          threshB = 1792 / 4;
2062            }
 /* 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!  
2063    
2064          if (!(MotionFlags & PMV_HALFPELDIAMOND8) )          iFound = 0;
                 iDiamondSize*=2;  
2065    
2066  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2067     MinSAD=SAD     MinSAD=SAD
# Line 1306  Line 2073 
2073    
2074  // Prepare for main loop  // Prepare for main loop
2075    
2076          currMV->x=start_x;              /* start with mv16 */    if (MotionFlags & PMV_USESQUARES8)
2077          currMV->y=start_y;        MainSearchPtr = Square8_MainSearch;
2078      else
2079    
2080          iMinSAD = sad8( cur,          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2081                          get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  MainSearchPtr = AdvDiamond8_MainSearch;
2082                          iEdgedWidth);          else
2083          iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode, iQuant);                  MainSearchPtr = Diamond8_MainSearch;
2084    
2085          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock])) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )  
2086          {          *currMV = startMV;
2087    
2088            iMinSAD =
2089                    sad8(cur,
2090                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2091                                                    iEdgedWidth), iEdgedWidth);
2092            iMinSAD +=
2093                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2094                                             (uint8_t) iFcode, iQuant);
2095    
2096            if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))
2097                                                                    && ((int32_t) iMinSAD <
2098                                                                            prevMB->sad8[iSubBlock]))) {
2099                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2100                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2101                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
2102                          goto PMVfast8_Terminate_with_Refine;                          goto PMVfast8_Terminate_with_Refine;
2103          }          }
2104    
2105    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2106       vector of the median.
2107       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2108    */
2109    
2110            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[iSubBlock])))
2111                    iFound = 2;
2112    
2113    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2114       Otherwise select large Diamond Search.
2115    */
2116    
2117            if ((!MVzero(pmv[0])) || (threshB < 1536 / 4) || (bPredEq))
2118                    iDiamondSize = 1;               // 1 halfpel!
2119            else
2120                    iDiamondSize = 2;               // 2 halfpel = 1 full pixel!
2121    
2122            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2123                    iDiamondSize *= 2;
2124    
2125    
2126  /*  /*
2127     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
# Line 1330  Line 2130 
2130     If MV is (0,0) subtract offset.     If MV is (0,0) subtract offset.
2131  */  */
2132    
2133  // the prediction might be even better than mv16  // the median prediction might be even better than mv16
         CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);  
2134    
2135  // (0,0) is always possible          if (!MVequal(pmv[0], startMV))
2136                    CHECK_MV8_CANDIDATE(center_x, center_y);
2137    
2138    // (0,0) if needed
2139            if (!MVzero(pmv[0]))
2140                    if (!MVzero(startMV))
2141          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
2142    
2143  // previous frame MV is always possible  // previous frame MV if needed
2144          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);          if (!MVzero(prevMB->mvs[iSubBlock]))
2145                    if (!MVequal(prevMB->mvs[iSubBlock], startMV))
2146                            if (!MVequal(prevMB->mvs[iSubBlock], pmv[0]))
2147                                    CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,
2148                                                                            prevMB->mvs[iSubBlock].y);
2149    
2150            if ((iMinSAD <= threshA) ||
2151                    (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2152                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2153                    if (MotionFlags & PMV_QUICKSTOP16)
2154                            goto PMVfast8_Terminate_without_Refine;
2155                    if (MotionFlags & PMV_EARLYSTOP16)
2156                            goto PMVfast8_Terminate_with_Refine;
2157            }
2158    
2159  // left neighbour, if allowed  // left neighbour, if allowed and needed
2160          if (psad[1] != MV_MAX_ERROR)          if (!MVzero(pmv[1]))
2161          {                  if (!MVequal(pmv[1], startMV))
2162                  if (!(MotionFlags & PMV_HALFPEL8 ))                          if (!MVequal(pmv[1], prevMB->mvs[iSubBlock]))
2163                  {       pmv[1].x = EVEN(pmv[1].x);                                  if (!MVequal(pmv[1], pmv[0])) {
2164                                            if (!(MotionFlags & PMV_HALFPEL8)) {
2165                                                    pmv[1].x = EVEN(pmv[1].x);
2166                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
2167                  }                  }
2168                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
2169          }          }
2170    // top neighbour, if allowed and needed
2171  // top neighbour, if allowed          if (!MVzero(pmv[2]))
2172          if (psad[2] != MV_MAX_ERROR)                  if (!MVequal(pmv[2], startMV))
2173          {                          if (!MVequal(pmv[2], prevMB->mvs[iSubBlock]))
2174                  if (!(MotionFlags & PMV_HALFPEL8 ))                                  if (!MVequal(pmv[2], pmv[0]))
2175                  {       pmv[2].x = EVEN(pmv[2].x);                                          if (!MVequal(pmv[2], pmv[1])) {
2176                                                    if (!(MotionFlags & PMV_HALFPEL8)) {
2177                                                            pmv[2].x = EVEN(pmv[2].x);
2178                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
2179                  }                  }
2180                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
2181    
2182  // top right neighbour, if allowed  // top right neighbour, if allowed and needed
2183                  if (psad[3] != MV_MAX_ERROR)                                                  if (!MVzero(pmv[3]))
2184                  {                                                          if (!MVequal(pmv[3], startMV))
2185                          if (!(MotionFlags & PMV_HALFPEL8 ))                                                                  if (!MVequal(pmv[3], prevMB->mvs[iSubBlock]))
2186                          {       pmv[3].x = EVEN(pmv[3].x);                                                                          if (!MVequal(pmv[3], pmv[0]))
2187                                                                                    if (!MVequal(pmv[3], pmv[1]))
2188                                                                                            if (!MVequal(pmv[3], pmv[2])) {
2189                                                                                                    if (!
2190                                                                                                            (MotionFlags &
2191                                                                                                             PMV_HALFPEL8)) {
2192                                                                                                            pmv[3].x = EVEN(pmv[3].x);
2193                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
2194                          }                          }
2195                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                                  CHECK_MV8_CANDIDATE(pmv[3].x,
2196                                                                                                                                            pmv[3].y);
2197                  }                  }
2198          }          }
2199    
2200          if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )          if ((MVzero(*currMV)) &&
2201                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2202                  iMinSAD -= MV8_00_BIAS;                  iMinSAD -= MV8_00_BIAS;
2203    
2204    
# Line 1377  Line 2206 
2206     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
2207  */  */
2208    
2209          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
2210          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2211                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2212                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2213                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2214                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1398  Line 2228 
2228          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2229    
2230  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2231          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2232                                           x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2233                                           currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2234                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2235                                                      iQuant, iFound);
2236    
2237          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2238                  *currMV = newMV;                  *currMV = newMV;
2239                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2240          }          }
2241    
2242          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2243  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
2244    
2245                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2246                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2247                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2248                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2249                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2250                                                                      iDiamondSize, iFcode, iQuant, iFound);
2251    
2252                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2253                          *currMV = newMV;                          *currMV = newMV;
2254                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2255                  }                  }
2256                  }                  }
2257    
2258                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2259                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2260                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2261                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2262                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2263                                                                      iQuant, iFound);
2264    
2265                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2266                          *currMV = newMV;                          *currMV = newMV;
2267                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2268                  }                  }
# Line 1446  Line 2275 
2275    
2276  PMVfast8_Terminate_with_Refine:  PMVfast8_Terminate_with_Refine:
2277          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2278                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2279                                                   x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2280                                                   currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2281                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2282    
2283    
2284  PMVfast8_Terminate_without_Refine:  PMVfast8_Terminate_without_Refine:
2285          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2286          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2287    
2288          return iMinSAD;          return iMinSAD;
2289  }  }
2290    
2291  int32_t EPZSSearch16(  int32_t
2292                                          const uint8_t * const pRef,  EPZSSearch16(const uint8_t * const pRef,
2293                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2294                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2295                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2296                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2297                                          const int x, const int y,                           const int x,
2298                             const int y,
2299                            const int start_x,
2300                            const int start_y,
2301                            const int center_x,
2302                            const int center_y,
2303                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2304                                          const uint32_t iQuant,                                          const uint32_t iQuant,
2305                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1496  Line 2330 
2330          int32_t psad[8];          int32_t psad[8];
2331    
2332          static MACROBLOCK * oldMBs = NULL;          static MACROBLOCK * oldMBs = NULL;
2333          const MACROBLOCK * const pMB = pMBs + x + y * iWcount;  
2334    //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
2335          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
2336          MACROBLOCK * oldMB = NULL;          MACROBLOCK * oldMB = NULL;
2337    
2338          static int32_t thresh2;           int32_t thresh2;
2339          int32_t bPredEq;          int32_t bPredEq;
2340          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2341    
2342          MainSearch16FuncPtr EPZSMainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
2343    
2344          if (oldMBs == NULL)          if (oldMBs == NULL) {
2345          {       oldMBs = (MACROBLOCK*) calloc(iWcount*iHcount,sizeof(MACROBLOCK));                  oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
2346  //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));  //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
2347          }          }
2348          oldMB = oldMBs + x + y * iWcount;          oldMB = oldMBs + x + y * iWcount;
2349    
2350  /* Get maximum range */  /* Get maximum range */
2351          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2352                          x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
2353    
2354          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
2355          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2356            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2357            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2358            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2359          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2360            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2361          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
2362            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2363    
2364  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2365          MinSAD=SAD          MinSAD=SAD
# Line 1534  Line 2370 
2370    
2371  // Prepare for main loop  // Prepare for main loop
2372    
2373          *currMV=pmv[0];         /* current best := median prediction */          currMV->x = start_x;
2374          if (!(MotionFlags & PMV_HALFPEL16))          currMV->y = start_y;
2375          {  
2376            if (!(MotionFlags & PMV_HALFPEL16)) {
2377                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2378                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2379          }          }
# Line 1552  Line 2389 
2389    
2390  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2391    
2392          iMinSAD = sad16( cur,          iMinSAD =
2393                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
2394                  iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2395          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2396            iMinSAD +=
2397                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2398                                              (uint8_t) iFcode, iQuant);
2399    
2400  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2401          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV, prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ((iMinSAD < 256) ||
2402                  {                  ((MVequal(*currMV, prevMB->mvs[0])) &&
2403                     ((int32_t) iMinSAD < prevMB->sad16))) {
2404                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2405                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2406                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1574  Line 2415 
2415  // set threshhold based on Min of Prediction and SAD of collocated block  // set threshhold based on Min of Prediction and SAD of collocated block
2416  // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want  // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
2417    
2418          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
2419                  thresh2 =  512;                  thresh2 =  512;
2420          }          } else {
         else  
         {  
2421  /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */  /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */
2422    
2423                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
# Line 1591  Line 2429 
2429    
2430    
2431  // left neighbour, if allowed  // left neighbour, if allowed
2432          if (x != 0)          if (x != 0) {
2433          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2434                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2435                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2436                  }                  }
2437                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
2438          }          }
   
2439  // top neighbour, if allowed  // top neighbour, if allowed
2440          if (y != 0)          if (y != 0) {
2441          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2442                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2443                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2444                  }                  }
2445                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
2446    
2447  // top right neighbour, if allowed  // top right neighbour, if allowed
2448                  if ((uint32_t)x != (iWcount-1))                  if ((uint32_t) x != (iWcount - 1)) {
2449                  {                          if (!(MotionFlags & PMV_HALFPEL16)) {
2450                          if (!(MotionFlags & PMV_HALFPEL16 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2451                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2452                          }                          }
2453                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
# Line 1625  Line 2459 
2459  */  */
2460    
2461          if ( (iMinSAD <= thresh2)          if ( (iMinSAD <= thresh2)
2462                  || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )                  || (MVequal(*currMV, prevMB->mvs[0]) &&
2463                  {                          ((int32_t) iMinSAD <= prevMB->sad16))) {
2464                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2465                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2466                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1647  Line 2481 
2481    
2482  // top neighbour  // top neighbour
2483          if (y != 0)          if (y != 0)
2484                  CHECK_MV16_CANDIDATE((prevMB-iWcount)->mvs[0].x,(prevMB-iWcount)->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,
2485                                                             (prevMB - iWcount)->mvs[0].y);
2486    
2487  // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs  // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
2488    
# Line 1656  Line 2491 
2491    
2492  // bottom neighbour, dito  // bottom neighbour, dito
2493          if ((uint32_t)y != iHcount-1)          if ((uint32_t)y != iHcount-1)
2494                  CHECK_MV16_CANDIDATE((prevMB+iWcount)->mvs[0].x,(prevMB+iWcount)->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,
2495                                                             (prevMB + iWcount)->mvs[0].y);
2496    
2497  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
2498          if (iMinSAD <= thresh2)          if (iMinSAD <= thresh2) {
                 {  
2499                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2500                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2501                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1669  Line 2504 
2504    
2505  /************ (if Diamond Search)  **************/  /************ (if Diamond Search)  **************/
2506    
2507          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2508    
2509            if (MotionFlags & PMV_USESQUARES16)
2510                    MainSearchPtr = Square16_MainSearch;
2511            else
2512             if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2513                    MainSearchPtr = AdvDiamond16_MainSearch;
2514            else
2515                    MainSearchPtr = Diamond16_MainSearch;
2516    
2517    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2518    
2519            iSAD =
2520                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2521                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2522                                                      min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2523    
2524            if (iSAD < iMinSAD) {
2525                    *currMV = newMV;
2526                    iMinSAD = iSAD;
2527            }
2528    
2529    
2530            if (MotionFlags & PMV_EXTSEARCH16) {
2531    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2532    
2533                    if (!(MVequal(pmv[0], backupMV))) {
2534                            iSAD =
2535                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2536                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2537                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2538                                                                      2, iFcode, iQuant, 0);
2539                    }
2540    
2541                    if (iSAD < iMinSAD) {
2542                            *currMV = newMV;
2543                            iMinSAD = iSAD;
2544                    }
2545    
2546                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2547                            iSAD =
2548                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2549                                                                      iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2550                                                                      max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2551    
2552                            if (iSAD < iMinSAD) {
2553                                    *currMV = newMV;
2554                                    iMinSAD = iSAD;
2555                            }
2556                    }
2557            }
2558    
2559    /***************        Choose best MV found     **************/
2560    
2561      EPZS16_Terminate_with_Refine:
2562            if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
2563                    iMinSAD =
2564                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2565                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2566                                                             iFcode, iQuant, iEdgedWidth);
2567    
2568      EPZS16_Terminate_without_Refine:
2569    
2570            *oldMB = *prevMB;
2571    
2572            currPMV->x = currMV->x - center_x;
2573            currPMV->y = currMV->y - center_y;
2574            return iMinSAD;
2575    }
2576    
2577    
2578    int32_t
2579    EPZSSearch8(const uint8_t * const pRef,
2580                            const uint8_t * const pRefH,
2581                            const uint8_t * const pRefV,
2582                            const uint8_t * const pRefHV,
2583                            const IMAGE * const pCur,
2584                            const int x,
2585                            const int y,
2586                            const int start_x,
2587                            const int start_y,
2588                            const int center_x,
2589                            const int center_y,
2590                            const uint32_t MotionFlags,
2591                            const uint32_t iQuant,
2592                            const uint32_t iFcode,
2593                            const MBParam * const pParam,
2594                            const MACROBLOCK * const pMBs,
2595                            const MACROBLOCK * const prevMBs,
2596                            VECTOR * const currMV,
2597                            VECTOR * const currPMV)
2598    {
2599    /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
2600    
2601            const uint32_t iWcount = pParam->mb_width;
2602            const int32_t iWidth = pParam->width;
2603            const int32_t iHeight = pParam->height;
2604            const int32_t iEdgedWidth = pParam->edged_width;
2605    
2606            const uint8_t *cur = pCur->y + x * 8 + y * 8 * iEdgedWidth;
2607    
2608            int32_t iDiamondSize = 1;
2609    
2610            int32_t min_dx;
2611            int32_t max_dx;
2612            int32_t min_dy;
2613            int32_t max_dy;
2614    
2615            VECTOR newMV;
2616            VECTOR backupMV;
2617    
2618            VECTOR pmv[4];
2619            int32_t psad[8];
2620    
2621            const int32_t iSubBlock = ((y & 1) << 1) + (x & 1);
2622    
2623    //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2624            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
2625    
2626            int32_t bPredEq;
2627            int32_t iMinSAD, iSAD = 9999;
2628    
2629            MainSearch8FuncPtr MainSearchPtr;
2630    
2631    /* Get maximum range */
2632            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2633                              iFcode);
2634    
2635    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2636    
2637            if (!(MotionFlags & PMV_HALFPEL8)) {
2638                    min_dx = EVEN(min_dx);
2639                    max_dx = EVEN(max_dx);
2640                    min_dy = EVEN(min_dy);
2641                    max_dy = EVEN(max_dy);
2642            }
2643            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2644            //bPredEq = get_pmvdata(pMBs, x >> 1, y >> 1, iWcount, iSubBlock, pmv[0].x, pmv[0].y, psad);
2645            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2646    
2647    
2648    /* Step 4: Calculate SAD around the Median prediction.
2649            MinSAD=SAD
2650            If Motion Vector equal to Previous frame motion vector
2651                    and MinSAD<PrevFrmSAD goto Step 10.
2652            If SAD<=256 goto Step 10.
2653    */
2654    
2655    // Prepare for main loop
2656    
2657    
2658            if (!(MotionFlags & PMV_HALFPEL8)) {
2659                    currMV->x = EVEN(currMV->x);
2660                    currMV->y = EVEN(currMV->y);
2661            }
2662    
2663            if (currMV->x > max_dx)
2664                    currMV->x = max_dx;
2665            if (currMV->x < min_dx)
2666                    currMV->x = min_dx;
2667            if (currMV->y > max_dy)
2668                    currMV->y = max_dy;
2669            if (currMV->y < min_dy)
2670                    currMV->y = min_dy;
2671    
2672    /***************** This is predictor SET A: only median prediction ******************/
2673    
2674    
2675            iMinSAD =
2676                    sad8(cur,
2677                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2678                                                    iEdgedWidth), iEdgedWidth);
2679            iMinSAD +=
2680                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2681                                             (uint8_t) iFcode, iQuant);
2682    
2683    
2684    // thresh1 is fixed to 256
2685            if (iMinSAD < 256 / 4) {
2686                    if (MotionFlags & PMV_QUICKSTOP8)
2687                            goto EPZS8_Terminate_without_Refine;
2688                    if (MotionFlags & PMV_EARLYSTOP8)
2689                            goto EPZS8_Terminate_with_Refine;
2690            }
2691    
2692    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2693    
2694    
2695    // MV=(0,0) is often a good choice
2696            CHECK_MV8_ZERO;
2697    
2698    // previous frame MV
2699            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x, prevMB->mvs[iSubBlock].y);
2700    
2701    // left neighbour, if allowed
2702            if (psad[1] != MV_MAX_ERROR) {
2703                    if (!(MotionFlags & PMV_HALFPEL8)) {
2704                            pmv[1].x = EVEN(pmv[1].x);
2705                            pmv[1].y = EVEN(pmv[1].y);
2706                    }
2707                    CHECK_MV8_CANDIDATE(pmv[1].x, pmv[1].y);
2708            }
2709    // top neighbour, if allowed
2710            if (psad[2] != MV_MAX_ERROR) {
2711                    if (!(MotionFlags & PMV_HALFPEL8)) {
2712                            pmv[2].x = EVEN(pmv[2].x);
2713                            pmv[2].y = EVEN(pmv[2].y);
2714                    }
2715                    CHECK_MV8_CANDIDATE(pmv[2].x, pmv[2].y);
2716    
2717    // top right neighbour, if allowed
2718                    if (psad[3] != MV_MAX_ERROR) {
2719                            if (!(MotionFlags & PMV_HALFPEL8)) {
2720                                    pmv[3].x = EVEN(pmv[3].x);
2721                                    pmv[3].y = EVEN(pmv[3].y);
2722                            }
2723                            CHECK_MV8_CANDIDATE(pmv[3].x, pmv[3].y);
2724                    }
2725            }
2726    
2727    /*  // this bias is zero anyway, at the moment!
2728    
2729            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
2730                    iMinSAD -= MV8_00_BIAS;
2731    
2732    */
2733    
2734    /* Terminate if MinSAD <= T_2
2735       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
2736    */
2737    
2738            if (iMinSAD < 512 / 4) {        /* T_2 == 512/4 hardcoded */
2739                    if (MotionFlags & PMV_QUICKSTOP8)
2740                            goto EPZS8_Terminate_without_Refine;
2741                    if (MotionFlags & PMV_EARLYSTOP8)
2742                            goto EPZS8_Terminate_with_Refine;
2743            }
2744    
2745    /************ (Diamond Search)  **************/
2746    
2747            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2748    
2749            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2750                    iDiamondSize *= 2;
2751    
2752    /* default: use best prediction as starting point for one call of EPZS_MainSearch */
2753    
2754    // there is no EPZS^2 for inter4v at the moment
2755    
2756  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */    if (MotionFlags & PMV_USESQUARES8)
2757          MainSearchPtr = Square8_MainSearch;
2758      else
2759    
2760          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2761                  EPZSMainSearchPtr = Square16_MainSearch;                  MainSearchPtr = AdvDiamond8_MainSearch;
2762          else          else
2763                  EPZSMainSearchPtr = Diamond16_MainSearch;                  MainSearchPtr = Diamond8_MainSearch;
2764    
2765          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2766                          x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2767                          currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2768                          2, iFcode, iQuant, 0);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2769                                                      iQuant, 0);
2770    
2771          if (iSAD < iMinSAD)  
2772          {          if (iSAD < iMinSAD) {
2773                  *currMV = newMV;                  *currMV = newMV;
2774                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2775          }          }
2776    
2777            if (MotionFlags & PMV_EXTSEARCH8) {
         if (MotionFlags & PMV_EXTSEARCH16)  
         {  
2778  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2779    
2780                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2781                  {                          iSAD =
2782                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2783                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2784                                  pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2785                                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, 0);
                 }  
2786    
2787                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2788                          *currMV = newMV;                          *currMV = newMV;
2789                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2790                  }                  }
2791                    }
2792    
2793                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2794                  {                          iSAD =
2795                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2796                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2797                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2798                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    iQuant, 0);
2799    
2800                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2801                                  *currMV = newMV;                                  *currMV = newMV;
2802                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2803                          }                          }
# Line 1725  Line 2806 
2806    
2807  /***************        Choose best MV found     **************/  /***************        Choose best MV found     **************/
2808    
2809  EPZS16_Terminate_with_Refine:    EPZS8_Terminate_with_Refine:
2810          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step
2811                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2812                                  x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2813                                  currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2814                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
   
 EPZS16_Terminate_without_Refine:  
2815    
2816          *oldMB = *prevMB;    EPZS8_Terminate_without_Refine:
2817    
2818          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2819          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2820          return iMinSAD;          return iMinSAD;
2821  }  }
2822    
2823    
2824  int32_t EPZSSearch8(  
2825                                          const uint8_t * const pRef,  int32_t
2826    PMVfastIntSearch16(const uint8_t * const pRef,
2827                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2828                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2829                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2830                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2831                                          const int x, const int y,                                  const int x,
2832                                          const int start_x, const int start_y,                                  const int y,
2833                                    const int start_x,              /* start should be most likely vector */
2834                                    const int start_y,
2835                                    const int center_x,             /* center is from where length of MVs is measured */
2836                                    const int center_y,
2837                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2838                                          const uint32_t iQuant,                                          const uint32_t iQuant,
2839                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1759  Line 2843 
2843                                          VECTOR * const currMV,                                          VECTOR * const currMV,
2844                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
2845  {  {
 /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */  
   
2846          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
2847          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
2848          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
2849          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
2850    
2851          const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;          const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
2852            const VECTOR zeroMV = { 0, 0 };
2853    
2854          int32_t iDiamondSize=1;          int32_t iDiamondSize;
2855    
2856          int32_t min_dx;          int32_t min_dx;
2857          int32_t max_dx;          int32_t max_dx;
2858          int32_t min_dy;          int32_t min_dy;
2859          int32_t max_dy;          int32_t max_dy;
2860    
2861            int32_t iFound;
2862    
2863          VECTOR newMV;          VECTOR newMV;
2864          VECTOR backupMV;          VECTOR backupMV;
2865    
2866          VECTOR pmv[4];          VECTOR pmv[4];
2867          int32_t psad[8];          int32_t psad[4];
2868    
2869          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);          MainSearch16FuncPtr MainSearchPtr;
2870    
2871          const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2872          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;          MACROBLOCK *const pMB = pMBs + x + y * iWcount;
2873    
2874            int32_t threshA, threshB;
2875          int32_t bPredEq;          int32_t bPredEq;
2876          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD, iSAD;
2877    
         MainSearch8FuncPtr EPZSMainSearchPtr;  
2878    
2879  /* Get maximum range */  /* Get maximum range */
2880          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2881                          x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2882    
2883  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2884    
2885          if (!(MotionFlags & PMV_HALFPEL8 ))          if ((x == 0) && (y == 0)) {
2886          { min_dx = EVEN(min_dx);                  threshA = 512;
2887            max_dx = EVEN(max_dx);                  threshB = 1024;
           min_dy = EVEN(min_dy);  
           max_dy = EVEN(max_dy);  
         }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */  
2888    
2889          bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);                  bPredEq = 0;
2890                    psad[0] = psad[1] = psad[2] = psad[3] = 0;
2891                    *currMV = pmv[0] = pmv[1] = pmv[2] = pmv[3] = zeroMV;
2892    
2893            } else {
2894    
2895                    bPredEq = get_ipmvdata(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2896    
2897                    threshA = psad[0];
2898                    threshB = threshA + 256;
2899                    if (threshA < 512)
2900                            threshA = 512;
2901 &nbs