[svn] / branches / dev-api-3 / xvidcore / src / motion / motion_est.c Repository:
ViewVC logotype

Diff of /branches/dev-api-3/xvidcore/src/motion/motion_est.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 184, Mon May 27 18:07:38 2002 UTC revision 300, Tue Jul 16 12:02:27 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  
   
 #define NEIGH_MOVE_THRESH 0  
 // how much a block's MV must differ from his neighbour  
 // to be search for INTER4V. The more, the faster...  
   
 /* 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 MV16_INTER_BIAS 512  
   
 /* Parameters which control inter/inter4v decision */  
 #define IMV16X16                        5  
   
 /* vector map (vlc delta size) smoother parameters */  
 #define NEIGH_TEND_16X16        2  
 #define NEIGH_TEND_8X8          2  
   
 // fast ((A)/2)*2  
 #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)  
   
 #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )  
 #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )  
   
 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 212  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 220  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 238  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,
# Line 289  Line 180 
180          if (sadInit)          if (sadInit)
181                  (*sadInit)();                  (*sadInit)();
182    
183          for (y = 0; y < iHcount; y++)          for (y = 0; y < iHcount; y++)   {
184                  for (x = 0; x < iWcount; x++)                  for (x = 0; x < iWcount; x ++)  {
185                  {  
186                          MACROBLOCK* const pMB = &pMBs[x + y * iWcount];                          MACROBLOCK* const pMB = &pMBs[x + y * iWcount];
187    
188                          pMB->sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                          pMB->sad16 =
189                                                   x, y, current->motion_flags, current->quant, current->fcode,                                  SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
190                                                   pParam, pMBs, prevMBs, &pMB->mv16, &pMB->pmvs[0]);                                                   y, current->motion_flags, current->quant,
191                                                     current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,
192                                                     &pMB->pmvs[0]);
193    
194                          if (0 < (pMB->sad16 - MV16_INTER_BIAS))                          if (0 < (pMB->sad16 - MV16_INTER_BIAS)) {
                         {  
195                                  int32_t deviation;                                  int32_t deviation;
                                 deviation = dev16(pCurrent->y + x*16 + y*16*pParam->edged_width, pParam->edged_width);  
196    
197                                  if (deviation < (pMB->sad16 - MV16_INTER_BIAS))                                  deviation =
198                                  {                                          dev16(pCurrent->y + x * 16 + y * 16 * pParam->edged_width,
199                                                      pParam->edged_width);
200    
201                                    if (deviation < (pMB->sad16 - MV16_INTER_BIAS)) {
202                                          pMB->mode = MODE_INTRA;                                          pMB->mode = MODE_INTRA;
203                                          pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = zeroMV;                                          pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
204                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = 0;                                                  pMB->mvs[3] = zeroMV;
205                                            pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
206                                                    pMB->sad8[3] = 0;
207    
208                                          iIntra++;                                          iIntra++;
209                                          if (iIntra >= iLimit)                                          if (iIntra >= iLimit)
# Line 319  Line 215 
215    
216                          pmv = pMB->pmvs[0];                          pmv = pMB->pmvs[0];
217                          if (current->global_flags & XVID_INTER4V)                          if (current->global_flags & XVID_INTER4V)
218                                  if ( (!(current->global_flags & XVID_LUMIMASKING) || pMB->dquant == NO_CHANGE) )                                  if ((!(current->global_flags & XVID_LUMIMASKING) ||
219                                  {                                           pMB->dquant == NO_CHANGE)) {
220                                          int32_t sad8 = IMV16X16 * current->quant; if (sad8 < pMB->sad16)                                          int32_t sad8 = IMV16X16 * current->quant;
221    
222                                            if (sad8 < pMB->sad16)
223    
224                                          sad8 += pMB->sad8[0]            = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                  sad8 += pMB->sad8[0] =
225                                                                                                                          2*x, 2*y, pMB->mv16.x, pMB->mv16.y,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
226                                                                                                                          current->motion_flags, current->quant, current->fcode,                                                                          pCurrent, 2 * x, 2 * y, pMB->mv16.x,
227                                                                                                                          pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]);                                                                          pMB->mv16.y, current->motion_flags,
228                                                                            current->quant, current->fcode, pParam,
229                                                                            pMBs, prevMBs, &pMB->mvs[0],
230                                                                            &pMB->pmvs[0]);
231    
232                                          if (sad8 < pMB->sad16)                                          if (sad8 < pMB->sad16)
233                                                  sad8 += pMB->sad8[1]    = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                  sad8 += pMB->sad8[1] =
234                                                                                                                          2*x+1, 2*y, pMB->mv16.x, pMB->mv16.y,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
235                                                                                                                          current->motion_flags, current->quant, current->fcode,                                                                          pCurrent, 2 * x + 1, 2 * y, pMB->mv16.x,
236                                                                                                                          pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]);                                                                          pMB->mv16.y, current->motion_flags,
237                                                                            current->quant, current->fcode, pParam,
238                                                                            pMBs, prevMBs, &pMB->mvs[1],
239                                                                            &pMB->pmvs[1]);
240    
241                                          if (sad8 < pMB->sad16)                                          if (sad8 < pMB->sad16)
242                                                  sad8 += pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                  sad8 += pMB->sad8[2] =
243                                                                                                                          2*x, 2*y+1, pMB->mv16.x, pMB->mv16.y,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
244                                                                                                                          current->motion_flags, current->quant, current->fcode,                                                                          pCurrent, 2 * x, 2 * y + 1, pMB->mv16.x,
245                                                                                                                          pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]);                                                                          pMB->mv16.y, current->motion_flags,
246                                                                            current->quant, current->fcode, pParam,
247                                                                            pMBs, prevMBs, &pMB->mvs[2],
248                                                                            &pMB->pmvs[2]);
249    
250                                          if (sad8 < pMB->sad16)                                          if (sad8 < pMB->sad16)
251                                                  sad8 += pMB->sad8[3]    = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                  sad8 += pMB->sad8[3] =
252                                                                                                                          2*x+1, 2*y+1, pMB->mv16.x, pMB->mv16.y,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
253                                                                                                                          current->motion_flags, current->quant, current->fcode,                                                                          pCurrent, 2 * x + 1, 2 * y + 1,
254                                                                                                                          pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]);                                                                          pMB->mv16.x, pMB->mv16.y,
255                                                                            current->motion_flags, current->quant,
256                                                                            current->fcode, pParam, pMBs, prevMBs,
257                                                                            &pMB->mvs[3], &pMB->pmvs[3]);
258    
259                                          /* decide: MODE_INTER or MODE_INTER4V                                          /* decide: MODE_INTER or MODE_INTER4V
260                                                  mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v                                                  mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
261                                          */                                          */
262    
263                                          if (sad8 < pMB->sad16)                                          if (sad8 < pMB->sad16) {
                                         {  
264                                                  pMB->mode = MODE_INTER4V;                                                  pMB->mode = MODE_INTER4V;
265                              pMB->sad8[0] *= 4;                              pMB->sad8[0] *= 4;
266                                                  pMB->sad8[1] *= 4;                                                  pMB->sad8[1] *= 4;
# Line 365  Line 274 
274                                  pMB->mode = MODE_INTER;                                  pMB->mode = MODE_INTER;
275                                  pMB->pmvs[0] = pmv; /* pMB->pmvs[1] = pMB->pmvs[2] = pMB->pmvs[3]  are not needed for INTER */                                  pMB->pmvs[0] = pmv; /* pMB->pmvs[1] = pMB->pmvs[2] = pMB->pmvs[3]  are not needed for INTER */
276                                  pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;                                  pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
277                                  pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = pMB->sad16;                          pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =
278                                    pMB->sad16;
279                            }
280                  }                  }
281    
282                  return 0;                  return 0;
283  }  }
284    
# Line 485  Line 396 
396          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
397          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
398          int32_t iSAD;          int32_t iSAD;
399          int32_t pred_x,pred_y;          VECTOR pred;
400    
401    
402          get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);          pred = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
403    
404          iSAD = sad16( cur,          iSAD = sad16( cur,
405                  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 497  Line 409 
409    
410          currMV->x = 0;          currMV->x = 0;
411          currMV->y = 0;          currMV->y = 0;
412          currPMV->x = -pred_x;          currPMV->x = -pred.x;
413          currPMV->y = -pred_y;          currPMV->y = -pred.y;
414    
415          return iSAD;          return iSAD;
416    
417  }  }
418  */  */
419    
420  int32_t Diamond16_MainSearch(  int32_t
421          const uint8_t * const pRef,  Diamond16_MainSearch(const uint8_t * const pRef,
422          const uint8_t * const pRefH,          const uint8_t * const pRefH,
423          const uint8_t * const pRefV,          const uint8_t * const pRefV,
424          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
425          const uint8_t * const cur,          const uint8_t * const cur,
426          const int x, const int y,                                           const int x,
427          int32_t startx, int32_t starty,                                           const int y,
428                                             int32_t startx,
429                                             int32_t starty,
430          int32_t iMinSAD,          int32_t iMinSAD,
431          VECTOR * const currMV,          VECTOR * const currMV,
432          const VECTOR * const pmv,          const VECTOR * const pmv,
433          const int32_t min_dx, const int32_t max_dx,                                           const int32_t min_dx,
434          const int32_t min_dy, const int32_t max_dy,                                           const int32_t max_dx,
435                                             const int32_t min_dy,
436                                             const int32_t max_dy,
437          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
438          const int32_t iDiamondSize,          const int32_t iDiamondSize,
439          const int32_t iFcode,          const int32_t iFcode,
# Line 529  Line 445 
445          int32_t iDirection=0;          int32_t iDirection=0;
446          int32_t iSAD;          int32_t iSAD;
447          VECTOR backupMV;          VECTOR backupMV;
448    
449          backupMV.x = startx;          backupMV.x = startx;
450          backupMV.y = starty;          backupMV.y = starty;
451    
# Line 540  Line 457 
457          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
458    
459          if (iDirection)          if (iDirection)
460                  while (!iFound)                  while (!iFound) {
                 {  
461                          iFound = 1;                          iFound = 1;
462                          backupMV=*currMV;                          backupMV=*currMV;
463    
464                          if ( iDirection != 2)                          if ( iDirection != 2)
465                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
466                                                                                       backupMV.y, 1);
467                          if ( iDirection != 1)                          if ( iDirection != 1)
468                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
469                                                                                       backupMV.y, 2);
470                          if ( iDirection != 4)                          if ( iDirection != 4)
471                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
472                                                                                       backupMV.y - iDiamondSize, 3);
473                          if ( iDirection != 3)                          if ( iDirection != 3)
474                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
475                  }                                                                                     backupMV.y + iDiamondSize, 4);
476          else          } else {
         {  
477                  currMV->x = startx;                  currMV->x = startx;
478                  currMV->y = starty;                  currMV->y = starty;
479          }          }
480          return iMinSAD;          return iMinSAD;
481  }  }
482    
483  int32_t Square16_MainSearch(  int32_t
484                                          const uint8_t * const pRef,  Square16_MainSearch(const uint8_t * const pRef,
485                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
486                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
487                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
488                                          const uint8_t * const cur,                                          const uint8_t * const cur,
489                                          const int x, const int y,                                          const int x,
490                                          int32_t startx, int32_t starty,                                          const int y,
491                                            int32_t startx,
492                                            int32_t starty,
493                                          int32_t iMinSAD,                                          int32_t iMinSAD,
494                                          VECTOR * const currMV,                                          VECTOR * const currMV,
495                                          const VECTOR * const pmv,                                          const VECTOR * const pmv,
496                                          const int32_t min_dx, const int32_t max_dx,                                          const int32_t min_dx,
497                                          const int32_t min_dy, const int32_t max_dy,                                          const int32_t max_dx,
498                                            const int32_t min_dy,
499                                            const int32_t max_dy,
500                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
501                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
502                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 586  Line 508 
508          int32_t iDirection=0;          int32_t iDirection=0;
509          int32_t iSAD;          int32_t iSAD;
510          VECTOR backupMV;          VECTOR backupMV;
511    
512          backupMV.x = startx;          backupMV.x = startx;
513          backupMV.y = starty;          backupMV.y = starty;
514    
# Line 602  Line 525 
525          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
526          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
527    
528          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
529          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                           backupMV.y - iDiamondSize, 5);
530          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
531          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                                           backupMV.y + iDiamondSize, 6);
532            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
533                                                             backupMV.y - iDiamondSize, 7);
534            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
535                                                             backupMV.y + iDiamondSize, 8);
536    
537    
538          if (iDirection)          if (iDirection)
539                  while (!iFound)                  while (!iFound) {
                 {  
540                          iFound = 1;                          iFound = 1;
541                          backupMV=*currMV;                          backupMV=*currMV;
542    
543                          switch (iDirection)                          switch (iDirection) {
                         {  
544                                  case 1:                                  case 1:
545                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
546                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                     backupMV.y, 1);
547                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
548                                                                                     backupMV.y - iDiamondSize, 5);
549                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
550                                                                                     backupMV.y - iDiamondSize, 7);
551                                          break;                                          break;
552                                  case 2:                                  case 2:
553                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
554                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   2);
555                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
556                                                                                     backupMV.y + iDiamondSize, 6);
557                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
558                                                                                     backupMV.y + iDiamondSize, 8);
559                                          break;                                          break;
560    
561                                  case 3:                                  case 3:
562                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
563                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
564                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
565                                                                                     backupMV.y - iDiamondSize, 7);
566                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
567                                                                                     backupMV.y + iDiamondSize, 8);
568                                          break;                                          break;
569    
570                                  case 4:                                  case 4:
571                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
572                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
573                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
574                                                                                     backupMV.y - iDiamondSize, 5);
575                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
576                                                                                     backupMV.y + iDiamondSize, 6);
577                                          break;                                          break;
578    
579                                  case 5:                                  case 5:
580                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y,
581                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   1);
582                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
583                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   3);
584                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
585                                                                                     backupMV.y - iDiamondSize, 5);
586                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
587                                                                                     backupMV.y + iDiamondSize, 6);
588                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
589                                                                                     backupMV.y - iDiamondSize, 7);
590                                          break;                                          break;
591    
592                                  case 6:                                  case 6:
593                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
594                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   2);
595                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
596                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
597                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);  
598                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
599                                                                                     backupMV.y - iDiamondSize, 5);
600                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
601                                                                                     backupMV.y + iDiamondSize, 6);
602                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
603                                                                                     backupMV.y + iDiamondSize, 8);
604    
605                                          break;                                          break;
606    
607                                  case 7:                                  case 7:
608                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
609                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                     backupMV.y, 1);
610                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
611                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
612                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
613                                                                                     backupMV.y - iDiamondSize, 5);
614                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
615                                                                                     backupMV.y - iDiamondSize, 7);
616                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
617                                                                                     backupMV.y + iDiamondSize, 8);
618                                          break;                                          break;
619    
620                                  case 8:                                  case 8:
621                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
622                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
623                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
624                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
625                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
626                                                                                     backupMV.y + iDiamondSize, 6);
627                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
628                                                                                     backupMV.y - iDiamondSize, 7);
629                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
630                                                                                     backupMV.y + iDiamondSize, 8);
631                                          break;                                          break;
632                          default:                          default:
633                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y,
634                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                                                                   1);
635                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
636                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
637                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
638                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
639                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
640                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
641                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);  
642                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
643                                                                                     backupMV.y - iDiamondSize, 5);
644                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
645                                                                                     backupMV.y + iDiamondSize, 6);
646                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
647                                                                                     backupMV.y - iDiamondSize, 7);
648                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
649                                                                                     backupMV.y + iDiamondSize, 8);
650                                          break;                                          break;
651                          }                          }
652                  }          } else {
         else  
                 {  
653                          currMV->x = startx;                          currMV->x = startx;
654                          currMV->y = starty;                          currMV->y = starty;
655                  }                  }
# Line 694  Line 657 
657  }  }
658    
659    
660  int32_t Full16_MainSearch(  int32_t
661                                          const uint8_t * const pRef,  Full16_MainSearch(const uint8_t * const pRef,
662                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
663                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
664                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
665                                          const uint8_t * const cur,                                          const uint8_t * const cur,
666                                          const int x, const int y,                                    const int x,
667                                          int32_t startx, int32_t starty,                                    const int y,
668                                      int32_t startx,
669                                      int32_t starty,
670                                          int32_t iMinSAD,                                          int32_t iMinSAD,
671                                          VECTOR * const currMV,                                          VECTOR * const currMV,
672                                          const VECTOR * const pmv,                                          const VECTOR * const pmv,
673                                          const int32_t min_dx, const int32_t max_dx,                                    const int32_t min_dx,
674                                          const int32_t min_dy, const int32_t max_dy,                                    const int32_t max_dx,
675                                      const int32_t min_dy,
676                                      const int32_t max_dy,
677                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
678                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
679                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 716  Line 683 
683          int32_t iSAD;          int32_t iSAD;
684          int32_t dx,dy;          int32_t dx,dy;
685          VECTOR backupMV;          VECTOR backupMV;
686    
687          backupMV.x = startx;          backupMV.x = startx;
688          backupMV.y = starty;          backupMV.y = starty;
689    
# Line 726  Line 694 
694          return iMinSAD;          return iMinSAD;
695  }  }
696    
697  int32_t AdvDiamond16_MainSearch(  int32_t
698          const uint8_t * const pRef,  AdvDiamond16_MainSearch(const uint8_t * const pRef,
699          const uint8_t * const pRefH,          const uint8_t * const pRefH,
700          const uint8_t * const pRefV,          const uint8_t * const pRefV,
701          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
702          const uint8_t * const cur,          const uint8_t * const cur,
703          const int x, const int y,                                                  const int x,
704          int32_t startx, int32_t starty,                                                  const int y,
705                                                    int32_t startx,
706                                                    int32_t starty,
707          int32_t iMinSAD,          int32_t iMinSAD,
708          VECTOR * const currMV,          VECTOR * const currMV,
709          const VECTOR * const pmv,          const VECTOR * const pmv,
710          const int32_t min_dx, const int32_t max_dx,                                                  const int32_t min_dx,
711          const int32_t min_dy, const int32_t max_dy,                                                  const int32_t max_dx,
712                                                    const int32_t min_dy,
713                                                    const int32_t max_dy,
714          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
715          const int32_t iDiamondSize,          const int32_t iDiamondSize,
716          const int32_t iFcode,          const int32_t iFcode,
# Line 750  Line 722 
722    
723  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
724    
725          if (iDirection)          if (iDirection) {
         {  
726                  CHECK_MV16_CANDIDATE(startx-iDiamondSize, starty);                  CHECK_MV16_CANDIDATE(startx-iDiamondSize, starty);
727                  CHECK_MV16_CANDIDATE(startx+iDiamondSize, starty);                  CHECK_MV16_CANDIDATE(startx+iDiamondSize, starty);
728                  CHECK_MV16_CANDIDATE(startx, starty-iDiamondSize);                  CHECK_MV16_CANDIDATE(startx, starty-iDiamondSize);
729                  CHECK_MV16_CANDIDATE(startx, starty+iDiamondSize);                  CHECK_MV16_CANDIDATE(startx, starty+iDiamondSize);
730          }          } else {
         else  
         {  
731                  int bDirection = 1+2+4+8;                  int bDirection = 1+2+4+8;
732                  do  
733                  {                  do {
734                          iDirection = 0;                          iDirection = 0;
735                          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)                          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)
736                                  CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize,starty,1);                                  CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize,starty,1);
# Line 781  Line 750 
750                          {                          {
751                                  bDirection = iDirection;                                  bDirection = iDirection;
752                                  iDirection = 0;                                  iDirection = 0;
753                                  startx=currMV->x; starty=currMV->y;                                  startx = currMV->x;
754                                    starty = currMV->y;
755                                  if (bDirection & 3) //our candidate is left or right                                  if (bDirection & 3) //our candidate is left or right
756                                  {                                  {
757                                          CHECK_MV16_CANDIDATE_DIR(startx,starty+iDiamondSize, 8);                                          CHECK_MV16_CANDIDATE_DIR(startx,starty+iDiamondSize, 8);
758                                          CHECK_MV16_CANDIDATE_DIR(startx,starty-iDiamondSize, 4);                                          CHECK_MV16_CANDIDATE_DIR(startx,starty-iDiamondSize, 4);
759                                  }                                  } else                  // what remains here is up or down
                                 else // what remains here is up or down  
760                                  {                                  {
761                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty, 2);                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty, 2);
762                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty, 1);                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty, 1);
763                                  }                                  }
764    
765                                  if (iDirection)                                  if (iDirection) {
766                                  {       bDirection+=iDirection;                                          bDirection += iDirection;
767                                          startx=currMV->x; starty=currMV->y;                                          startx = currMV->x;
768                                  }                                          starty = currMV->y;
769                          }                          }
770                          else //about to quit, eh? not so fast....                          } else                          //about to quit, eh? not so fast....
                         {  
                                 switch (bDirection)  
771                                  {                                  {
772                                    switch (bDirection) {
773                                  case 2:                                  case 2:
774                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
775                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                                                                           starty - iDiamondSize, 2 + 4);
776                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
777                                                                                             starty + iDiamondSize, 2 + 8);
778                                          break;                                          break;
779                                  case 1:                                  case 1:
780                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
781                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                           starty - iDiamondSize, 1 + 4);
782                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
783                                                                                             starty + iDiamondSize, 1 + 8);
784                                          break;                                          break;
785                                  case 2+4:                                  case 2+4:
786                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
787                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                                                                           starty - iDiamondSize, 1 + 4);
788                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
789                                                                                             starty - iDiamondSize, 2 + 4);
790                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
791                                                                                             starty + iDiamondSize, 2 + 8);
792                                          break;                                          break;
793                                  case 4:                                  case 4:
794                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
795                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                                                                           starty - iDiamondSize, 2 + 4);
796                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
797                                                                                             starty - iDiamondSize, 1 + 4);
798                                          break;                                          break;
799                                  case 8:                                  case 8:
800                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
801                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                           starty + iDiamondSize, 2 + 8);
802                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
803                                                                                             starty + iDiamondSize, 1 + 8);
804                                          break;                                          break;
805                                  case 1+4:                                  case 1+4:
806                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
807                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                                                                           starty + iDiamondSize, 1 + 8);
808                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
809                                                                                             starty - iDiamondSize, 1 + 4);
810                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
811                                                                                             starty - iDiamondSize, 2 + 4);
812                                          break;                                          break;
813                                  case 2+8:                                  case 2+8:
814                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
815                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                           starty - iDiamondSize, 1 + 4);
816                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
817                                                                                             starty + iDiamondSize, 1 + 8);
818                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
819                                                                                             starty + iDiamondSize, 2 + 8);
820                                          break;                                          break;
821                                  case 1+8:                                  case 1+8:
822                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
823                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                                                                           starty - iDiamondSize, 2 + 4);
824                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                          CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
825                                                                                             starty + iDiamondSize, 2 + 8);
826                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
827                                                                                             starty + iDiamondSize, 1 + 8);
828                                          break;                                          break;
829                                  default: //1+2+4+8 == we didn't find anything at all                                  default: //1+2+4+8 == we didn't find anything at all
830                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
831                                          CHECK_MV16_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                           starty - iDiamondSize, 1 + 4);
832                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
833                                          CHECK_MV16_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                                                                           starty + iDiamondSize, 1 + 8);
834                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
835                                                                                             starty - iDiamondSize, 2 + 4);
836                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
837                                                                                             starty + iDiamondSize, 2 + 8);
838                                          break;                                          break;
839                                  }                                  }
840                                  if (!iDirection) break; //ok, the end. really                                  if (!iDirection)
841                                  else                                          break;          //ok, the end. really
842                                  {       bDirection=iDirection;                                  else {
843                                          startx=currMV->x; starty=currMV->y;                                          bDirection = iDirection;
844                                            startx = currMV->x;
845                                            starty = currMV->y;
846                                  }                                  }
847                          }                          }
848                  }                  }
# Line 857  Line 851 
851          return iMinSAD;          return iMinSAD;
852  }  }
853    
854  int32_t AdvDiamond8_MainSearch(  int32_t
855          const uint8_t * const pRef,  AdvDiamond8_MainSearch(const uint8_t * const pRef,
856          const uint8_t * const pRefH,          const uint8_t * const pRefH,
857          const uint8_t * const pRefV,          const uint8_t * const pRefV,
858          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
859          const uint8_t * const cur,          const uint8_t * const cur,
860          const int x, const int y,                                             const int x,
861          int32_t startx, int32_t starty,                                             const int y,
862                                               int32_t startx,
863                                               int32_t starty,
864          int32_t iMinSAD,          int32_t iMinSAD,
865          VECTOR * const currMV,          VECTOR * const currMV,
866          const VECTOR * const pmv,          const VECTOR * const pmv,
867          const int32_t min_dx, const int32_t max_dx,                                             const int32_t min_dx,
868          const int32_t min_dy, const int32_t max_dy,                                             const int32_t max_dx,
869                                               const int32_t min_dy,
870                                               const int32_t max_dy,
871          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
872          const int32_t iDiamondSize,          const int32_t iDiamondSize,
873          const int32_t iFcode,          const int32_t iFcode,
# Line 881  Line 879 
879    
880  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
881    
882          if (iDirection)          if (iDirection) {
         {  
883                  CHECK_MV8_CANDIDATE(startx-iDiamondSize, starty);                  CHECK_MV8_CANDIDATE(startx-iDiamondSize, starty);
884                  CHECK_MV8_CANDIDATE(startx+iDiamondSize, starty);                  CHECK_MV8_CANDIDATE(startx+iDiamondSize, starty);
885                  CHECK_MV8_CANDIDATE(startx, starty-iDiamondSize);                  CHECK_MV8_CANDIDATE(startx, starty-iDiamondSize);
886                  CHECK_MV8_CANDIDATE(startx, starty+iDiamondSize);                  CHECK_MV8_CANDIDATE(startx, starty+iDiamondSize);
887          }          } else {
         else  
         {  
888                  int bDirection = 1+2+4+8;                  int bDirection = 1+2+4+8;
889                  do  
890                  {                  do {
891                          iDirection = 0;                          iDirection = 0;
892                          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)                          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)
893                                  CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize,starty,1);                                  CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize,starty,1);
# Line 912  Line 907 
907                          {                          {
908                                  bDirection = iDirection;                                  bDirection = iDirection;
909                                  iDirection = 0;                                  iDirection = 0;
910                                  startx=currMV->x; starty=currMV->y;                                  startx = currMV->x;
911                                    starty = currMV->y;
912                                  if (bDirection & 3) //our candidate is left or right                                  if (bDirection & 3) //our candidate is left or right
913                                  {                                  {
914                                          CHECK_MV8_CANDIDATE_DIR(startx,starty+iDiamondSize, 8);                                          CHECK_MV8_CANDIDATE_DIR(startx,starty+iDiamondSize, 8);
915                                          CHECK_MV8_CANDIDATE_DIR(startx,starty-iDiamondSize, 4);                                          CHECK_MV8_CANDIDATE_DIR(startx,starty-iDiamondSize, 4);
916                                  }                                  } else                  // what remains here is up or down
                                 else // what remains here is up or down  
917                                  {                                  {
918                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty, 2);                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty, 2);
919                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty, 1);                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty, 1);
920                                  }                                  }
921    
922                                  if (iDirection)                                  if (iDirection) {
923                                  {       bDirection+=iDirection;                                          bDirection += iDirection;
924                                          startx=currMV->x; starty=currMV->y;                                          startx = currMV->x;
925                                            starty = currMV->y;
926                                  }                                  }
927                          }                          } else                          //about to quit, eh? not so fast....
                         else //about to quit, eh? not so fast....  
                         {  
                                 switch (bDirection)  
928                                  {                                  {
929                                    switch (bDirection) {
930                                  case 2:                                  case 2:
931                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
932                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                                                                          starty - iDiamondSize, 2 + 4);
933                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
934                                                                                            starty + iDiamondSize, 2 + 8);
935                                          break;                                          break;
936                                  case 1:                                  case 1:
937                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
938                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                          starty - iDiamondSize, 1 + 4);
939                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
940                                                                                            starty + iDiamondSize, 1 + 8);
941                                          break;                                          break;
942                                  case 2+4:                                  case 2+4:
943                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
944                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                                                                          starty - iDiamondSize, 1 + 4);
945                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
946                                                                                            starty - iDiamondSize, 2 + 4);
947                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
948                                                                                            starty + iDiamondSize, 2 + 8);
949                                          break;                                          break;
950                                  case 4:                                  case 4:
951                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
952                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                                                                          starty - iDiamondSize, 2 + 4);
953                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
954                                                                                            starty - iDiamondSize, 1 + 4);
955                                          break;                                          break;
956                                  case 8:                                  case 8:
957                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
958                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                          starty + iDiamondSize, 2 + 8);
959                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
960                                                                                            starty + iDiamondSize, 1 + 8);
961                                          break;                                          break;
962                                  case 1+4:                                  case 1+4:
963                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
964                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                                                                          starty + iDiamondSize, 1 + 8);
965                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
966                                                                                            starty - iDiamondSize, 1 + 4);
967                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
968                                                                                            starty - iDiamondSize, 2 + 4);
969                                          break;                                          break;
970                                  case 2+8:                                  case 2+8:
971                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
972                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                          starty - iDiamondSize, 1 + 4);
973                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
974                                                                                            starty + iDiamondSize, 1 + 8);
975                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
976                                                                                            starty + iDiamondSize, 2 + 8);
977                                          break;                                          break;
978                                  case 1+8:                                  case 1+8:
979                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
980                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                                                                          starty - iDiamondSize, 2 + 4);
981                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                          CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
982                                                                                            starty + iDiamondSize, 2 + 8);
983                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
984                                                                                            starty + iDiamondSize, 1 + 8);
985                                          break;                                          break;
986                                  default: //1+2+4+8 == we didn't find anything at all                                  default: //1+2+4+8 == we didn't find anything at all
987                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty-iDiamondSize, 1+4);                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
988                                          CHECK_MV8_CANDIDATE_DIR(startx-iDiamondSize, starty+iDiamondSize, 1+8);                                                                                          starty - iDiamondSize, 1 + 4);
989                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty-iDiamondSize, 2+4);                                          CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
990                                          CHECK_MV8_CANDIDATE_DIR(startx+iDiamondSize, starty+iDiamondSize, 2+8);                                                                                          starty + iDiamondSize, 1 + 8);
991                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
992                                                                                            starty - iDiamondSize, 2 + 4);
993                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
994                                                                                            starty + iDiamondSize, 2 + 8);
995                                          break;                                          break;
996                                  }                                  }
997                                  if (!(iDirection)) break; //ok, the end. really                                  if (!(iDirection))
998                                  else                                          break;          //ok, the end. really
999                                  {       bDirection=iDirection;                                  else {
1000                                          startx=currMV->x; starty=currMV->y;                                          bDirection = iDirection;
1001                                            startx = currMV->x;
1002                                            starty = currMV->y;
1003                                  }                                  }
1004                          }                          }
1005                  }                  }
# Line 989  Line 1009 
1009  }  }
1010    
1011    
1012  int32_t Full8_MainSearch(  int32_t
1013                                          const uint8_t * const pRef,  Full8_MainSearch(const uint8_t * const pRef,
1014                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1015                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1016                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1017                                          const uint8_t * const cur,                                          const uint8_t * const cur,
1018                                          const int x, const int y,                                   const int x,
1019                                          int32_t startx, int32_t starty,                                   const int y,
1020                                     int32_t startx,
1021                                     int32_t starty,
1022                                          int32_t iMinSAD,                                          int32_t iMinSAD,
1023                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1024                                          const VECTOR * const pmv,                                          const VECTOR * const pmv,
1025                                          const int32_t min_dx, const int32_t max_dx,                                   const int32_t min_dx,
1026                                          const int32_t min_dy, const int32_t max_dy,                                   const int32_t max_dx,
1027                                     const int32_t min_dy,
1028                                     const int32_t max_dy,
1029                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
1030                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
1031                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 1011  Line 1035 
1035          int32_t iSAD;          int32_t iSAD;
1036          int32_t dx,dy;          int32_t dx,dy;
1037          VECTOR backupMV;          VECTOR backupMV;
1038    
1039          backupMV.x = startx;          backupMV.x = startx;
1040          backupMV.y = starty;          backupMV.y = starty;
1041    
# Line 1021  Line 1046 
1046          return iMinSAD;          return iMinSAD;
1047  }  }
1048    
1049    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1050    
1051    int32_t
1052  int32_t Halfpel16_Refine(  Halfpel16_Refine(const uint8_t * const pRef,
         const uint8_t * const pRef,  
1053          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1054          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1055          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1056          const uint8_t * const cur,          const uint8_t * const cur,
1057          const int x, const int y,                                   const int x,
1058                                     const int y,
1059          VECTOR * const currMV,          VECTOR * const currMV,
1060          int32_t iMinSAD,          int32_t iMinSAD,
1061          const VECTOR * const pmv,          const VECTOR * const pmv,
1062          const int32_t min_dx, const int32_t max_dx,                                   const int32_t min_dx,
1063          const int32_t min_dy, const int32_t max_dy,                                   const int32_t max_dx,
1064                                     const int32_t min_dy,
1065                                     const int32_t max_dy,
1066          const int32_t iFcode,          const int32_t iFcode,
1067          const int32_t iQuant,          const int32_t iQuant,
1068          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 1059  Line 1087 
1087  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1088    
1089    
1090  int32_t PMVfastSearch16(  int32_t
1091                                          const uint8_t * const pRef,  PMVfastSearch16(const uint8_t * const pRef,
1092                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1093                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1094                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1095                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1096                                          const int x, const int y,                                  const int x,
1097                                    const int y,
1098                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1099                                          const uint32_t iQuant,                                          const uint32_t iQuant,
1100                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1099  Line 1128 
1128    
1129          MainSearch16FuncPtr MainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
1130    
 //      const MACROBLOCK * const pMB = pMBs + x + y * iWcount;  
1131          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1132    
1133          static int32_t threshA,threshB;          int32_t threshA, threshB;
1134          int32_t bPredEq;          int32_t bPredEq;
1135          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1136    
1137  /* Get maximum range */  /* Get maximum range */
1138          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,
1139                    x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
1140    
1141  /* 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 */
1142    
1143          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
1144          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1145          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1146          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1147          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1148          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
   
   
         bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);  
1149    
1150          if ((x==0) && (y==0) )          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1151          {          //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1152            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1153    
1154    /*      fprintf(stderr,"pmv: %d %d / %d --- %d %d   %d %d   %d %d - %d %d %d\n",
1155                    pmv[0].x,pmv[0].y,psad[0],
1156                    pmv[1].x,pmv[1].y,pmv[2].x,pmv[2].y,pmv[3].x,pmv[3].y,
1157                    psad[1],psad[2],psad[3]);
1158    */
1159            if ((x == 0) && (y == 0)) {
1160                  threshA =  512;                  threshA =  512;
1161                  threshB = 1024;                  threshB = 1024;
1162            } else {
         }  
         else  
         {  
1163                  threshA = psad[0];                  threshA = psad[0];
1164                  threshB = threshA+256;                  threshB = threshA+256;
1165                  if (threshA< 512) threshA =  512;                  if (threshA < 512)
1166                  if (threshA>1024) threshA = 1024;                          threshA = 512;
1167                  if (threshB>1792) threshB = 1792;                  if (threshA > 1024)
1168                            threshA = 1024;
1169                    if (threshB > 1792)
1170                            threshB = 1792;
1171          }          }
1172    
1173          iFound=0;          iFound=0;
# Line 1147  Line 1180 
1180  */  */
1181    
1182          *currMV=pmv[0];         /* current best := prediction */          *currMV=pmv[0];         /* current best := prediction */
1183          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {   /* This should NOT be necessary! */
         {       /* This should NOT be necessary! */  
1184                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1185                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
1186          }          }
1187    
1188          if (currMV->x > max_dx)          if (currMV->x > max_dx) {
         {  
1189                  currMV->x=max_dx;                  currMV->x=max_dx;
1190          }          }
1191          if (currMV->x < min_dx)          if (currMV->x < min_dx) {
         {  
1192                  currMV->x=min_dx;                  currMV->x=min_dx;
1193          }          }
1194          if (currMV->y > max_dy)          if (currMV->y > max_dy) {
         {  
1195                  currMV->y=max_dy;                  currMV->y=max_dy;
1196          }          }
1197          if (currMV->y < min_dy)          if (currMV->y < min_dy) {
         {  
1198                  currMV->y=min_dy;                  currMV->y=min_dy;
1199          }          }
1200    
1201          iMinSAD = sad16( cur,          iMinSAD =
1202                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1203                           iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1204          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1205            iMinSAD +=
1206          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )                  calc_delta_16(currMV->x - pmv[0].x, currMV->y - pmv[0].y,
1207          {                                            (uint8_t) iFcode, iQuant);
1208    
1209            if ((iMinSAD < 256) ||
1210                    ((MVequal(*currMV, prevMB->mvs[0])) &&
1211                     ((int32_t) iMinSAD < prevMB->sad16))) {
1212                  if (iMinSAD < 2*iQuant) // high chances for SKIP-mode                  if (iMinSAD < 2*iQuant) // high chances for SKIP-mode
1213                  {                  {
1214                          if (!MVzero(*currMV))                          if (!MVzero(*currMV)) {
                         {  
1215                                  iMinSAD += MV16_00_BIAS;                                  iMinSAD += MV16_00_BIAS;
1216                                  CHECK_MV16_ZERO;                // (0,0) saves space for letterboxed pictures                                  CHECK_MV16_ZERO;                // (0,0) saves space for letterboxed pictures
1217                                  iMinSAD -= MV16_00_BIAS;                                  iMinSAD -= MV16_00_BIAS;
# Line 1236  Line 1267 
1267    
1268          if (!MVzero(pmv[1]))          if (!MVzero(pmv[1]))
1269          if (!MVequal(pmv[1],prevMB->mvs[0]))          if (!MVequal(pmv[1],prevMB->mvs[0]))
1270          if (!MVequal(pmv[1],pmv[0]))                          if (!MVequal(pmv[1], pmv[0])) {
1271          {                                  if (!(MotionFlags & PMV_HALFPEL16)) {
1272                  if (!(MotionFlags & PMV_HALFPEL16 ))                                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
1273                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
1274                  }                  }
1275    
1276                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1277          }          }
   
1278  // top neighbour, if allowed  // top neighbour, if allowed
1279          if (!MVzero(pmv[2]))          if (!MVzero(pmv[2]))
1280          if (!MVequal(pmv[2],prevMB->mvs[0]))          if (!MVequal(pmv[2],prevMB->mvs[0]))
1281          if (!MVequal(pmv[2],pmv[0]))          if (!MVequal(pmv[2],pmv[0]))
1282          if (!MVequal(pmv[2],pmv[1]))                                  if (!MVequal(pmv[2], pmv[1])) {
1283          {                                          if (!(MotionFlags & PMV_HALFPEL16)) {
1284                  if (!(MotionFlags & PMV_HALFPEL16 ))                                                  pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
1285                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
1286                  }                  }
1287                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
# Line 1263  Line 1291 
1291                  if (!MVequal(pmv[3],prevMB->mvs[0]))                  if (!MVequal(pmv[3],prevMB->mvs[0]))
1292                  if (!MVequal(pmv[3],pmv[0]))                  if (!MVequal(pmv[3],pmv[0]))
1293                  if (!MVequal(pmv[3],pmv[1]))                  if (!MVequal(pmv[3],pmv[1]))
1294                  if (!MVequal(pmv[3],pmv[2]))                                                                          if (!MVequal(pmv[3], pmv[2])) {
1295                  {                                                                                  if (!(MotionFlags & PMV_HALFPEL16)) {
1296                          if (!(MotionFlags & PMV_HALFPEL16 ))                                                                                          pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
1297                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
1298                          }                          }
1299                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                  CHECK_MV16_CANDIDATE(pmv[3].x,
1300                                                                                                                             pmv[3].y);
1301                  }                  }
1302          }          }
1303    
1304          if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96)*/ )          if ((MVzero(*currMV)) &&
1305                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1306                  iMinSAD -= MV16_00_BIAS;                  iMinSAD -= MV16_00_BIAS;
1307    
1308    
# Line 1281  Line 1310 
1310     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.
1311  */  */
1312    
1313          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ((iMinSAD <= threshA) ||
1314          {                  (MVequal(*currMV, prevMB->mvs[0]) &&
1315                     ((int32_t) iMinSAD < prevMB->sad16))) {
1316                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1317                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
1318                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1302  Line 1332 
1332    
1333          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
1334                  MainSearchPtr = Square16_MainSearch;                  MainSearchPtr = Square16_MainSearch;
1335          else          else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
                 if (MotionFlags & PMV_ADVANCEDDIAMOND16)  
1336                          MainSearchPtr = AdvDiamond16_MainSearch;                          MainSearchPtr = AdvDiamond16_MainSearch;
1337                  else                  else
1338                          MainSearchPtr = Diamond16_MainSearch;                          MainSearchPtr = Diamond16_MainSearch;
1339    
1340          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1341    
1342    
1343    //      fprintf(stderr,"Entering Diamond %d %d (%d):\n",x,y,iMinSAD);
1344    
1345  /* 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 */
1346          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1347                                            x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
1348                                            currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,
1349                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1350                                                      iQuant, iFound);
1351    
1352          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1353                  *currMV = newMV;                  *currMV = newMV;
1354                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1355          }          }
1356    
1357          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
1358  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1359    
1360                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1361                  {       iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1362                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1363                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,
1364                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1365                                                                      iDiamondSize, iFcode, iQuant, iFound);
1366    
1367                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1368                          *currMV = newMV;                          *currMV = newMV;
1369                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1370                  }                  }
1371                  }                  }
1372    
1373                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1374                  {       iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1375                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1376                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,
1377                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
1378                                                                      iQuant, iFound);
1379    
1380                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1381                          *currMV = newMV;                          *currMV = newMV;
1382                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1383                  }                  }
# Line 1359  Line 1390 
1390    
1391  PMVfast16_Terminate_with_Refine:  PMVfast16_Terminate_with_Refine:
1392          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1393                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1394                                    x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1395                                    currMV, iMinSAD,                                                           iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,
1396                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1397    
1398    /*fprintf(stderr,"Chosen for %d %d: %d %d - %d %d\n",x,y,currMV->x,currMV->y,pmv[0].x,pmv[0].y);
1399    */
1400  PMVfast16_Terminate_without_Refine:  PMVfast16_Terminate_without_Refine:
1401          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1402          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
# Line 1375  Line 1408 
1408    
1409    
1410    
1411  int32_t Diamond8_MainSearch(  int32_t
1412          const uint8_t * const pRef,  Diamond8_MainSearch(const uint8_t * const pRef,
1413          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1414          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1415          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1416          const uint8_t * const cur,          const uint8_t * const cur,
1417          const int x, const int y,                                          const int x,
1418          int32_t startx, int32_t starty,                                          const int y,
1419                                            int32_t startx,
1420                                            int32_t starty,
1421          int32_t iMinSAD,          int32_t iMinSAD,
1422          VECTOR * const currMV,          VECTOR * const currMV,
1423          const VECTOR * const pmv,          const VECTOR * const pmv,
1424          const int32_t min_dx, const int32_t max_dx,                                          const int32_t min_dx,
1425          const int32_t min_dy, const int32_t max_dy,                                          const int32_t max_dx,
1426                                            const int32_t min_dy,
1427                                            const int32_t max_dy,
1428          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
1429          const int32_t iDiamondSize,          const int32_t iDiamondSize,
1430          const int32_t iFcode,          const int32_t iFcode,
# Line 1399  Line 1436 
1436          int32_t iDirection=0;          int32_t iDirection=0;
1437          int32_t iSAD;          int32_t iSAD;
1438          VECTOR backupMV;          VECTOR backupMV;
1439    
1440          backupMV.x = startx;          backupMV.x = startx;
1441          backupMV.y = starty;          backupMV.y = starty;
1442    
# Line 1410  Line 1448 
1448          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1449    
1450          if (iDirection)          if (iDirection)
1451                  while (!iFound)                  while (!iFound) {
                 {  
1452                          iFound = 1;                          iFound = 1;
1453                          backupMV=*currMV;       // since iDirection!=0, this is well defined!                          backupMV=*currMV;       // since iDirection!=0, this is well defined!
1454    
1455                          if ( iDirection != 2)                          if ( iDirection != 2)
1456                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1457                                                                                      backupMV.y, 1);
1458                          if ( iDirection != 1)                          if ( iDirection != 1)
1459                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1460                                                                                      backupMV.y, 2);
1461                          if ( iDirection != 4)                          if ( iDirection != 4)
1462                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1463                                                                                      backupMV.y - iDiamondSize, 3);
1464                          if ( iDirection != 3)                          if ( iDirection != 3)
1465                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1466                  }                                                                                    backupMV.y + iDiamondSize, 4);
1467          else          } else {
         {  
1468                  currMV->x = startx;                  currMV->x = startx;
1469                  currMV->y = starty;                  currMV->y = starty;
1470          }          }
1471          return iMinSAD;          return iMinSAD;
1472  }  }
1473    
1474  int32_t Halfpel8_Refine(  int32_t
1475          const uint8_t * const pRef,  Halfpel8_Refine_c(const uint8_t * const pRef,
1476          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1477          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1478          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1479          const uint8_t * const cur,          const uint8_t * const cur,
1480          const int x, const int y,                                  const int x,
1481                                    const int y,
1482          VECTOR * const currMV,          VECTOR * const currMV,
1483          int32_t iMinSAD,          int32_t iMinSAD,
1484          const VECTOR * const pmv,          const VECTOR * const pmv,
1485          const int32_t min_dx, const int32_t max_dx,                                  const int32_t min_dx,
1486          const int32_t min_dy, const int32_t max_dy,                                  const int32_t max_dx,
1487                                    const int32_t min_dy,
1488                                    const int32_t max_dy,
1489          const int32_t iFcode,          const int32_t iFcode,
1490          const int32_t iQuant,          const int32_t iQuant,
1491          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 1468  Line 1510 
1510    
1511  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1512    
1513  int32_t PMVfastSearch8(  int32_t
1514                                          const uint8_t * const pRef,  PMVfastSearch8(const uint8_t * const pRef,
1515                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1516                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1517                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1518                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1519                                          const int x, const int y,                             const int x,
1520                                          const int start_x, const int start_y,                             const int y,
1521                               const int start_x,
1522                               const int start_y,
1523                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1524                                          const uint32_t iQuant,                                          const uint32_t iQuant,
1525                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1508  Line 1552 
1552  //      const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //      const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1553          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1554    
1555          static int32_t threshA,threshB;           int32_t threshA, threshB;
1556          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
1557          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1558    
# Line 1521  Line 1565 
1565          startMV.y = start_y;          startMV.y = start_y;
1566    
1567          /* Get maximum range */          /* Get maximum range */
1568          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,
1569                    x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
1570    
1571          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
1572          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1573            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
1574            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
1575            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
1576          }               /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          }
1577    
1578            /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
1579            //bPredEq = get_pmvdata(pMBs, (x >> 1), (y >> 1), iWcount, iSubBlock, pmv, psad);
1580            bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
1581    
1582          bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);          if ((x == 0) && (y == 0)) {
   
         if ((x==0) && (y==0) )  
         {  
1583                  threshA =  512/4;                  threshA =  512/4;
1584                  threshB = 1024/4;                  threshB = 1024/4;
1585    
1586          }          } else {
         else  
         {  
1587                  threshA = psad[0]/4;                    /* good estimate */                  threshA = psad[0]/4;                    /* good estimate */
1588                  threshB = threshA+256/4;                  threshB = threshA+256/4;
1589                  if (threshA< 512/4) threshA =  512/4;                  if (threshA < 512 / 4)
1590                  if (threshA>1024/4) threshA = 1024/4;                          threshA = 512 / 4;
1591                  if (threshB>1792/4) threshB = 1792/4;                  if (threshA > 1024 / 4)
1592                            threshA = 1024 / 4;
1593                    if (threshB > 1792 / 4)
1594                            threshB = 1792 / 4;
1595          }          }
1596    
1597          iFound=0;          iFound=0;
# Line 1573  Line 1618 
1618    
1619          *currMV = startMV;          *currMV = startMV;
1620    
1621          iMinSAD = sad8( cur,          iMinSAD =
1622                          get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  sad8(cur,
1623                          iEdgedWidth);                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
1624          iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode, iQuant);                                                  iEdgedWidth), iEdgedWidth);
1625            iMinSAD +=
1626                    calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y,
1627                                             (uint8_t) iFcode, iQuant);
1628    
1629          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock]))          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock]))
1630                                  && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )                                                                  && ((int32_t) iMinSAD <
1631          {                                                                          prevMB->sad8[iSubBlock]))) {
1632                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1633                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
1634                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1629  Line 1677 
1677          if (!MVzero(prevMB->mvs[iSubBlock]))          if (!MVzero(prevMB->mvs[iSubBlock]))
1678          if (!MVequal(prevMB->mvs[iSubBlock],startMV))          if (!MVequal(prevMB->mvs[iSubBlock],startMV))
1679          if (!MVequal(prevMB->mvs[iSubBlock],pmv[0]))          if (!MVequal(prevMB->mvs[iSubBlock],pmv[0]))
1680          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);                                  CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,
1681                                                                            prevMB->mvs[iSubBlock].y);
1682    
1683          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
1684          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
1685                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
1686                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1687                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
1688                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
1689                          goto PMVfast8_Terminate_with_Refine;                          goto PMVfast8_Terminate_with_Refine;
1690          }          }
1691    
   
1692  // left neighbour, if allowed and needed  // left neighbour, if allowed and needed
1693          if (!MVzero(pmv[1]))          if (!MVzero(pmv[1]))
1694          if (!MVequal(pmv[1],startMV))          if (!MVequal(pmv[1],startMV))
1695          if (!MVequal(pmv[1],prevMB->mvs[iSubBlock]))          if (!MVequal(pmv[1],prevMB->mvs[iSubBlock]))
1696          if (!MVequal(pmv[1],pmv[0]))                                  if (!MVequal(pmv[1], pmv[0])) {
1697          {                                          if (!(MotionFlags & PMV_HALFPEL8)) {
1698                  if (!(MotionFlags & PMV_HALFPEL8 ))                                                  pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
1699                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
1700                  }                  }
1701                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1702          }          }
   
1703  // top neighbour, if allowed and needed  // top neighbour, if allowed and needed
1704          if (!MVzero(pmv[2]))          if (!MVzero(pmv[2]))
1705          if (!MVequal(pmv[2],startMV))          if (!MVequal(pmv[2],startMV))
1706          if (!MVequal(pmv[2],prevMB->mvs[iSubBlock]))          if (!MVequal(pmv[2],prevMB->mvs[iSubBlock]))
1707          if (!MVequal(pmv[2],pmv[0]))          if (!MVequal(pmv[2],pmv[0]))
1708          if (!MVequal(pmv[2],pmv[1]))                                          if (!MVequal(pmv[2], pmv[1])) {
1709          {                                                  if (!(MotionFlags & PMV_HALFPEL8)) {
1710                  if (!(MotionFlags & PMV_HALFPEL8 ))                                                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
1711                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
1712                  }                  }
1713                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
# Line 1672  Line 1718 
1718          if (!MVequal(pmv[3],prevMB->mvs[iSubBlock]))          if (!MVequal(pmv[3],prevMB->mvs[iSubBlock]))
1719          if (!MVequal(pmv[3],pmv[0]))          if (!MVequal(pmv[3],pmv[0]))
1720          if (!MVequal(pmv[3],pmv[1]))          if (!MVequal(pmv[3],pmv[1]))
1721          if (!MVequal(pmv[3],pmv[2]))                                                                                          if (!MVequal(pmv[3], pmv[2])) {
1722                  {                                                                                                  if (!
1723                          if (!(MotionFlags & PMV_HALFPEL8 ))                                                                                                          (MotionFlags &
1724                          {       pmv[3].x = EVEN(pmv[3].x);                                                                                                           PMV_HALFPEL8)) {
1725                                                                                                            pmv[3].x = EVEN(pmv[3].x);
1726                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
1727                          }                          }
1728                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                                  CHECK_MV8_CANDIDATE(pmv[3].x,
1729                                                                                                                                            pmv[3].y);
1730                  }                  }
1731          }          }
1732    
1733          if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )          if ((MVzero(*currMV)) &&
1734                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1735                  iMinSAD -= MV8_00_BIAS;                  iMinSAD -= MV8_00_BIAS;
1736    
1737    
# Line 1690  Line 1739 
1739     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.
1740  */  */
1741    
1742          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
1743          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
1744                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
1745                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1746                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
1747                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1711  Line 1761 
1761          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1762    
1763  /* 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 */
1764          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1765                                           x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
1766                                           currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,
1767                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1768                                                      iQuant, iFound);
1769    
1770          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1771                  *currMV = newMV;                  *currMV = newMV;
1772                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1773          }          }
1774    
1775          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
1776  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1777    
1778                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1779                  {       iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1780                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1781                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,
1782                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1783                                                                      iDiamondSize, iFcode, iQuant, iFound);
1784    
1785                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1786                          *currMV = newMV;                          *currMV = newMV;
1787                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1788                  }                  }
1789                  }                  }
1790    
1791                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1792                  {       iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1793                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1794                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,
1795                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
1796                                                                      iQuant, iFound);
1797    
1798                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1799                          *currMV = newMV;                          *currMV = newMV;
1800                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1801                  }                  }
# Line 1759  Line 1808 
1808    
1809  PMVfast8_Terminate_with_Refine:  PMVfast8_Terminate_with_Refine:
1810          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
1811                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1812                                                   x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1813                                                   currMV, iMinSAD,                                                          iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,
1814                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
1815    
1816    
1817  PMVfast8_Terminate_without_Refine:  PMVfast8_Terminate_without_Refine:
# Line 1772  Line 1821 
1821          return iMinSAD;          return iMinSAD;
1822  }  }
1823    
1824  int32_t EPZSSearch16(  int32_t
1825                                          const uint8_t * const pRef,  EPZSSearch16(const uint8_t * const pRef,
1826                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1827                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1828                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1829                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1830                                          const int x, const int y,                           const int x,
1831                             const int y,
1832                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1833                                          const uint32_t iQuant,                                          const uint32_t iQuant,
1834                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1809  Line 1859 
1859          int32_t psad[8];          int32_t psad[8];
1860    
1861          static MACROBLOCK * oldMBs = NULL;          static MACROBLOCK * oldMBs = NULL;
1862    
1863  //      const MACROBLOCK * const pMB = pMBs + x + y * iWcount;  //      const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
1864          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1865          MACROBLOCK * oldMB = NULL;          MACROBLOCK * oldMB = NULL;
1866    
1867          static int32_t thresh2;           int32_t thresh2;
1868          int32_t bPredEq;          int32_t bPredEq;
1869          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
1870    
1871          MainSearch16FuncPtr MainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
1872    
1873          if (oldMBs == NULL)          if (oldMBs == NULL) {
1874          {       oldMBs = (MACROBLOCK*) calloc(iWcount*iHcount,sizeof(MACROBLOCK));                  oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
1875  //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));  //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
1876          }          }
1877          oldMB = oldMBs + x + y * iWcount;          oldMB = oldMBs + x + y * iWcount;
1878    
1879  /* Get maximum range */  /* Get maximum range */
1880          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,
1881                          x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
1882    
1883          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
1884          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1885            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
1886            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
1887            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
1888          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
1889            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1890          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1891            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1892    
1893  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1894          MinSAD=SAD          MinSAD=SAD
# Line 1848  Line 1900 
1900  // Prepare for main loop  // Prepare for main loop
1901    
1902          *currMV=pmv[0];         /* current best := median prediction */          *currMV=pmv[0];         /* current best := median prediction */
1903          if (!(MotionFlags & PMV_HALFPEL16))          if (!(MotionFlags & PMV_HALFPEL16)) {
         {  
1904                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1905                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
1906          }          }
# Line 1865  Line 1916 
1916    
1917  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
1918    
1919          iMinSAD = sad16( cur,          iMinSAD =
1920                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1921                  iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1922          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1923            iMinSAD +=
1924                    calc_delta_16(currMV->x - pmv[0].x, currMV->y - pmv[0].y,
1925                                              (uint8_t) iFcode, iQuant);
1926    
1927  // thresh1 is fixed to 256  // thresh1 is fixed to 256
1928          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV, prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ((iMinSAD < 256) ||
1929                  {                  ((MVequal(*currMV, prevMB->mvs[0])) &&
1930                     ((int32_t) iMinSAD < prevMB->sad16))) {
1931                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
1932                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
1933                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1887  Line 1942 
1942  // set threshhold based on Min of Prediction and SAD of collocated block  // set threshhold based on Min of Prediction and SAD of collocated block
1943  // 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
1944    
1945          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1946                  thresh2 =  512;                  thresh2 =  512;
1947          }          } else {
         else  
         {  
1948  /* 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] */
1949    
1950                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
# Line 1904  Line 1956 
1956    
1957    
1958  // left neighbour, if allowed  // left neighbour, if allowed
1959          if (x != 0)          if (x != 0) {
1960          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
1961                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
1962                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
1963                  }                  }
1964                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1965          }          }
   
1966  // top neighbour, if allowed  // top neighbour, if allowed
1967          if (y != 0)          if (y != 0) {
1968          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
1969                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
1970                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
1971                  }                  }
1972                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1973    
1974  // top right neighbour, if allowed  // top right neighbour, if allowed
1975                  if ((uint32_t)x != (iWcount-1))                  if ((uint32_t) x != (iWcount - 1)) {
1976                  {                          if (!(MotionFlags & PMV_HALFPEL16)) {
1977                          if (!(MotionFlags & PMV_HALFPEL16 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
1978                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
1979                          }                          }
1980                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
# Line 1938  Line 1986 
1986  */  */
1987    
1988          if ( (iMinSAD <= thresh2)          if ( (iMinSAD <= thresh2)
1989                  || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )                  || (MVequal(*currMV, prevMB->mvs[0]) &&
1990                  {                          ((int32_t) iMinSAD <= prevMB->sad16))) {
1991                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
1992                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
1993                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1960  Line 2008 
2008    
2009  // top neighbour  // top neighbour
2010          if (y != 0)          if (y != 0)
2011                  CHECK_MV16_CANDIDATE((prevMB-iWcount)->mvs[0].x,(prevMB-iWcount)->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,
2012                                                             (prevMB - iWcount)->mvs[0].y);
2013    
2014  // 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
2015    
# Line 1969  Line 2018 
2018    
2019  // bottom neighbour, dito  // bottom neighbour, dito
2020          if ((uint32_t)y != iHcount-1)          if ((uint32_t)y != iHcount-1)
2021                  CHECK_MV16_CANDIDATE((prevMB+iWcount)->mvs[0].x,(prevMB+iWcount)->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,
2022                                                             (prevMB + iWcount)->mvs[0].y);
2023    
2024  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
2025          if (iMinSAD <= thresh2)          if (iMinSAD <= thresh2) {
                 {  
2026                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2027                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2028                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1984  Line 2033 
2033    
2034          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2035    
2036          if (MotionFlags & PMV_USESQUARES8)          if (MotionFlags & PMV_USESQUARES16)
2037                  MainSearchPtr = Square16_MainSearch;                  MainSearchPtr = Square16_MainSearch;
2038          else          else
2039             if (MotionFlags & PMV_ADVANCEDDIAMOND16)
         if (MotionFlags & PMV_ADVANCEDDIAMOND8)  
2040                  MainSearchPtr = AdvDiamond16_MainSearch;                  MainSearchPtr = AdvDiamond16_MainSearch;
2041          else          else
2042                  MainSearchPtr = Diamond16_MainSearch;                  MainSearchPtr = Diamond16_MainSearch;
2043    
2044  /* 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 */
2045    
2046          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2047                          x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2048                          currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,
2049                          2, iFcode, iQuant, 0);                                                    min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2050    
2051          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2052                  *currMV = newMV;                  *currMV = newMV;
2053                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2054          }          }
2055    
2056    
2057          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
2058  /* 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) */
2059    
2060                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2061                  {                          iSAD =
2062                          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2063                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,
2064                                  pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2065                                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    2, iFcode, iQuant, 0);
2066                  }                  }
2067    
2068                  if (iSAD < iMinSAD)                  if (iSAD < iMinSAD) {
                 {  
2069                          *currMV = newMV;                          *currMV = newMV;
2070                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2071                  }                  }
2072    
2073                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2074                  {                          iSAD =
2075                          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2076                                  x, y,                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,
2077                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
                         pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);  
2078    
2079                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2080                                  *currMV = newMV;                                  *currMV = newMV;
2081                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2082                          }                          }
# Line 2044  Line 2087 
2087    
2088  EPZS16_Terminate_with_Refine:  EPZS16_Terminate_with_Refine:
2089          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
2090                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2091                                  x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2092                                  currMV, iMinSAD,                                                           iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,
2093                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
2094    
2095  EPZS16_Terminate_without_Refine:  EPZS16_Terminate_without_Refine:
2096    
# Line 2059  Line 2102 
2102  }  }
2103    
2104    
2105  int32_t EPZSSearch8(  int32_t
2106                                          const uint8_t * const pRef,  EPZSSearch8(const uint8_t * const pRef,
2107                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2108                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2109                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2110                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2111                                          const int x, const int y,                          const int x,
2112                                          const int start_x, const int start_y,                          const int y,
2113                            const int start_x,
2114                            const int start_y,
2115                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2116                                          const uint32_t iQuant,                                          const uint32_t iQuant,
2117                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 2109  Line 2154 
2154          MainSearch8FuncPtr MainSearchPtr;          MainSearch8FuncPtr MainSearchPtr;
2155    
2156  /* Get maximum range */  /* Get maximum range */
2157          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,
2158                          x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2159    
2160  /* 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 */
2161    
2162          if (!(MotionFlags & PMV_HALFPEL8 ))          if (!(MotionFlags & PMV_HALFPEL8)) {
2163          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2164            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2165            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2166            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2167          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2168            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2169          bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);          //bPredEq = get_pmvdata(pMBs, x >> 1, y >> 1, iWcount, iSubBlock, pmv, psad);
2170            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2171    
2172    
2173  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
# Line 2134  Line 2180 
2180  // Prepare for main loop  // Prepare for main loop
2181    
2182    
2183          if (!(MotionFlags & PMV_HALFPEL8))          if (!(MotionFlags & PMV_HALFPEL8)) {
         {  
2184                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2185                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2186          }          }
# Line 2152  Line 2197 
2197  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2198    
2199    
2200          iMinSAD = sad8( cur,          iMinSAD =
2201                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  sad8(cur,
2202                  iEdgedWidth);                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2203          iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);                                                  iEdgedWidth), iEdgedWidth);
2204            iMinSAD +=
2205                    calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y,
2206                                             (uint8_t) iFcode, iQuant);
2207    
2208    
2209  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2210          if (iMinSAD < 256/4 )          if (iMinSAD < 256 / 4) {
                 {  
2211                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2212                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2213                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
# Line 2177  Line 2224 
2224          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
2225    
2226  // left neighbour, if allowed  // left neighbour, if allowed
2227          if (psad[1] != MV_MAX_ERROR)          if (psad[1] != MV_MAX_ERROR) {
2228          {                  if (!(MotionFlags & PMV_HALFPEL8)) {
2229                  if (!(MotionFlags & PMV_HALFPEL8 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2230                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2231                  }                  }
2232                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
2233          }          }
   
2234  // top neighbour, if allowed  // top neighbour, if allowed
2235          if (psad[2] != MV_MAX_ERROR)          if (psad[2] != MV_MAX_ERROR) {
2236          {                  if (!(MotionFlags & PMV_HALFPEL8)) {
2237                  if (!(MotionFlags & PMV_HALFPEL8 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2238                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2239                  }                  }
2240                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
2241    
2242  // top right neighbour, if allowed  // top right neighbour, if allowed
2243                  if (psad[3] != MV_MAX_ERROR)                  if (psad[3] != MV_MAX_ERROR) {
2244                  {                          if (!(MotionFlags & PMV_HALFPEL8)) {
2245                          if (!(MotionFlags & PMV_HALFPEL8 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2246                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2247                          }                          }
2248                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);
# Line 2217  Line 2260 
2260     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
2261  */  */
2262    
2263          if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */          if (iMinSAD < 512 / 4) {        /* T_2 == 512/4 hardcoded */
                 {  
2264                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2265                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2266                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
# Line 2245  Line 2287 
2287          else          else
2288                  MainSearchPtr = Diamond8_MainSearch;                  MainSearchPtr = Diamond8_MainSearch;
2289    
2290          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2291                  x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2292                  currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,
2293                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2294                  iDiamondSize, iFcode, iQuant, 0);                                                    iQuant, 0);
2295    
2296    
2297          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2298                  *currMV = newMV;                  *currMV = newMV;
2299                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2300          }          }
2301    
2302          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2303  /* 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) */
2304    
2305                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2306                  {                          iSAD =
2307                          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2308                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,
2309                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2310                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, 0);
2311    
2312                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2313                                  *currMV = newMV;                                  *currMV = newMV;
2314                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2315                          }                          }
2316                  }                  }
2317    
2318                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2319                  {                          iSAD =
2320                          iSAD = (*MainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2321                                  x, y,                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,
2322                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2323                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iQuant, 0);
2324    
2325                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2326                                  *currMV = newMV;                                  *currMV = newMV;
2327                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2328                          }                          }
# Line 2295  Line 2333 
2333    
2334  EPZS8_Terminate_with_Refine:  EPZS8_Terminate_with_Refine:
2335          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2336                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2337                                  x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2338                                  currMV, iMinSAD,                                                          iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,
2339                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2340    
2341  EPZS8_Terminate_without_Refine:  EPZS8_Terminate_without_Refine:
2342    
# Line 2309  Line 2347 
2347    
2348    
2349    
2350    int32_t
2351    PMVfastIntSearch16(const uint8_t * const pRef,
2352                                    const uint8_t * const pRefH,
2353                                    const uint8_t * const pRefV,
2354                                    const uint8_t * const pRefHV,
2355                                    const IMAGE * const pCur,
2356                                    const int x,
2357                                    const int y,
2358                                    const uint32_t MotionFlags,
2359                                    const uint32_t iQuant,
2360                                    const uint32_t iFcode,
2361                                    const MBParam * const pParam,
2362                                    const MACROBLOCK * const pMBs,
2363                                    const MACROBLOCK * const prevMBs,
2364                                    VECTOR * const currMV,
2365                                    VECTOR * const currPMV)
2366    {
2367            const uint32_t iWcount = pParam->mb_width;
2368            const int32_t iWidth = pParam->width;
2369            const int32_t iHeight = pParam->height;
2370            const int32_t iEdgedWidth = pParam->edged_width;
2371    
2372            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
2373            const VECTOR zeroMV = { 0, 0 };
2374    
2375            int32_t iDiamondSize;
2376    
2377            int32_t min_dx;
2378            int32_t max_dx;
2379            int32_t min_dy;
2380            int32_t max_dy;
2381    
2382            int32_t iFound;
2383    
2384            VECTOR newMV;
2385            VECTOR backupMV;                        /* just for PMVFAST */
2386    
2387            VECTOR pmv[4];
2388            int32_t psad[4];
2389    
2390            MainSearch16FuncPtr MainSearchPtr;
2391    
2392            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2393            MACROBLOCK *const pMB = pMBs + x + y * iWcount;
2394    
2395            int32_t threshA, threshB;
2396            int32_t bPredEq;
2397            int32_t iMinSAD, iSAD;
2398    
2399    /* Get maximum range */
2400            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2401                              iFcode);
2402    
2403    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2404    
2405            if ((x == 0) && (y == 0)) {
2406                    threshA = 512;
2407                    threshB = 1024;
2408    
2409                    bPredEq = 0;
2410                    psad[0] = psad[1] = psad[2] = psad[3] = 0;
2411                    *currMV = pmv[0] = pmv[1] = pmv[2] = pmv[3] = zeroMV;
2412    
2413            } else {
2414                    threshA = psad[0];
2415                    threshB = threshA + 256;
2416                    if (threshA < 512)
2417                            threshA = 512;
2418                    if (threshA > 1024)
2419                            threshA = 1024;
2420                    if (threshB > 1792)
2421                            threshB = 1792;
2422    
2423                    bPredEq = get_ipmvdata(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2424                    *currMV = pmv[0];                       /* current best := prediction */
2425            }
2426    
2427            iFound = 0;
2428    
2429    /* Step 4: Calculate SAD around the Median prediction.
2430       MinSAD=SAD
2431       If Motion Vector equal to Previous frame motion vector
2432       and MinSAD<PrevFrmSAD goto Step 10.
2433       If SAD<=256 goto Step 10.
2434    */
2435    
2436            if (currMV->x > max_dx) {
2437                    currMV->x = EVEN(max_dx);
2438            }
2439            if (currMV->x < min_dx) {
2440                    currMV->x = EVEN(min_dx);
2441            }
2442            if (currMV->y > max_dy) {
2443                    currMV->y = EVEN(max_dy);
2444            }
2445            if (currMV->y < min_dy) {
2446                    currMV->y = EVEN(min_dy);
2447            }
2448    
2449            iMinSAD =
2450                    sad16(cur,
2451                              get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2452                                                     iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2453            iMinSAD +=
2454                    calc_delta_16(currMV->x - pmv[0].x, currMV->y - pmv[0].y,
2455                                              (uint8_t) iFcode, iQuant);
2456    
2457            if ((iMinSAD < 256) ||
2458                    ((MVequal(*currMV, prevMB->i_mvs[0])) &&
2459                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2460                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
2461                    {
2462                            if (!MVzero(*currMV)) {
2463                                    iMinSAD += MV16_00_BIAS;
2464                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
2465                                    iMinSAD -= MV16_00_BIAS;
2466                            }
2467                    }
2468    
2469                    if (MotionFlags & PMV_EARLYSTOP16)
2470                            goto PMVfastInt16_Terminate_with_Refine;
2471            }
2472    
2473    
2474    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2475       vector of the median.
2476       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2477    */
2478    
2479            if ((bPredEq) && (MVequal(pmv[0], prevMB->i_mvs[0])))
2480                    iFound = 2;
2481    
2482    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2483       Otherwise select large Diamond Search.
2484    */
2485    
2486            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
2487                    iDiamondSize = 2;               // halfpel units!
2488            else
2489                    iDiamondSize = 4;               // halfpel units!
2490    
2491    /*
2492       Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
2493       Also calculate (0,0) but do not subtract offset.
2494       Let MinSAD be the smallest SAD up to this point.
2495       If MV is (0,0) subtract offset.
2496    */
2497    
2498    // (0,0) is often a good choice
2499    
2500            if (!MVzero(pmv[0]))
2501                    CHECK_MV16_ZERO;
2502    
2503    // previous frame MV is always possible
2504    
2505            if (!MVzero(prevMB->i_mvs[0]))
2506                    if (!MVequal(prevMB->i_mvs[0], pmv[0]))
2507                            CHECK_MV16_CANDIDATE(prevMB->i_mvs[0].x, prevMB->i_mvs[0].y);
2508    
2509    // left neighbour, if allowed
2510    
2511            if (!MVzero(pmv[1]))
2512                    if (!MVequal(pmv[1], prevMB->i_mvs[0]))
2513                            if (!MVequal(pmv[1], pmv[0]))
2514                                    CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
2515    
2516    // top neighbour, if allowed
2517            if (!MVzero(pmv[2]))
2518                    if (!MVequal(pmv[2], prevMB->i_mvs[0]))
2519                            if (!MVequal(pmv[2], pmv[0]))
2520                                    if (!MVequal(pmv[2], pmv[1]))
2521                                            CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
2522    
2523    // top right neighbour, if allowed
2524                                            if (!MVzero(pmv[3]))
2525                                                    if (!MVequal(pmv[3], prevMB->i_mvs[0]))
2526                                                            if (!MVequal(pmv[3], pmv[0]))
2527                                                                    if (!MVequal(pmv[3], pmv[1]))
2528                                                                            if (!MVequal(pmv[3], pmv[2]))
2529                                                                                    CHECK_MV16_CANDIDATE(pmv[3].x,
2530                                                                                                                             pmv[3].y);
2531    
2532            if ((MVzero(*currMV)) &&
2533                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2534                    iMinSAD -= MV16_00_BIAS;
2535    
2536    
2537    /* Step 6: If MinSAD <= thresa goto Step 10.
2538       If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
2539    */
2540    
2541            if ((iMinSAD <= threshA) ||
2542                    (MVequal(*currMV, prevMB->i_mvs[0]) &&
2543                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2544    
2545                    if (MotionFlags & PMV_EARLYSTOP16)
2546                            goto PMVfastInt16_Terminate_with_Refine;
2547            }
2548    
2549    
2550    /************ (Diamond Search)  **************/
2551    /*
2552       Step 7: Perform Diamond search, with either the small or large diamond.
2553       If Found=2 only examine one Diamond pattern, and afterwards goto step 10
2554       Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
2555       If center then goto step 10.
2556       Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
2557       Refine by using small diamond and goto step 10.
2558    */
2559    
2560            if (MotionFlags & PMV_USESQUARES16)
2561                    MainSearchPtr = Square16_MainSearch;
2562            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2563                    MainSearchPtr = AdvDiamond16_MainSearch;
2564            else
2565                    MainSearchPtr = Diamond16_MainSearch;
2566    
2567            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2568    
2569    
2570    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2571            iSAD =
2572                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2573                                                      currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,
2574                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2575                                                      iQuant, iFound);
2576    
2577            if (iSAD < iMinSAD) {
2578                    *currMV = newMV;
2579                    iMinSAD = iSAD;
2580            }
2581    
2582            if (MotionFlags & PMV_EXTSEARCH16) {
2583    /* extended: search (up to) two more times: orignal prediction and (0,0) */
2584    
2585                    if (!(MVequal(pmv[0], backupMV))) {
2586                            iSAD =
2587                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2588                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,
2589                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2590                                                                      iDiamondSize, iFcode, iQuant, iFound);
2591    
2592                            if (iSAD < iMinSAD) {
2593                                    *currMV = newMV;
2594                                    iMinSAD = iSAD;
2595                            }
2596                    }
2597    
2598                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2599                            iSAD =
2600                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2601                                                                      iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,
2602                                                                      max_dy, iEdgedWidth, iDiamondSize, iFcode,
2603                                                                      iQuant, iFound);
2604    
2605                            if (iSAD < iMinSAD) {
2606                                    *currMV = newMV;
2607                                    iMinSAD = iSAD;
2608                            }
2609                    }
2610            }
2611    
2612    /*
2613       Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.
2614    */
2615    
2616    PMVfastInt16_Terminate_with_Refine:
2617    
2618            pMB->i_mvs[0] = pMB->i_mvs[1] = pMB->i_mvs[2] = pMB->i_mvs[3] = pMB->i_mv16 = *currMV;
2619            pMB->i_sad8[0] = pMB->i_sad8[1] = pMB->i_sad8[2] = pMB->i_sad8[3] = pMB->i_sad16 = iMinSAD;
2620    
2621            if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
2622                    iMinSAD =
2623                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2624                                                             iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,
2625                                                             iFcode, iQuant, iEdgedWidth);
2626    
2627            pmv[0] = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          // get _REAL_ prediction (halfpel possible)
2628    
2629    PMVfastInt16_Terminate_without_Refine:
2630            currPMV->x = currMV->x - pmv[0].x;
2631            currPMV->y = currMV->y - pmv[0].y;
2632            return iMinSAD;
2633    }
2634    
2635    
2636    
2637  /* ***********************************************************  /* ***********************************************************
# Line 2317  Line 2640 
2640  ***************************************************************/  ***************************************************************/
2641    
2642    
2643  void MotionEstimationBVOP(  void
2644                          MBParam * const pParam,  MotionEstimationBVOP(MBParam * const pParam,
2645                          FRAMEINFO * const frame,                          FRAMEINFO * const frame,
   
2646                          // forward (past) reference                          // forward (past) reference
2647                          const MACROBLOCK * const f_mbs,                          const MACROBLOCK * const f_mbs,
2648                      const IMAGE * const f_ref,                      const IMAGE * const f_ref,
# Line 2349  Line 2671 
2671          VECTOR pmv_dontcare;          VECTOR pmv_dontcare;
2672    
2673          // note: i==horizontal, j==vertical          // note: i==horizontal, j==vertical
2674      for (j = 0; j < mb_height; j++)          for (j = 0; j < mb_height; j++) {
2675          {                  for (i = 0; i < mb_width; i++) {
                 for (i = 0; i < mb_width; i++)  
                 {  
2676                          MACROBLOCK *mb = &frame->mbs[i + j*mb_width];                          MACROBLOCK *mb = &frame->mbs[i + j*mb_width];
2677                          const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];                          const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];
2678                          const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];                          const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];
2679    
2680                          if (b_mb->mode == MODE_INTER                          if (b_mb->mode == MODE_INTER && b_mb->cbp == 0 &&
2681                                  && b_mb->cbp == 0                                  b_mb->mvs[0].x == 0 && b_mb->mvs[0].y == 0) {
                                 && b_mb->mvs[0].x == 0  
                                 && b_mb->mvs[0].y == 0)  
                         {  
2682                                  mb->mode = MODE_NOT_CODED;                                  mb->mode = MODE_NOT_CODED;
2683                                  mb->mvs[0].x = 0;                                  mb->mvs[0].x = 0;
2684                                  mb->mvs[0].y = 0;                                  mb->mvs[0].y = 0;
# Line 2369  Line 2686 
2686                                  mb->b_mvs[0].y = 0;                                  mb->b_mvs[0].y = 0;
2687                                  continue;                                  continue;
2688                          }                          }
2689                    /* force F_SAD16
2690                            f_sad16 = 100;
2691                            b_sad16 = 65535;
2692    
2693                            mb->mode = MODE_FORWARD;
2694                            mb->mvs[0].x = 1;
2695                            mb->mvs[0].y = 1;
2696                            mb->b_mvs[0].x = 1;
2697                            mb->b_mvs[0].y = 1;
2698                            continue;
2699                     ^^ force F_SAD16 */
2700    
2701    
2702                          // forward search                          // forward search
2703                          f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                          f_sad16 =
2704                                                  &frame->image,                                  SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2705                                                  i, j,                                                   &frame->image, i, j, frame->motion_flags,
2706                                                  frame->motion_flags,  frame->quant, frame->fcode,                                                   frame->quant, frame->fcode, pParam,
2707                                                  pParam,                                                   f_mbs,  f_mbs, /* todo */
                                                 f_mbs, f_mbs /* todo */,  
2708                                                  &mb->mvs[0], &pmv_dontcare);    // ignore pmv                                                  &mb->mvs[0], &pmv_dontcare);    // ignore pmv
2709    
2710                          // backward search                          // backward search
2711                          b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,                          b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2712                                                  &frame->image,                                                  &frame->image, i, j, frame->motion_flags,
2713                                                  i, j,                                                  frame->quant, frame->bcode, pParam,
                                                 frame->motion_flags,  frame->quant, frame->bcode,  
                                                 pParam,  
2714                                                  b_mbs, b_mbs, /* todo */                                                  b_mbs, b_mbs, /* todo */
2715                                                  &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv                                                  &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv
2716    
2717                          // interpolate search (simple, but effective)                          // interpolate search (simple, but effective)
2718                          i_sad16 = sad16bi_c(                          i_sad16 = 65535;
2719                                          frame->image.y + i*16 + j*16*edged_width,  
2720                            /*
2721                            x/y range somewhat buggy
2722                            i_sad16 =
2723                                    sad16bi_c(frame->image.y + i * 16 + j * 16 * edged_width,
2724                                          get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                                          get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2725                                                  i, j, 16, mb->mvs[0].x, mb->mvs[0].y, edged_width),                                                                    i, j, 16, mb->mvs[0].x, mb->mvs[0].y,
2726                                          get_ref(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,                                                                    edged_width), get_ref(b_ref->y, b_refH->y,
2727                                                  i, j, 16, mb->b_mvs[0].x, mb->b_mvs[0].x, edged_width),                                                                                                                  b_refV->y, b_refHV->y,
2728                                                                                                                    i, j, 16,
2729                                                                                                                    mb->b_mvs[0].x,
2730                                                                                                                    mb->b_mvs[0].x,
2731                                                                                                                    edged_width),
2732                                          edged_width);                                          edged_width);
2733                            */
2734    
2735                          // TODO: direct search                          // TODO: direct search
2736                          // predictor + range of [-32,32]                          // predictor + range of [-32,32]
2737                          d_sad16 = 65535;                          d_sad16 = 65535;
2738    
2739    
2740                          if (f_sad16 < b_sad16)                          if (f_sad16 < b_sad16) {
                         {  
2741                                  best_sad = f_sad16;                                  best_sad = f_sad16;
2742                                  mb->mode = MODE_FORWARD;                                  mb->mode = MODE_FORWARD;
2743                          }                          } else {
                         else  
                         {  
2744                                  best_sad = b_sad16;                                  best_sad = b_sad16;
2745                                  mb->mode = MODE_BACKWARD;                                  mb->mode = MODE_BACKWARD;
2746                          }                          }
2747    
2748                          if (i_sad16 < best_sad)                          if (i_sad16 < best_sad) {
                         {  
2749                                  best_sad = i_sad16;                                  best_sad = i_sad16;
2750                                  mb->mode = MODE_INTERPOLATE;                                  mb->mode = MODE_INTERPOLATE;
2751                          }                          }
2752    
2753                          if (d_sad16 < best_sad)                          if (d_sad16 < best_sad) {
                         {  
2754                                  best_sad = d_sad16;                                  best_sad = d_sad16;
2755                                  mb->mode = MODE_DIRECT;                                  mb->mode = MODE_DIRECT;
2756                          }                          }

Legend:
Removed from v.184  
changed lines
  Added in v.300

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