[svn] / trunk / xvidcore / src / motion / motion_est.c Repository:
ViewVC logotype

Diff of /trunk/xvidcore/src/motion/motion_est.c

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

revision 174, Sat May 11 23:54:30 2002 UTC revision 345, Sat Jul 27 23:47:01 2002 UTC
# Line 1  Line 1 
1  /**************************************************************************  /**************************************************************************
2   *   *
3     *      XVID MPEG-4 VIDEO CODEC
4     *      motion estimation
5     *
6     *      This program is an implementation of a part of one or more MPEG-4
7     *      Video tools as specified in ISO/IEC 14496-2 standard.  Those intending
8     *      to use this software module in hardware or software products are
9     *      advised that its use may infringe existing patents or copyrights, and
10     *      any such use would be at such party's own risk.  The original
11     *      developer of this software module and his/her company, and subsequent
12     *      editors and their companies, will have no liability for use of this
13     *      software or modifications or derivatives thereof.
14     *
15     *      This program is free software; you can redistribute it and/or modify
16     *      it under the terms of the GNU General Public License as published by
17     *      the Free Software Foundation; either version 2 of the License, or
18     *      (at your option) any later version.
19     *
20     *      This program is distributed in the hope that it will be useful,
21     *      but WITHOUT ANY WARRANTY; without even the implied warranty of
22     *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23     *      GNU General Public License for more details.
24     *
25     *      You should have received a copy of the GNU General Public License
26     *      along with this program; if not, write to the Free Software
27     *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28     *
29     *************************************************************************/
30    
31    /**************************************************************************
32     *
33   *  Modifications:   *  Modifications:
34   *   *
35   *      01.05.2002      updated MotionEstimationBVOP   *      01.05.2002      updated MotionEstimationBVOP
# Line 47  Line 77 
77  #include "motion.h"  #include "motion.h"
78  #include "sad.h"  #include "sad.h"
79    
 // very large value  
 #define MV_MAX_ERROR    (4096 * 256)  
   
 // stop search if sdelta < THRESHOLD  
 #define MV16_THRESHOLD  192  
 #define MV8_THRESHOLD   56  
   
 #define NEIGH_MOVE_THRESH 8  
 // 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,
163          const IMAGE * const pRefV,          const IMAGE * const pRefV,
164          const IMAGE * const pRefHV,          const IMAGE * const pRefHV,
165          const uint32_t iLimit)          const uint32_t iLimit)
   
166  {  {
167          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
168          const uint32_t iHcount = pParam->mb_height;          const uint32_t iHcount = pParam->mb_height;
169          MACROBLOCK * const pMBs = current->mbs;          MACROBLOCK * const pMBs = current->mbs;
170          MACROBLOCK * const prevMBs = reference->mbs;    // previous frame          MACROBLOCK *const prevMBs = reference->mbs;
   
171          const IMAGE * const pCurrent = &current->image;          const IMAGE * const pCurrent = &current->image;
172          const IMAGE * const pRef = &reference->image;          const IMAGE * const pRef = &reference->image;
173    
174          const VECTOR zeroMV = {0,0};          static const VECTOR zeroMV = { 0, 0 };
175            VECTOR predMV;
176    
177          int32_t x, y;          int32_t x, y;
178          int32_t iIntra = 0;          int32_t iIntra = 0;
# Line 291  Line 181 
181          if (sadInit)          if (sadInit)
182                  (*sadInit)();                  (*sadInit)();
183    
184          for (y = 0; y < iHcount; y++)          for (y = 0; y < iHcount; y++)   {
185                  for (x = 0; x < iWcount; x++)                  for (x = 0; x < iWcount; x ++)  {
186                  {  
187                          MACROBLOCK* const pMB = &pMBs[x + y * iWcount];                          MACROBLOCK* const pMB = &pMBs[x + y * iWcount];
188    
189                          pMB->sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                          predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
                                          x, y, current->motion_flags, current->quant, current->fcode,  
                                          pParam, pMBs, prevMBs, &pMB->mv16, &pMB->pmvs[0]);  
                 }  
190    
191          for (y = 0; y < iHcount; y++)                          pMB->sad16 =
192                  for (x = 0; x < iWcount; x++)                                  SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
193                  {                                                   x, y, predMV.x, predMV.y, predMV.x, predMV.y,
194                          MACROBLOCK* const pMB = &pMBs[x + y * iWcount];                                                   current->motion_flags, current->quant,
195                                                     current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,
196                                                     &pMB->pmvs[0]);
197    
198                          if (0 < (pMB->sad16 - MV16_INTER_BIAS))                          if (0 < (pMB->sad16 - MV16_INTER_BIAS)) {
                         {  
199                                  int32_t deviation;                                  int32_t deviation;
200                                  deviation = dev16(pCurrent->y + x*16 + y*16*pParam->edged_width,  
201                                    deviation =
202                                            dev16(pCurrent->y + x * 16 + y * 16 * pParam->edged_width,
203                                                           pParam->edged_width);                                                           pParam->edged_width);
204    
205                                  if (deviation < (pMB->sad16 - MV16_INTER_BIAS))                                  if (deviation < (pMB->sad16 - MV16_INTER_BIAS)) {
                                 {  
206                                          pMB->mode = MODE_INTRA;                                          pMB->mode = MODE_INTRA;
207                                          pMB->mv16 = pMB->mvs[0] = pMB->mvs[1]                                          pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
208                                                                   = pMB->mvs[2] = pMB->mvs[3] = zeroMV;                                                  pMB->mvs[3] = zeroMV;
209                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1]                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
210                                                               = pMB->sad8[2] = pMB->sad8[3] = 0;                                                  pMB->sad8[3] = 0;
211    
212                                          iIntra++;                                          iIntra++;
213                                          if (iIntra >= iLimit)                                          if (iIntra >= iLimit)
# Line 328  Line 217 
217                                  }                                  }
218                          }                          }
219    
220                          if ( (current->global_flags & XVID_INTER4V)                          pmv = pMB->pmvs[0];
221                                  && (!(current->global_flags & XVID_LUMIMASKING)                          if (current->global_flags & XVID_INTER4V)
222                                          || pMB->dquant == NO_CHANGE) )                                  if ((!(current->global_flags & XVID_LUMIMASKING) ||
223                          {                                           pMB->dquant == NO_CHANGE)) {
224                                  int32_t neigh=0;                                          int32_t sad8 = IMV16X16 * current->quant;
225    
226                                  if (x>0)                                          if (sad8 < pMB->sad16) {
227                                  {       neigh += abs((pMB->mv16.x)-((pMB-1)->mv16.x));                                                  sad8 += pMB->sad8[0] =
228                                          neigh += abs((pMB->mv16.y)-((pMB-1)->mv16.y));                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
229                                  }                                                                          pCurrent, 2 * x, 2 * y,
230                                  if (y>0)                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
231                                  {       neigh += abs((pMB->mv16.x)-((pMB-iWcount)->mv16.x));                                                                          current->motion_flags,
232                                          neigh += abs((pMB->mv16.y)-((pMB-iWcount)->mv16.y));                                                                          current->quant, current->fcode, pParam,
233                                  }                                                                          pMBs, prevMBs, &pMB->mvs[0],
234                                  if (x<(iWcount-1))                                                                          &pMB->pmvs[0]);
235                                  {       neigh += abs((pMB->mv16.x)-((pMB+1)->mv16.x));                                          }
236                                          neigh += abs((pMB->mv16.y)-((pMB+1)->mv16.y));                                          if (sad8 < pMB->sad16) {
237                                  }  
238                                  if (y<(iHcount-1))                                                  predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 1);
239                                  {       neigh += abs((pMB->mv16.x)-((pMB+iHcount)->mv16.x));                                                  sad8 += pMB->sad8[1] =
240                                          neigh += abs((pMB->mv16.y)-((pMB+iHcount)->mv16.y));                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
241                                  }                                                                          pCurrent, 2 * x + 1, 2 * y,
242                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
243                                  if (neigh > NEIGH_MOVE_THRESH)                                                                          current->motion_flags,
244                                  {                                                                          current->quant, current->fcode, pParam,
245                                          int32_t sad8 = 129; //IMV16X16 * current->quant;                                                                          pMBs, prevMBs, &pMB->mvs[1],
246                                                                            &pMB->pmvs[1]);
247                                  if (sad8 < pMB->sad16)                                          }
248                                  sad8 += pMB->sad8[0]                                          if (sad8 < pMB->sad16) {
249                                          = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                  predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 2);
250                                                         2*x, 2*y, pMB->mv16.x, pMB->mv16.y,                                                  sad8 += pMB->sad8[2] =
251                                                             current->motion_flags, current->quant, current->fcode,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
252                                                         pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]);                                                                          pCurrent, 2 * x, 2 * y + 1,
253                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
254                                  if (sad8 < pMB->sad16)                                                                          current->motion_flags,
255                                  sad8 += pMB->sad8[1]                                                                          current->quant, current->fcode, pParam,
256                                          = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                                          pMBs, prevMBs, &pMB->mvs[2],
257                                 2*x+1, 2*y, pMB->mv16.x, pMB->mv16.y,                                                                          &pMB->pmvs[2]);
258                                                  current->motion_flags, current->quant, current->fcode,                                          }
259                                                  pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]);                                          if (sad8 < pMB->sad16) {
260                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 3);
261                                  if (sad8 < pMB->sad16)                                                  sad8 += pMB->sad8[3] =
262                                  sad8 += pMB->sad8[2]                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
263                                          = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                                          pCurrent, 2 * x + 1, 2 * y + 1,
264                                                  2*x, 2*y+1, pMB->mv16.x, pMB->mv16.y,                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
265                                                  current->motion_flags, current->quant, current->fcode,                                                                          current->motion_flags,
266                                                  pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]);                                                                          current->quant, current->fcode, pParam,
267                                                                            pMBs, prevMBs,
268                                  if (sad8 < pMB->sad16)                                                                          &pMB->mvs[3],
269                                  sad8 += pMB->sad8[3]                                                                          &pMB->pmvs[3]);
270                                          = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                          }
                                                 2*x+1, 2*y+1, pMB->mv16.x, pMB->mv16.y,  
                                                 current->motion_flags, current->quant, current->fcode,  
                                                 pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]);  
271    
272                          /* decide: MODE_INTER or MODE_INTER4V                          /* decide: MODE_INTER or MODE_INTER4V
273                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
274                          */                          */
275    
276                                  if (sad8 < pMB->sad16)                                          if (sad8 < pMB->sad16) {
                                 {  
277                                          pMB->mode = MODE_INTER4V;                                          pMB->mode = MODE_INTER4V;
278                 pMB->sad8[0] *= 4;                 pMB->sad8[0] *= 4;
279                                          pMB->sad8[1] *= 4;                                          pMB->sad8[1] *= 4;
# Line 396  Line 281 
281                                          pMB->sad8[3] *= 4;                                          pMB->sad8[3] *= 4;
282                                          continue;                                          continue;
283                                  }                                  }
284                                  }  
285                          }                          }
286    
287                          pMB->mode = MODE_INTER;                          pMB->mode = MODE_INTER;
288                            pMB->pmvs[0] = pmv;     /* pMB->pmvs[1] = pMB->pmvs[2] = pMB->pmvs[3]  are not needed for INTER */
289                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
290           pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = pMB->sad16;                          pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =
291                                    pMB->sad16;
292                          pmv = get_pmv(pMBs, x, y, pParam->mb_width, 0);                          }
                         // get_pmv has to be called again.  
                         // intra-decision and inter4v change predictors  
   
                                 pMB->pmvs[0].x = pMB->mv16.x - pmv.x;  
                                 pMB->pmvs[0].y = pMB->mv16.y - pmv.y;  
293                  }                  }
294    
295          return 0;          return 0;
296  }  }
297    
298    
299  #define CHECK_MV16_ZERO {\  #define CHECK_MV16_ZERO {\
300    if ( (0 <= max_dx) && (0 >= min_dx) \    if ( (0 <= max_dx) && (0 >= min_dx) \
301      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
302    { \    { \
303      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \
304      iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16(-center_x, -center_y, (uint8_t)iFcode, iQuant);\
305      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
306      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
307  }  }
308    
309  #define NOCHECK_MV16_CANDIDATE(X,Y) { \  #define NOCHECK_MV16_CANDIDATE(X,Y) { \
310      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
311      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
312      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
313      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
314  }  }
# Line 436  Line 318 
318      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
319    { \    { \
320      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
321      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
322      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
323      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
324  }  }
# Line 446  Line 328 
328      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
329    { \    { \
330      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
331      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
332      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
333      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
334  }  }
# Line 456  Line 338 
338      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
339    { \    { \
340      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
341      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
342      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
343      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
344  }  }
# Line 464  Line 346 
346    
347  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
348    iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \    iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \
349    iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\    iSAD += calc_delta_8(-center_x, -center_y, (uint8_t)iFcode, iQuant);\
350    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
351    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
352  }  }
# Line 472  Line 354 
354  #define NOCHECK_MV8_CANDIDATE(X,Y) \  #define NOCHECK_MV8_CANDIDATE(X,Y) \
355    { \    { \
356      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
357      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
358      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
359      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
360  }  }
# Line 482  Line 364 
364      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
365    { \    { \
366      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
367      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
368      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
369      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
370  }  }
# Line 492  Line 374 
374      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
375    { \    { \
376      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
377      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
378      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
379      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
380  }  }
# Line 502  Line 384 
384      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
385    { \    { \
386      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
387      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
388      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
389      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
390  }  }
# Line 528  Line 410 
410          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
411          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
412          int32_t iSAD;          int32_t iSAD;
413          int32_t pred_x,pred_y;          VECTOR pred;
414    
415    
416          get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);          pred = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
417    
418          iSAD = sad16( cur,          iSAD = sad16( cur,
419                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),
# Line 540  Line 423 
423    
424          currMV->x = 0;          currMV->x = 0;
425          currMV->y = 0;          currMV->y = 0;
426          currPMV->x = -pred_x;          currPMV->x = -pred.x;
427          currPMV->y = -pred_y;          currPMV->y = -pred.y;
428    
429          return iSAD;          return iSAD;
430    
431  }  }
432  */  */
433    
434  int32_t Diamond16_MainSearch(  int32_t
435          const uint8_t * const pRef,  Diamond16_MainSearch(const uint8_t * const pRef,
436          const uint8_t * const pRefH,          const uint8_t * const pRefH,
437          const uint8_t * const pRefV,          const uint8_t * const pRefV,
438          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
439          const uint8_t * const cur,          const uint8_t * const cur,
440          const int x, const int y,                                           const int x,
441          int32_t startx, int32_t starty,                                           const int y,
442          int32_t iMinSAD,                                     const int start_x,
443                                       const int start_y,
444                                       int iMinSAD,
445          VECTOR * const currMV,          VECTOR * const currMV,
446          const VECTOR * const pmv,                                     const int center_x,
447          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
448          const int32_t min_dy, const int32_t max_dy,                                           const int32_t min_dx,
449                                             const int32_t max_dx,
450                                             const int32_t min_dy,
451                                             const int32_t max_dy,
452          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
453          const int32_t iDiamondSize,          const int32_t iDiamondSize,
454          const int32_t iFcode,          const int32_t iFcode,
# Line 570  Line 458 
458  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
459    
460          int32_t iDirection=0;          int32_t iDirection=0;
461            int32_t iDirectionBackup;
462          int32_t iSAD;          int32_t iSAD;
463          VECTOR backupMV;          VECTOR backupMV;
464          backupMV.x = startx;  
465          backupMV.y = starty;          backupMV.x = start_x;
466            backupMV.y = start_y;
467    
468  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
469    
# Line 582  Line 472 
472          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
473          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
474    
475          if (iDirection)          if (iDirection) {
476                  while (!iFound)                  while (!iFound) {
                 {  
477                          iFound = 1;                          iFound = 1;
478                          backupMV=*currMV;                          backupMV=*currMV;
479                            iDirectionBackup = iDirection;
480    
481                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
482                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
483                          if ( iDirection != 1)                                                                                     backupMV.y, 1);
484                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
485                          if ( iDirection != 4)                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
486                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                     backupMV.y, 2);
487                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
488                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
489                  }                                                                                     backupMV.y - iDiamondSize, 3);
490          else                          if (iDirectionBackup != 3)
491          {                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
492                  currMV->x = startx;                                                                                     backupMV.y + iDiamondSize, 4);
493                  currMV->y = starty;                  }
494            } else {
495                    currMV->x = start_x;
496                    currMV->y = start_y;
497          }          }
498          return iMinSAD;          return iMinSAD;
499  }  }
500    
501  int32_t Square16_MainSearch(  int32_t
502                                          const uint8_t * const pRef,  Square16_MainSearch(const uint8_t * const pRef,
503                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
504                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
505                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
506                                          const uint8_t * const cur,                                          const uint8_t * const cur,
507                                          const int x, const int y,                                          const int x,
508                                          int32_t startx, int32_t starty,                                          const int y,
509                                          int32_t iMinSAD,                                     const int start_x,
510                                       const int start_y,
511                                       int iMinSAD,
512                                          VECTOR * const currMV,                                          VECTOR * const currMV,
513                                          const VECTOR * const pmv,                                     const int center_x,
514                                          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
515                                          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
516                                            const int32_t max_dx,
517                                            const int32_t min_dy,
518                                            const int32_t max_dy,
519                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
520                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
521                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 629  Line 527 
527          int32_t iDirection=0;          int32_t iDirection=0;
528          int32_t iSAD;          int32_t iSAD;
529          VECTOR backupMV;          VECTOR backupMV;
530          backupMV.x = startx;  
531          backupMV.y = starty;          backupMV.x = start_x;
532            backupMV.y = start_y;
533    
534  /* It's one search with full square pattern, and new parts for all following diamonds */  /* It's one search with full square pattern, and new parts for all following diamonds */
535    
# Line 645  Line 544 
544          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
545          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
546    
547          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
548          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                           backupMV.y - iDiamondSize, 5);
549          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
550          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                                           backupMV.y + iDiamondSize, 6);
551            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
552                                                             backupMV.y - iDiamondSize, 7);
553            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
554                                                             backupMV.y + iDiamondSize, 8);
555    
556    
557          if (iDirection)          if (iDirection) {
558                  while (!iFound)                  while (!iFound) {
                 {  
559                          iFound = 1;                          iFound = 1;
560                          backupMV=*currMV;                          backupMV=*currMV;
561    
562                          switch (iDirection)                          switch (iDirection) {
                         {  
563                                  case 1:                                  case 1:
564                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
565                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                     backupMV.y, 1);
566                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
567                                                                                     backupMV.y - iDiamondSize, 5);
568                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
569                                                                                     backupMV.y - iDiamondSize, 7);
570                                          break;                                          break;
571                                  case 2:                                  case 2:
572                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
573                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   2);
574                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
575                                                                                     backupMV.y + iDiamondSize, 6);
576                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
577                                                                                     backupMV.y + iDiamondSize, 8);
578                                          break;                                          break;
579    
580                                  case 3:                                  case 3:
581                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
582                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
583                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
584                                                                                     backupMV.y - iDiamondSize, 7);
585                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
586                                                                                     backupMV.y + iDiamondSize, 8);
587                                          break;                                          break;
588    
589                                  case 4:                                  case 4:
590                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
591                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
592                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
593                                                                                     backupMV.y - iDiamondSize, 5);
594                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
595                                                                                     backupMV.y + iDiamondSize, 6);
596                                          break;                                          break;
597    
598                                  case 5:                                  case 5:
599                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
600                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   1);
601                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
602                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   3);
603                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
604                                                                                     backupMV.y - iDiamondSize, 5);
605                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
606                                                                                     backupMV.y + iDiamondSize, 6);
607                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
608                                                                                     backupMV.y - iDiamondSize, 7);
609                                          break;                                          break;
610    
611                                  case 6:                                  case 6:
612                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
613                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   2);
614                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
615                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
616                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);  
617                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
618                                                                                     backupMV.y - iDiamondSize, 5);
619                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
620                                                                                     backupMV.y + iDiamondSize, 6);
621                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
622                                                                                     backupMV.y + iDiamondSize, 8);
623    
624                                          break;                                          break;
625    
626                                  case 7:                                  case 7:
627                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
628                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                     backupMV.y, 1);
629                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
630                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
631                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
632                                                                                     backupMV.y - iDiamondSize, 5);
633                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
634                                                                                     backupMV.y - iDiamondSize, 7);
635                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
636                                                                                     backupMV.y + iDiamondSize, 8);
637                                          break;                                          break;
638    
639                                  case 8:                                  case 8:
640                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
641                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
642                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
643                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
644                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
645                                                                                     backupMV.y + iDiamondSize, 6);
646                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
647                                                                                     backupMV.y - iDiamondSize, 7);
648                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
649                                                                                     backupMV.y + iDiamondSize, 8);
650                                          break;                                          break;
651                          default:                          default:
652                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
653                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                                                                   1);
654                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
655                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
656                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
657                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
658                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
659                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
660                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);  
661                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
662                                                                                     backupMV.y - iDiamondSize, 5);
663                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
664                                                                                     backupMV.y + iDiamondSize, 6);
665                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
666                                                                                     backupMV.y - iDiamondSize, 7);
667                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
668                                                                                     backupMV.y + iDiamondSize, 8);
669                                          break;                                          break;
670                          }                          }
671                  }                  }
672          else          } else {
673                  {                  currMV->x = start_x;
674                          currMV->x = startx;                  currMV->y = start_y;
                         currMV->y = starty;  
675                  }                  }
676          return iMinSAD;          return iMinSAD;
677  }  }
678    
679    
680  int32_t Full16_MainSearch(  int32_t
681                                          const uint8_t * const pRef,  Full16_MainSearch(const uint8_t * const pRef,
682                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
683                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
684                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
685                                          const uint8_t * const cur,                                          const uint8_t * const cur,
686                                          const int x, const int y,                                    const int x,
687                                          int32_t startx, int32_t starty,                                    const int y,
688                                          int32_t iMinSAD,                                     const int start_x,
689                                       const int start_y,
690                                       int iMinSAD,
691                                          VECTOR * const currMV,                                          VECTOR * const currMV,
692                                          const VECTOR * const pmv,                                     const int center_x,
693                                          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
694                                          const int32_t min_dy, const int32_t max_dy,                                    const int32_t min_dx,
695                                      const int32_t max_dx,
696                                      const int32_t min_dy,
697                                      const int32_t max_dy,
698                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
699                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
700                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 759  Line 704 
704          int32_t iSAD;          int32_t iSAD;
705          int32_t dx,dy;          int32_t dx,dy;
706          VECTOR backupMV;          VECTOR backupMV;
707          backupMV.x = startx;  
708          backupMV.y = starty;          backupMV.x = start_x;
709            backupMV.y = start_y;
710    
711          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
712                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
# Line 769  Line 715 
715          return iMinSAD;          return iMinSAD;
716  }  }
717    
718  int32_t Full8_MainSearch(  int32_t
719                                          const uint8_t * const pRef,  AdvDiamond16_MainSearch(const uint8_t * const pRef,
720                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
721                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
722                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
723                                          const uint8_t * const cur,                                          const uint8_t * const cur,
724                                          const int x, const int y,                                                  const int x,
725                                          int32_t startx, int32_t starty,                                                  const int y,
726                                          int32_t iMinSAD,                                             int start_x,
727                                               int start_y,
728                                               int iMinSAD,
729                                          VECTOR * const currMV,                                          VECTOR * const currMV,
730                                          const VECTOR * const pmv,                                             const int center_x,
731                                          const int32_t min_dx, const int32_t max_dx,                                             const int center_y,
732                                          const int32_t min_dy, const int32_t max_dy,                                                  const int32_t min_dx,
733                                                    const int32_t max_dx,
734                                                    const int32_t min_dy,
735                                                    const int32_t max_dy,
736                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
737                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
738                                          const int32_t iFcode,                                          const int32_t iFcode,
739                                          const int32_t iQuant,                                          const int32_t iQuant,
740                                          int iFound)                                                  int iDirection)
741  {  {
742    
743          int32_t iSAD;          int32_t iSAD;
         int32_t dx,dy;  
         VECTOR backupMV;  
         backupMV.x = startx;  
         backupMV.y = starty;  
744    
745          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
                 for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)  
                         NOCHECK_MV8_CANDIDATE(dx,dy);  
746    
747          return iMinSAD;          if (iDirection) {
748  }                  CHECK_MV16_CANDIDATE(start_x - iDiamondSize, start_y);
749                    CHECK_MV16_CANDIDATE(start_x + iDiamondSize, start_y);
750                    CHECK_MV16_CANDIDATE(start_x, start_y - iDiamondSize);
751                    CHECK_MV16_CANDIDATE(start_x, start_y + iDiamondSize);
752            } else {
753                    int bDirection = 1 + 2 + 4 + 8;
754    
755                    do {
756                            iDirection = 0;
757                            if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
758                                    CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
759    
760                            if (bDirection & 2)
761                                    CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
762    
763  int32_t Halfpel16_Refine(                          if (bDirection & 4)
764          const uint8_t * const pRef,                                  CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
         const uint8_t * const pRefH,  
         const uint8_t * const pRefV,  
         const uint8_t * const pRefHV,  
         const uint8_t * const cur,  
         const int x, const int y,  
         VECTOR * const currMV,  
         int32_t iMinSAD,  
         const VECTOR * const pmv,  
         const int32_t min_dx, const int32_t max_dx,  
         const int32_t min_dy, const int32_t max_dy,  
         const int32_t iFcode,  
         const int32_t iQuant,  
         const int32_t iEdgedWidth)  
 {  
 /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  
765    
766          int32_t iSAD;                          if (bDirection & 8)
767          VECTOR backupMV = *currMV;                                  CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
768    
769          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y-1);                          /* now we're doing diagonal checks near our candidate */
770          CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y-1);  
771          CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y-1);                          if (iDirection)         //checking if anything found
772          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y);                          {
773          CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y);                                  bDirection = iDirection;
774          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y+1);                                  iDirection = 0;
775          CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y+1);                                  start_x = currMV->x;
776          CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y+1);                                  start_y = currMV->y;
777                                    if (bDirection & 3)     //our candidate is left or right
778                                    {
779                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
780                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
781                                    } else                  // what remains here is up or down
782                                    {
783                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
784                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
785                                    }
786    
787                                    if (iDirection) {
788                                            bDirection += iDirection;
789                                            start_x = currMV->x;
790                                            start_y = currMV->y;
791                                    }
792                            } else                          //about to quit, eh? not so fast....
793                            {
794                                    switch (bDirection) {
795                                    case 2:
796                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
797                                                                                             start_y - iDiamondSize, 2 + 4);
798                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
799                                                                                             start_y + iDiamondSize, 2 + 8);
800                                            break;
801                                    case 1:
802    
803                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
804                                                                                             start_y - iDiamondSize, 1 + 4);
805                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
806                                                                                             start_y + iDiamondSize, 1 + 8);
807                                            break;
808                                    case 2 + 4:
809                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
810                                                                                             start_y - iDiamondSize, 1 + 4);
811                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
812                                                                                             start_y - iDiamondSize, 2 + 4);
813                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
814                                                                                             start_y + iDiamondSize, 2 + 8);
815                                            break;
816                                    case 4:
817                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
818                                                                                             start_y - iDiamondSize, 2 + 4);
819                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
820                                                                                             start_y - iDiamondSize, 1 + 4);
821                                            break;
822                                    case 8:
823                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
824                                                                                             start_y + iDiamondSize, 2 + 8);
825                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
826                                                                                             start_y + iDiamondSize, 1 + 8);
827                                            break;
828                                    case 1 + 4:
829                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
830                                                                                             start_y + iDiamondSize, 1 + 8);
831                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
832                                                                                             start_y - iDiamondSize, 1 + 4);
833                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
834                                                                                             start_y - iDiamondSize, 2 + 4);
835                                            break;
836                                    case 2 + 8:
837                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
838                                                                                             start_y - iDiamondSize, 1 + 4);
839                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
840                                                                                             start_y + iDiamondSize, 1 + 8);
841                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
842                                                                                             start_y + iDiamondSize, 2 + 8);
843                                            break;
844                                    case 1 + 8:
845                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
846                                                                                             start_y - iDiamondSize, 2 + 4);
847                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
848                                                                                             start_y + iDiamondSize, 2 + 8);
849                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
850                                                                                             start_y + iDiamondSize, 1 + 8);
851                                            break;
852                                    default:                //1+2+4+8 == we didn't find anything at all
853                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
854                                                                                             start_y - iDiamondSize, 1 + 4);
855                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
856                                                                                             start_y + iDiamondSize, 1 + 8);
857                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
858                                                                                             start_y - iDiamondSize, 2 + 4);
859                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
860                                                                                             start_y + iDiamondSize, 2 + 8);
861                                            break;
862                                    }
863                                    if (!iDirection)
864                                            break;          //ok, the end. really
865                                    else {
866                                            bDirection = iDirection;
867                                            start_x = currMV->x;
868                                            start_y = currMV->y;
869                                    }
870                            }
871                    }
872                    while (1);                              //forever
873            }
874          return iMinSAD;          return iMinSAD;
875  }  }
876    
 #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  
877    
878    #define CHECK_MV16_F_INTERPOL(X,Y,BX,BY) { \
879      if ( ((X) <= max_dx) && ((X) >= min_dx) \
880        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
881      { \
882        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
883        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
884        if (iSAD < iMinSAD) \
885        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
886    }
887    
888  int32_t PMVfastSearch16(  #define CHECK_MV16_F_INTERPOL_DIR(X,Y,BX,BY,D) { \
889                                          const uint8_t * const pRef,    if ( ((X) <= max_dx) && ((X) >= min_dx) \
890                                          const uint8_t * const pRefH,      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
891                                          const uint8_t * const pRefV,    { \
892                                          const uint8_t * const pRefHV,      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
893                                          const IMAGE * const pCur,      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
894                                          const int x, const int y,      if (iSAD < iMinSAD) \
895                                          const uint32_t MotionFlags,      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
896                                          const uint32_t iQuant,  }
897                                          const uint32_t iFcode,  
898    #define CHECK_MV16_F_INTERPOL_FOUND(X,Y,BX,BY,D) { \
899      if ( ((X) <= max_dx) && ((X) >= min_dx) \
900        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
901      { \
902        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
903        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
904        if (iSAD < iMinSAD) \
905        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
906    }
907    
908    
909    #define CHECK_MV16_B_INTERPOL(FX,FY,X,Y) { \
910      if ( ((X) <= max_dx) && ((X) >= min_dx) \
911        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
912      { \
913        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
914        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
915        if (iSAD < iMinSAD) \
916        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
917    }
918    
919    
920    #define CHECK_MV16_B_INTERPOL_DIR(FX,FY,X,Y,D) { \
921      if ( ((X) <= max_dx) && ((X) >= min_dx) \
922        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
923      { \
924        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
925        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
926        if (iSAD < iMinSAD) \
927        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
928    }
929    
930    
931    #define CHECK_MV16_B_INTERPOL_FOUND(FX,FY,X,Y,D) { \
932      if ( ((X) <= max_dx) && ((X) >= min_dx) \
933        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
934      { \
935        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
936        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
937        if (iSAD < iMinSAD) \
938        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
939    }
940    
941    
942    #if (0==1)
943    int32_t
944    Diamond16_InterpolMainSearch(
945                                            const uint8_t * const f_pRef,
946                                             const uint8_t * const f_pRefH,
947                                             const uint8_t * const f_pRefV,
948                                             const uint8_t * const f_pRefHV,
949                                             const uint8_t * const cur,
950    
951                                            const uint8_t * const b_pRef,
952                                             const uint8_t * const b_pRefH,
953                                             const uint8_t * const b_pRefV,
954                                             const uint8_t * const b_pRefHV,
955    
956                                             const int x,
957                                             const int y,
958    
959                                       const int f_start_x,
960                                       const int f_start_y,
961                                       const int b_start_x,
962                                       const int b_start_y,
963    
964                                       int iMinSAD,
965                                       VECTOR * const f_currMV,
966                                       VECTOR * const b_currMV,
967    
968                                       const int f_center_x,
969                                       const int f_center_y,
970                                       const int b_center_x,
971                                       const int b_center_y,
972    
973                                             const int32_t min_dx,
974                                             const int32_t max_dx,
975                                             const int32_t min_dy,
976                                             const int32_t max_dy,
977                                             const int32_t iEdgedWidth,
978                                             const int32_t iDiamondSize,
979    
980                                             const int32_t f_iFcode,
981                                             const int32_t b_iFcode,
982    
983                                             const int32_t iQuant,
984                                             int iFound)
985    {
986    /* Do a diamond search around given starting point, return SAD of best */
987    
988            int32_t f_iDirection = 0;
989            int32_t b_iDirection = 0;
990            int32_t iSAD;
991    
992            VECTOR f_backupMV;
993            VECTOR b_backupMV;
994    
995            f_backupMV.x = start_x;
996            f_backupMV.y = start_y;
997            b_backupMV.x = start_x;
998            b_backupMV.y = start_y;
999    
1000    /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1001    
1002            CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1003            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1004            CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1005            CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1006    
1007            if (iDirection)
1008                    while (!iFound) {
1009                            iFound = 1;
1010                            backupMV = *currMV;
1011    
1012                            if (iDirection != 2)
1013                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1014                                                                                       backupMV.y, 1);
1015                            if (iDirection != 1)
1016                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1017                                                                                       backupMV.y, 2);
1018                            if (iDirection != 4)
1019                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
1020                                                                                       backupMV.y - iDiamondSize, 3);
1021                            if (iDirection != 3)
1022                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
1023                                                                                       backupMV.y + iDiamondSize, 4);
1024            } else {
1025                    currMV->x = start_x;
1026                    currMV->y = start_y;
1027            }
1028            return iMinSAD;
1029    }
1030    #endif
1031    
1032    
1033    int32_t
1034    AdvDiamond8_MainSearch(const uint8_t * const pRef,
1035                                               const uint8_t * const pRefH,
1036                                               const uint8_t * const pRefV,
1037                                               const uint8_t * const pRefHV,
1038                                               const uint8_t * const cur,
1039                                               const int x,
1040                                               const int y,
1041                                               int start_x,
1042                                               int start_y,
1043                                               int iMinSAD,
1044                                               VECTOR * const currMV,
1045                                               const int center_x,
1046                                               const int center_y,
1047                                               const int32_t min_dx,
1048                                               const int32_t max_dx,
1049                                               const int32_t min_dy,
1050                                               const int32_t max_dy,
1051                                               const int32_t iEdgedWidth,
1052                                               const int32_t iDiamondSize,
1053                                               const int32_t iFcode,
1054                                               const int32_t iQuant,
1055                                               int iDirection)
1056    {
1057    
1058            int32_t iSAD;
1059    
1060    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
1061    
1062            if (iDirection) {
1063                    CHECK_MV8_CANDIDATE(start_x - iDiamondSize, start_y);
1064                    CHECK_MV8_CANDIDATE(start_x + iDiamondSize, start_y);
1065                    CHECK_MV8_CANDIDATE(start_x, start_y - iDiamondSize);
1066                    CHECK_MV8_CANDIDATE(start_x, start_y + iDiamondSize);
1067            } else {
1068                    int bDirection = 1 + 2 + 4 + 8;
1069    
1070                    do {
1071                            iDirection = 0;
1072                            if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
1073                                    CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1074    
1075                            if (bDirection & 2)
1076                                    CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1077    
1078                            if (bDirection & 4)
1079                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1080    
1081                            if (bDirection & 8)
1082                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1083    
1084                            /* now we're doing diagonal checks near our candidate */
1085    
1086                            if (iDirection)         //checking if anything found
1087                            {
1088                                    bDirection = iDirection;
1089                                    iDirection = 0;
1090                                    start_x = currMV->x;
1091                                    start_y = currMV->y;
1092                                    if (bDirection & 3)     //our candidate is left or right
1093                                    {
1094                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1095                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1096                                    } else                  // what remains here is up or down
1097                                    {
1098                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1099                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1100                                    }
1101    
1102                                    if (iDirection) {
1103                                            bDirection += iDirection;
1104                                            start_x = currMV->x;
1105                                            start_y = currMV->y;
1106                                    }
1107                            } else                          //about to quit, eh? not so fast....
1108                            {
1109                                    switch (bDirection) {
1110                                    case 2:
1111                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1112                                                                                            start_y - iDiamondSize, 2 + 4);
1113                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1114                                                                                            start_y + iDiamondSize, 2 + 8);
1115                                            break;
1116                                    case 1:
1117                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1118                                                                                            start_y - iDiamondSize, 1 + 4);
1119                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1120                                                                                            start_y + iDiamondSize, 1 + 8);
1121                                            break;
1122                                    case 2 + 4:
1123                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1124                                                                                            start_y - iDiamondSize, 1 + 4);
1125                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1126                                                                                            start_y - iDiamondSize, 2 + 4);
1127                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1128                                                                                            start_y + iDiamondSize, 2 + 8);
1129                                            break;
1130                                    case 4:
1131                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1132                                                                                            start_y - iDiamondSize, 2 + 4);
1133                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1134                                                                                            start_y - iDiamondSize, 1 + 4);
1135                                            break;
1136                                    case 8:
1137                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1138                                                                                            start_y + iDiamondSize, 2 + 8);
1139                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1140                                                                                            start_y + iDiamondSize, 1 + 8);
1141                                            break;
1142                                    case 1 + 4:
1143                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1144                                                                                            start_y + iDiamondSize, 1 + 8);
1145                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1146                                                                                            start_y - iDiamondSize, 1 + 4);
1147                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1148                                                                                            start_y - iDiamondSize, 2 + 4);
1149                                            break;
1150                                    case 2 + 8:
1151                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1152                                                                                            start_y - iDiamondSize, 1 + 4);
1153                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1154                                                                                            start_y + iDiamondSize, 1 + 8);
1155                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1156                                                                                            start_y + iDiamondSize, 2 + 8);
1157                                            break;
1158                                    case 1 + 8:
1159                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1160                                                                                            start_y - iDiamondSize, 2 + 4);
1161                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1162                                                                                            start_y + iDiamondSize, 2 + 8);
1163                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1164                                                                                            start_y + iDiamondSize, 1 + 8);
1165                                            break;
1166                                    default:                //1+2+4+8 == we didn't find anything at all
1167                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1168                                                                                            start_y - iDiamondSize, 1 + 4);
1169                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1170                                                                                            start_y + iDiamondSize, 1 + 8);
1171                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1172                                                                                            start_y - iDiamondSize, 2 + 4);
1173                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1174                                                                                            start_y + iDiamondSize, 2 + 8);
1175                                            break;
1176                                    }
1177                                    if (!(iDirection))
1178                                            break;          //ok, the end. really
1179                                    else {
1180                                            bDirection = iDirection;
1181                                            start_x = currMV->x;
1182                                            start_y = currMV->y;
1183                                    }
1184                            }
1185                    }
1186                    while (1);                              //forever
1187            }
1188            return iMinSAD;
1189    }
1190    
1191    
1192    int32_t
1193    Full8_MainSearch(const uint8_t * const pRef,
1194                                     const uint8_t * const pRefH,
1195                                     const uint8_t * const pRefV,
1196                                     const uint8_t * const pRefHV,
1197                                     const uint8_t * const cur,
1198                                     const int x,
1199                                     const int y,
1200                               const int start_x,
1201                               const int start_y,
1202                               int iMinSAD,
1203                               VECTOR * const currMV,
1204                               const int center_x,
1205                               const int center_y,
1206                                     const int32_t min_dx,
1207                                     const int32_t max_dx,
1208                                     const int32_t min_dy,
1209                                     const int32_t max_dy,
1210                                     const int32_t iEdgedWidth,
1211                                     const int32_t iDiamondSize,
1212                                     const int32_t iFcode,
1213                                     const int32_t iQuant,
1214                                     int iFound)
1215    {
1216            int32_t iSAD;
1217            int32_t dx, dy;
1218            VECTOR backupMV;
1219    
1220            backupMV.x = start_x;
1221            backupMV.y = start_y;
1222    
1223            for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
1224                    for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
1225                            NOCHECK_MV8_CANDIDATE(dx, dy);
1226    
1227            return iMinSAD;
1228    }
1229    
1230    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1231    
1232    int32_t
1233    Halfpel16_Refine(const uint8_t * const pRef,
1234                                     const uint8_t * const pRefH,
1235                                     const uint8_t * const pRefV,
1236                                     const uint8_t * const pRefHV,
1237                                     const uint8_t * const cur,
1238                                     const int x,
1239                                     const int y,
1240                                     VECTOR * const currMV,
1241                                     int32_t iMinSAD,
1242                               const int center_x,
1243                               const int center_y,
1244                                     const int32_t min_dx,
1245                                     const int32_t max_dx,
1246                                     const int32_t min_dy,
1247                                     const int32_t max_dy,
1248                                     const int32_t iFcode,
1249                                     const int32_t iQuant,
1250                                     const int32_t iEdgedWidth)
1251    {
1252    /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
1253    
1254            int32_t iSAD;
1255            VECTOR backupMV = *currMV;
1256    
1257            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y - 1);
1258            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y - 1);
1259            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y - 1);
1260            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y);
1261            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y);
1262            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y + 1);
1263            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y + 1);
1264            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y + 1);
1265    
1266            return iMinSAD;
1267    }
1268    
1269    #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1270    
1271    
1272    
1273    int32_t
1274    PMVfastSearch16(const uint8_t * const pRef,
1275                                    const uint8_t * const pRefH,
1276                                    const uint8_t * const pRefV,
1277                                    const uint8_t * const pRefHV,
1278                                    const IMAGE * const pCur,
1279                                    const int x,
1280                                    const int y,
1281                                    const int start_x,
1282                                    const int start_y,
1283                                    const int center_x,
1284                                    const int center_y,
1285                                    const uint32_t MotionFlags,
1286                                    const uint32_t iQuant,
1287                                    const uint32_t iFcode,
1288                                          const MBParam * const pParam,                                          const MBParam * const pParam,
1289                                          const MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
1290                                          const MACROBLOCK * const prevMBs,                                          const MACROBLOCK * const prevMBs,
# Line 877  Line 1313 
1313          VECTOR pmv[4];          VECTOR pmv[4];
1314          int32_t psad[4];          int32_t psad[4];
1315    
1316  //      const MACROBLOCK * const pMB = pMBs + x + y * iWcount;          MainSearch16FuncPtr MainSearchPtr;
1317    
1318          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1319    
1320          static int32_t threshA,threshB;          int32_t threshA, threshB;
1321          int32_t bPredEq;          int32_t bPredEq;
1322          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1323    
1324  /* Get maximum range */  /* Get maximum range */
1325          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
1326                    x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
1327    
1328  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1329    
1330          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
1331          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1332          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1333          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1334          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1335          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
   
1336    
1337          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1338            //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1339            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1340    
1341          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1342                  threshA =  512;                  threshA =  512;
1343                  threshB = 1024;                  threshB = 1024;
1344            } else {
         }  
         else  
         {  
1345                  threshA = psad[0];                  threshA = psad[0];
1346                  threshB = threshA+256;                  threshB = threshA+256;
1347                  if (threshA< 512) threshA =  512;                  if (threshA < 512)
1348                  if (threshA>1024) threshA = 1024;                          threshA = 512;
1349                  if (threshB>1792) threshB = 1792;                  if (threshA > 1024)
1350                            threshA = 1024;
1351                    if (threshB > 1792)
1352                            threshB = 1792;
1353          }          }
1354    
1355          iFound=0;          iFound=0;
# Line 924  Line 1361 
1361     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
1362  */  */
1363    
1364          *currMV=pmv[0];         /* current best := prediction */          currMV->x = start_x;
1365          if (!(MotionFlags & PMV_HALFPEL16 ))          currMV->y = start_y;
1366          {       /* This should NOT be necessary! */  
1367            if (!(MotionFlags & PMV_HALFPEL16)) {   /* This should NOT be necessary! */
1368                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1369                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
1370          }          }
1371    
1372          if (currMV->x > max_dx)          if (currMV->x > max_dx) {
         {  
1373                  currMV->x=max_dx;                  currMV->x=max_dx;
1374          }          }
1375          if (currMV->x < min_dx)          if (currMV->x < min_dx) {
         {  
1376                  currMV->x=min_dx;                  currMV->x=min_dx;
1377          }          }
1378          if (currMV->y > max_dy)          if (currMV->y > max_dy) {
         {  
1379                  currMV->y=max_dy;                  currMV->y=max_dy;
1380          }          }
1381          if (currMV->y < min_dy)          if (currMV->y < min_dy) {
         {  
1382                  currMV->y=min_dy;                  currMV->y=min_dy;
1383          }          }
1384    
1385          iMinSAD = sad16( cur,          iMinSAD =
1386                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1387                           iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1388          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1389            iMinSAD +=
1390          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
1391          {                                            (uint8_t) iFcode, iQuant);
1392    
1393            if ((iMinSAD < 256) ||
1394                    ((MVequal(*currMV, prevMB->mvs[0])) &&
1395                     ((int32_t) iMinSAD < prevMB->sad16))) {
1396                  if (iMinSAD < 2*iQuant) // high chances for SKIP-mode                  if (iMinSAD < 2*iQuant) // high chances for SKIP-mode
1397                  {                  {
1398                          if (!MVzero(*currMV))                          if (!MVzero(*currMV)) {
                         {  
1399                                  iMinSAD += MV16_00_BIAS;                                  iMinSAD += MV16_00_BIAS;
1400                                  CHECK_MV16_ZERO;                // (0,0) saves space for letterboxed pictures                                  CHECK_MV16_ZERO;                // (0,0) saves space for letterboxed pictures
1401                                  iMinSAD -= MV16_00_BIAS;                                  iMinSAD -= MV16_00_BIAS;
# Line 1014  Line 1451 
1451    
1452          if (!MVzero(pmv[1]))          if (!MVzero(pmv[1]))
1453          if (!MVequal(pmv[1],prevMB->mvs[0]))          if (!MVequal(pmv[1],prevMB->mvs[0]))
1454          if (!MVequal(pmv[1],pmv[0]))                          if (!MVequal(pmv[1], pmv[0])) {
1455          {                                  if (!(MotionFlags & PMV_HALFPEL16)) {
1456                  if (!(MotionFlags & PMV_HALFPEL16 ))                                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
1457                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
1458                  }                  }
1459    
1460                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1461          }          }
   
1462  // top neighbour, if allowed  // top neighbour, if allowed
1463          if (!MVzero(pmv[2]))          if (!MVzero(pmv[2]))
1464          if (!MVequal(pmv[2],prevMB->mvs[0]))          if (!MVequal(pmv[2],prevMB->mvs[0]))
1465          if (!MVequal(pmv[2],pmv[0]))          if (!MVequal(pmv[2],pmv[0]))
1466          if (!MVequal(pmv[2],pmv[1]))                                  if (!MVequal(pmv[2], pmv[1])) {
1467          {                                          if (!(MotionFlags & PMV_HALFPEL16)) {
1468                  if (!(MotionFlags & PMV_HALFPEL16 ))                                                  pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
1469                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
1470                  }                  }
1471                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
# Line 1041  Line 1475 
1475                  if (!MVequal(pmv[3],prevMB->mvs[0]))                  if (!MVequal(pmv[3],prevMB->mvs[0]))
1476                  if (!MVequal(pmv[3],pmv[0]))                  if (!MVequal(pmv[3],pmv[0]))
1477                  if (!MVequal(pmv[3],pmv[1]))                  if (!MVequal(pmv[3],pmv[1]))
1478                  if (!MVequal(pmv[3],pmv[2]))                                                                          if (!MVequal(pmv[3], pmv[2])) {
1479                  {                                                                                  if (!(MotionFlags & PMV_HALFPEL16)) {
1480                          if (!(MotionFlags & PMV_HALFPEL16 ))                                                                                          pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
1481                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
1482                          }                          }
1483                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                  CHECK_MV16_CANDIDATE(pmv[3].x,
1484                                                                                                                             pmv[3].y);
1485                  }                  }
1486          }          }
1487    
1488          if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96)*/ )          if ((MVzero(*currMV)) &&
1489                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1490                  iMinSAD -= MV16_00_BIAS;                  iMinSAD -= MV16_00_BIAS;
1491    
1492    
# Line 1059  Line 1494 
1494     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
1495  */  */
1496    
1497          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ((iMinSAD <= threshA) ||
1498          {                  (MVequal(*currMV, prevMB->mvs[0]) &&
1499                     ((int32_t) iMinSAD < prevMB->sad16))) {
1500                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1501                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
1502                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1078  Line 1514 
1514     Refine by using small diamond and goto step 10.     Refine by using small diamond and goto step 10.
1515  */  */
1516    
1517            if (MotionFlags & PMV_USESQUARES16)
1518                    MainSearchPtr = Square16_MainSearch;
1519            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
1520                    MainSearchPtr = AdvDiamond16_MainSearch;
1521            else
1522                    MainSearchPtr = Diamond16_MainSearch;
1523    
1524          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1525    
1526    
1527  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1528          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1529                                            x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1530                                            currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->x, currMV->y, iMinSAD, &newMV, center_x, center_y,
1531                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dx, max_dx,
1532                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1533                                                      iQuant, iFound);
1534    
1535          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1536                  *currMV = newMV;                  *currMV = newMV;
1537                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1538          }          }
1539    
1540          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
1541  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1542    
1543                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1544                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1545                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1546                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    center_x, center_y, iMinSAD, &newMV, center_x, center_y,
1547                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1548                                                                      iDiamondSize, iFcode, iQuant, iFound);
1549    
1550                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1551                          *currMV = newMV;                          *currMV = newMV;
1552                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1553                  }                  }
1554                  }                  }
1555    
1556                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1557                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1558                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1559                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y,
1560                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy,
1561                                                                      iEdgedWidth, iDiamondSize, iFcode,
1562                                                                      iQuant, iFound);
1563    
1564                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1565                          *currMV = newMV;                          *currMV = newMV;
1566                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1567                  }                  }
# Line 1129  Line 1574 
1574    
1575  PMVfast16_Terminate_with_Refine:  PMVfast16_Terminate_with_Refine:
1576          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1577                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1578                                    x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1579                                    currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1580                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1581    
1582  PMVfast16_Terminate_without_Refine:  PMVfast16_Terminate_without_Refine:
1583          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
1584          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
1585          return iMinSAD;          return iMinSAD;
1586  }  }
1587    
# Line 1145  Line 1590 
1590    
1591    
1592    
1593  int32_t Diamond8_MainSearch(  int32_t
1594          const uint8_t * const pRef,  Diamond8_MainSearch(const uint8_t * const pRef,
1595          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1596          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1597          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1598          const uint8_t * const cur,          const uint8_t * const cur,
1599          const int x, const int y,                                          const int x,
1600          int32_t startx, int32_t starty,                                          const int y,
1601                                            int32_t start_x,
1602                                            int32_t start_y,
1603          int32_t iMinSAD,          int32_t iMinSAD,
1604          VECTOR * const currMV,          VECTOR * const currMV,
1605          const VECTOR * const pmv,                                     const int center_x,
1606          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
1607          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
1608                                            const int32_t max_dx,
1609                                            const int32_t min_dy,
1610                                            const int32_t max_dy,
1611          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
1612          const int32_t iDiamondSize,          const int32_t iDiamondSize,
1613          const int32_t iFcode,          const int32_t iFcode,
# Line 1167  Line 1617 
1617  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
1618    
1619          int32_t iDirection=0;          int32_t iDirection=0;
1620            int32_t iDirectionBackup;
1621          int32_t iSAD;          int32_t iSAD;
1622          VECTOR backupMV;          VECTOR backupMV;
1623          backupMV.x = startx;  
1624          backupMV.y = starty;          backupMV.x = start_x;
1625            backupMV.y = start_y;
1626    
1627  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1628    
# Line 1179  Line 1631 
1631          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
1632          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1633    
1634          if (iDirection)          if (iDirection) {
1635                  while (!iFound)                  while (!iFound) {
                 {  
1636                          iFound = 1;                          iFound = 1;
1637                          backupMV=*currMV;       // since iDirection!=0, this is well defined!                          backupMV=*currMV;       // since iDirection!=0, this is well defined!
1638                            iDirectionBackup = iDirection;
1639    
1640                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
1641                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1642                          if ( iDirection != 1)                                                                                    backupMV.y, 1);
1643                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
1644                          if ( iDirection != 4)                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1645                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                    backupMV.y, 2);
1646                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
1647                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1648                  }                                                                                    backupMV.y - iDiamondSize, 3);
1649          else                          if (iDirectionBackup != 3)
1650          {                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1651                  currMV->x = startx;                                                                                    backupMV.y + iDiamondSize, 4);
1652                  currMV->y = starty;                  }
1653            } else {
1654                    currMV->x = start_x;
1655                    currMV->y = start_y;
1656          }          }
1657          return iMinSAD;          return iMinSAD;
1658  }  }
1659    
1660  int32_t Halfpel8_Refine(  
1661          const uint8_t * const pRef,  
1662    
1663    int32_t
1664    Square8_MainSearch(const uint8_t * const pRef,
1665          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1666          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1667          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1668          const uint8_t * const cur,          const uint8_t * const cur,
1669          const int x, const int y,                                          const int x,
1670          VECTOR * const currMV,                                          const int y,
1671                                            int32_t start_x,
1672                                            int32_t start_y,
1673          int32_t iMinSAD,          int32_t iMinSAD,
1674          const VECTOR * const pmv,                                          VECTOR * const currMV,
1675          const int32_t min_dx, const int32_t max_dx,                                     const int center_x,
1676          const int32_t min_dy, const int32_t max_dy,                                     const int center_y,
1677                                            const int32_t min_dx,
1678                                            const int32_t max_dx,
1679                                            const int32_t min_dy,
1680                                            const int32_t max_dy,
1681                                            const int32_t iEdgedWidth,
1682                                            const int32_t iDiamondSize,
1683          const int32_t iFcode,          const int32_t iFcode,
1684          const int32_t iQuant,          const int32_t iQuant,
1685          const int32_t iEdgedWidth)                                          int iFound)
1686  {  {
1687  /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  /* Do a square search around given starting point, return SAD of best */
1688    
1689            int32_t iDirection = 0;
1690            int32_t iSAD;
1691            VECTOR backupMV;
1692    
1693            backupMV.x = start_x;
1694            backupMV.y = start_y;
1695    
1696    /* It's one search with full square pattern, and new parts for all following diamonds */
1697    
1698    /*   new direction are extra, so 1-4 is normal diamond
1699          537
1700          1*2
1701          648
1702    */
1703    
1704            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1705            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1706            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1707            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1708    
1709            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1710                                                             backupMV.y - iDiamondSize, 5);
1711            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1712                                                             backupMV.y + iDiamondSize, 6);
1713            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1714                                                             backupMV.y - iDiamondSize, 7);
1715            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1716                                                             backupMV.y + iDiamondSize, 8);
1717    
1718    
1719            if (iDirection) {
1720                    while (!iFound) {
1721                            iFound = 1;
1722                            backupMV = *currMV;
1723    
1724                            switch (iDirection) {
1725                            case 1:
1726                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1727                                                                                       backupMV.y, 1);
1728                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1729                                                                                     backupMV.y - iDiamondSize, 5);
1730                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1731                                                                                     backupMV.y - iDiamondSize, 7);
1732                                    break;
1733                            case 2:
1734                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1735                                                                                     2);
1736                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1737                                                                                     backupMV.y + iDiamondSize, 6);
1738                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1739                                                                                     backupMV.y + iDiamondSize, 8);
1740                                    break;
1741    
1742                            case 3:
1743                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1744                                                                                     4);
1745                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1746                                                                                     backupMV.y - iDiamondSize, 7);
1747                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1748                                                                                     backupMV.y + iDiamondSize, 8);
1749                                    break;
1750    
1751                            case 4:
1752                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1753                                                                                     3);
1754                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1755                                                                                     backupMV.y - iDiamondSize, 5);
1756                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1757                                                                                     backupMV.y + iDiamondSize, 6);
1758                                    break;
1759    
1760                            case 5:
1761                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1762                                                                                     1);
1763                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1764                                                                                     3);
1765                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1766                                                                                     backupMV.y - iDiamondSize, 5);
1767                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1768                                                                                     backupMV.y + iDiamondSize, 6);
1769                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1770                                                                                     backupMV.y - iDiamondSize, 7);
1771                                    break;
1772    
1773                            case 6:
1774                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1775                                                                                     2);
1776                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1777                                                                                     3);
1778    
1779                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1780                                                                                     backupMV.y - iDiamondSize, 5);
1781                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1782                                                                                     backupMV.y + iDiamondSize, 6);
1783                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1784                                                                                     backupMV.y + iDiamondSize, 8);
1785    
1786                                    break;
1787    
1788                            case 7:
1789                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1790                                                                                       backupMV.y, 1);
1791                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1792                                                                                     4);
1793                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1794                                                                                     backupMV.y - iDiamondSize, 5);
1795                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1796                                                                                     backupMV.y - iDiamondSize, 7);
1797                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1798                                                                                     backupMV.y + iDiamondSize, 8);
1799                                    break;
1800    
1801                            case 8:
1802                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1803                                                                                     2);
1804                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1805                                                                                     4);
1806                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1807                                                                                     backupMV.y + iDiamondSize, 6);
1808                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1809                                                                                     backupMV.y - iDiamondSize, 7);
1810                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1811                                                                                     backupMV.y + iDiamondSize, 8);
1812                                    break;
1813                            default:
1814                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1815                                                                                     1);
1816                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1817                                                                                     2);
1818                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1819                                                                                     3);
1820                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1821                                                                                     4);
1822    
1823                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1824                                                                                     backupMV.y - iDiamondSize, 5);
1825                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1826                                                                                     backupMV.y + iDiamondSize, 6);
1827                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1828                                                                                     backupMV.y - iDiamondSize, 7);
1829                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1830                                                                                     backupMV.y + iDiamondSize, 8);
1831                                    break;
1832                            }
1833                    }
1834            } else {
1835                    currMV->x = start_x;
1836                    currMV->y = start_y;
1837            }
1838            return iMinSAD;
1839    }
1840    
1841    
1842    
1843    
1844    
1845    int32_t
1846    Halfpel8_Refine_c(const uint8_t * const pRef,
1847                                    const uint8_t * const pRefH,
1848                                    const uint8_t * const pRefV,
1849                                    const uint8_t * const pRefHV,
1850                                    const uint8_t * const cur,
1851                                    const int x,
1852                                    const int y,
1853                                    VECTOR * const currMV,
1854                                    int32_t iMinSAD,
1855                               const int center_x,
1856                               const int center_y,
1857                                    const int32_t min_dx,
1858                                    const int32_t max_dx,
1859                                    const int32_t min_dy,
1860                                    const int32_t max_dy,
1861                                    const int32_t iFcode,
1862                                    const int32_t iQuant,
1863                                    const int32_t iEdgedWidth)
1864    {
1865    /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
1866    
1867          int32_t iSAD;          int32_t iSAD;
1868          VECTOR backupMV = *currMV;          VECTOR backupMV = *currMV;
# Line 1238  Line 1882 
1882    
1883  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1884    
1885  int32_t PMVfastSearch8(  int32_t
1886                                          const uint8_t * const pRef,  PMVfastSearch8(const uint8_t * const pRef,
1887                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1888                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1889                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1890                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1891                                          const int x, const int y,                             const int x,
1892                                          const int start_x, const int start_y,                             const int y,
1893                               const int start_x,
1894                               const int start_y,
1895                                    const int center_x,
1896                                    const int center_y,
1897                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1898                                          const uint32_t iQuant,                                          const uint32_t iQuant,
1899                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1278  Line 1926 
1926  //      const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //      const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1927          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1928    
1929          static int32_t threshA,threshB;           int32_t threshA, threshB;
1930          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
1931          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1932    
1933          int32_t iSubBlock = (y&1)+(y&1) + (x&1);          int32_t iSubBlock = (y&1)+(y&1) + (x&1);
1934    
1935            MainSearch8FuncPtr MainSearchPtr;
1936    
1937          /* Init variables */          /* Init variables */
1938          startMV.x = start_x;          startMV.x = start_x;
1939          startMV.y = start_y;          startMV.y = start_y;
1940    
1941          /* Get maximum range */          /* Get maximum range */
1942          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
1943                    x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
1944    
1945          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
1946          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1947            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
1948            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
1949            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
1950          }               /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          }
   
1951    
1952          bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
1953            //bPredEq = get_pmvdata(pMBs, (x >> 1), (y >> 1), iWcount, iSubBlock, pmv, psad);
1954            bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
1955    
1956          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1957                  threshA =  512/4;                  threshA =  512/4;
1958                  threshB = 1024/4;                  threshB = 1024/4;
1959    
1960          }          } else {
1961          else                  threshA = psad[0] / 4;  /* good estimate? */
         {  
                 threshA = psad[0]/4;                    /* good estimate */  
1962                  threshB = threshA+256/4;                  threshB = threshA+256/4;
1963                  if (threshA< 512/4) threshA =  512/4;                  if (threshA < 512 / 4)
1964                  if (threshA>1024/4) threshA = 1024/4;                          threshA = 512 / 4;
1965                  if (threshB>1792/4) threshB = 1792/4;                  if (threshA > 1024 / 4)
1966                            threshA = 1024 / 4;
1967                    if (threshB > 1792 / 4)
1968                            threshB = 1792 / 4;
1969          }          }
1970    
1971          iFound=0;          iFound=0;
# Line 1329  Line 1980 
1980    
1981  // Prepare for main loop  // Prepare for main loop
1982    
1983      if (MotionFlags & PMV_USESQUARES8)
1984          MainSearchPtr = Square8_MainSearch;
1985      else
1986    
1987            if (MotionFlags & PMV_ADVANCEDDIAMOND8)
1988                    MainSearchPtr = AdvDiamond8_MainSearch;
1989            else
1990                    MainSearchPtr = Diamond8_MainSearch;
1991    
1992    
1993          *currMV = startMV;          *currMV = startMV;
1994    
1995          iMinSAD = sad8( cur,          iMinSAD =
1996                          get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  sad8(cur,
1997                          iEdgedWidth);                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
1998          iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode, iQuant);                                                  iEdgedWidth), iEdgedWidth);
1999            iMinSAD +=
2000                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2001                                             (uint8_t) iFcode, iQuant);
2002    
2003          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock]))          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock]))
2004                                  && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )                                                                  && ((int32_t) iMinSAD <
2005          {                                                                          prevMB->sad8[iSubBlock]))) {
2006                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2007                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2008                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1376  Line 2040 
2040  // the median prediction might be even better than mv16  // the median prediction might be even better than mv16
2041    
2042          if (!MVequal(pmv[0],startMV))          if (!MVequal(pmv[0],startMV))
2043                  CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);                  CHECK_MV8_CANDIDATE(center_x, center_y);
2044    
2045  // (0,0) if needed  // (0,0) if needed
2046          if (!MVzero(pmv[0]))          if (!MVzero(pmv[0]))
# Line 1387  Line 2051 
2051          if (!MVzero(prevMB->mvs[iSubBlock]))          if (!MVzero(prevMB->mvs[iSubBlock]))
2052          if (!MVequal(prevMB->mvs[iSubBlock],startMV))          if (!MVequal(prevMB->mvs[iSubBlock],startMV))
2053          if (!MVequal(prevMB->mvs[iSubBlock],pmv[0]))          if (!MVequal(prevMB->mvs[iSubBlock],pmv[0]))
2054          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);                                  CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,
2055                                                                            prevMB->mvs[iSubBlock].y);
2056    
2057          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
2058          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2059                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2060                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2061                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2062                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
2063                          goto PMVfast8_Terminate_with_Refine;                          goto PMVfast8_Terminate_with_Refine;
2064          }          }
2065    
   
2066  // left neighbour, if allowed and needed  // left neighbour, if allowed and needed
2067          if (!MVzero(pmv[1]))          if (!MVzero(pmv[1]))
2068          if (!MVequal(pmv[1],startMV))          if (!MVequal(pmv[1],startMV))
2069          if (!MVequal(pmv[1],prevMB->mvs[iSubBlock]))          if (!MVequal(pmv[1],prevMB->mvs[iSubBlock]))
2070          if (!MVequal(pmv[1],pmv[0]))                                  if (!MVequal(pmv[1], pmv[0])) {
2071          {                                          if (!(MotionFlags & PMV_HALFPEL8)) {
2072                  if (!(MotionFlags & PMV_HALFPEL8 ))                                                  pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2073                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2074                  }                  }
2075                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
2076          }          }
   
2077  // top neighbour, if allowed and needed  // top neighbour, if allowed and needed
2078          if (!MVzero(pmv[2]))          if (!MVzero(pmv[2]))
2079          if (!MVequal(pmv[2],startMV))          if (!MVequal(pmv[2],startMV))
2080          if (!MVequal(pmv[2],prevMB->mvs[iSubBlock]))          if (!MVequal(pmv[2],prevMB->mvs[iSubBlock]))
2081          if (!MVequal(pmv[2],pmv[0]))          if (!MVequal(pmv[2],pmv[0]))
2082          if (!MVequal(pmv[2],pmv[1]))                                          if (!MVequal(pmv[2], pmv[1])) {
2083          {                                                  if (!(MotionFlags & PMV_HALFPEL8)) {
2084                  if (!(MotionFlags & PMV_HALFPEL8 ))                                                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2085                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2086                  }                  }
2087                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
# Line 1430  Line 2092 
2092          if (!MVequal(pmv[3],prevMB->mvs[iSubBlock]))          if (!MVequal(pmv[3],prevMB->mvs[iSubBlock]))
2093          if (!MVequal(pmv[3],pmv[0]))          if (!MVequal(pmv[3],pmv[0]))
2094          if (!MVequal(pmv[3],pmv[1]))          if (!MVequal(pmv[3],pmv[1]))
2095          if (!MVequal(pmv[3],pmv[2]))                                                                                          if (!MVequal(pmv[3], pmv[2])) {
2096                  {                                                                                                  if (!
2097                          if (!(MotionFlags & PMV_HALFPEL8 ))                                                                                                          (MotionFlags &
2098                          {       pmv[3].x = EVEN(pmv[3].x);                                                                                                           PMV_HALFPEL8)) {
2099                                                                                                            pmv[3].x = EVEN(pmv[3].x);
2100                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2101                          }                          }
2102                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                                  CHECK_MV8_CANDIDATE(pmv[3].x,
2103                                                                                                                                            pmv[3].y);
2104                  }                  }
2105          }          }
2106    
2107          if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )          if ((MVzero(*currMV)) &&
2108                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2109                  iMinSAD -= MV8_00_BIAS;                  iMinSAD -= MV8_00_BIAS;
2110    
2111    
# Line 1448  Line 2113 
2113     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
2114  */  */
2115    
2116          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
2117          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2118                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2119                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2120                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2121                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1469  Line 2135 
2135          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2136    
2137  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2138          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2139                                           x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2140                                           currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2141                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2142                                                      iQuant, iFound);
2143    
2144          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2145                  *currMV = newMV;                  *currMV = newMV;
2146                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2147          }          }
2148    
2149          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2150  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
2151    
2152                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2153                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2154                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2155                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2156                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2157                                                                      iDiamondSize, iFcode, iQuant, iFound);
2158    
2159                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2160                          *currMV = newMV;                          *currMV = newMV;
2161                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2162                  }                  }
2163                  }                  }
2164    
2165                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2166                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2167                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2168                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2169                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2170                                                                      iQuant, iFound);
2171    
2172                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2173                          *currMV = newMV;                          *currMV = newMV;
2174                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2175                  }                  }
# Line 1517  Line 2182 
2182    
2183  PMVfast8_Terminate_with_Refine:  PMVfast8_Terminate_with_Refine:
2184          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2185                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2186                                                   x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2187                                                   currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2188                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2189    
2190    
2191  PMVfast8_Terminate_without_Refine:  PMVfast8_Terminate_without_Refine:
2192          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2193          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2194    
2195          return iMinSAD;          return iMinSAD;
2196  }  }
2197    
2198  int32_t EPZSSearch16(  int32_t
2199                                          const uint8_t * const pRef,  EPZSSearch16(const uint8_t * const pRef,
2200                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2201                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2202                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2203                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2204                                          const int x, const int y,                           const int x,
2205                             const int y,
2206                            const int start_x,
2207                            const int start_y,
2208                            const int center_x,
2209                            const int center_y,
2210                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2211                                          const uint32_t iQuant,                                          const uint32_t iQuant,
2212                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1567  Line 2237 
2237          int32_t psad[8];          int32_t psad[8];
2238    
2239          static MACROBLOCK * oldMBs = NULL;          static MACROBLOCK * oldMBs = NULL;
2240    
2241  //      const MACROBLOCK * const pMB = pMBs + x + y * iWcount;  //      const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
2242          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
2243          MACROBLOCK * oldMB = NULL;          MACROBLOCK * oldMB = NULL;
2244    
2245          static int32_t thresh2;           int32_t thresh2;
2246          int32_t bPredEq;          int32_t bPredEq;
2247          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2248    
2249          MainSearch16FuncPtr EPZSMainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
2250    
2251          if (oldMBs == NULL)          if (oldMBs == NULL) {
2252          {       oldMBs = (MACROBLOCK*) calloc(iWcount*iHcount,sizeof(MACROBLOCK));                  oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
2253  //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));  //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
2254          }          }
2255          oldMB = oldMBs + x + y * iWcount;          oldMB = oldMBs + x + y * iWcount;
2256    
2257  /* Get maximum range */  /* Get maximum range */
2258          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2259                          x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
2260    
2261          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
2262          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2263            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2264            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2265            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2266          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2267            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2268          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
2269            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2270    
2271  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2272          MinSAD=SAD          MinSAD=SAD
# Line 1605  Line 2277 
2277    
2278  // Prepare for main loop  // Prepare for main loop
2279    
2280          *currMV=pmv[0];         /* current best := median prediction */          currMV->x = start_x;
2281          if (!(MotionFlags & PMV_HALFPEL16))          currMV->y = start_y;
2282          {  
2283            if (!(MotionFlags & PMV_HALFPEL16)) {
2284                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2285                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2286          }          }
# Line 1623  Line 2296 
2296    
2297  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2298    
2299          iMinSAD = sad16( cur,          iMinSAD =
2300                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
2301                  iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2302          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2303            iMinSAD +=
2304                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2305                                              (uint8_t) iFcode, iQuant);
2306    
2307  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2308          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV, prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ((iMinSAD < 256) ||
2309                  {                  ((MVequal(*currMV, prevMB->mvs[0])) &&
2310                     ((int32_t) iMinSAD < prevMB->sad16))) {
2311                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2312                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2313                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1645  Line 2322 
2322  // set threshhold based on Min of Prediction and SAD of collocated block  // set threshhold based on Min of Prediction and SAD of collocated block
2323  // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want  // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
2324    
2325          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
2326                  thresh2 =  512;                  thresh2 =  512;
2327          }          } else {
         else  
         {  
2328  /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */  /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */
2329    
2330                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
# Line 1662  Line 2336 
2336    
2337    
2338  // left neighbour, if allowed  // left neighbour, if allowed
2339          if (x != 0)          if (x != 0) {
2340          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2341                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2342                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2343                  }                  }
2344                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
2345          }          }
   
2346  // top neighbour, if allowed  // top neighbour, if allowed
2347          if (y != 0)          if (y != 0) {
2348          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2349                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2350                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2351                  }                  }
2352                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
2353    
2354  // top right neighbour, if allowed  // top right neighbour, if allowed
2355                  if ((uint32_t)x != (iWcount-1))                  if ((uint32_t) x != (iWcount - 1)) {
2356                  {                          if (!(MotionFlags & PMV_HALFPEL16)) {
2357                          if (!(MotionFlags & PMV_HALFPEL16 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2358                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2359                          }                          }
2360                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
# Line 1696  Line 2366 
2366  */  */
2367    
2368          if ( (iMinSAD <= thresh2)          if ( (iMinSAD <= thresh2)
2369                  || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )                  || (MVequal(*currMV, prevMB->mvs[0]) &&
2370                  {                          ((int32_t) iMinSAD <= prevMB->sad16))) {
2371                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2372                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2373                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1718  Line 2388 
2388    
2389  // top neighbour  // top neighbour
2390          if (y != 0)          if (y != 0)
2391                  CHECK_MV16_CANDIDATE((prevMB-iWcount)->mvs[0].x,(prevMB-iWcount)->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,
2392                                                             (prevMB - iWcount)->mvs[0].y);
2393    
2394  // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs  // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
2395    
# Line 1727  Line 2398 
2398    
2399  // bottom neighbour, dito  // bottom neighbour, dito
2400          if ((uint32_t)y != iHcount-1)          if ((uint32_t)y != iHcount-1)
2401                  CHECK_MV16_CANDIDATE((prevMB+iWcount)->mvs[0].x,(prevMB+iWcount)->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,
2402                                                             (prevMB + iWcount)->mvs[0].y);
2403    
2404  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
2405          if (iMinSAD <= thresh2)          if (iMinSAD <= thresh2) {
                 {  
2406                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2407                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2408                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1742  Line 2413 
2413    
2414          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2415    
 /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  
   
2416          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
2417                  EPZSMainSearchPtr = Square16_MainSearch;                  MainSearchPtr = Square16_MainSearch;
2418            else
2419             if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2420                    MainSearchPtr = AdvDiamond16_MainSearch;
2421          else          else
2422                  EPZSMainSearchPtr = Diamond16_MainSearch;                  MainSearchPtr = Diamond16_MainSearch;
2423    
2424          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
                         x, y,  
                         currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,  
                         2, iFcode, iQuant, 0);  
2425    
2426          if (iSAD < iMinSAD)          iSAD =
2427          {                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2428                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2429                                                      min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2430    
2431            if (iSAD < iMinSAD) {
2432                  *currMV = newMV;                  *currMV = newMV;
2433                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2434          }          }
2435    
2436    
2437          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
2438  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2439    
2440                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2441                  {                          iSAD =
2442                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2443                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2444                                  pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2445                                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    2, iFcode, iQuant, 0);
2446                  }                  }
2447    
2448                  if (iSAD < iMinSAD)                  if (iSAD < iMinSAD) {
                 {  
2449                          *currMV = newMV;                          *currMV = newMV;
2450                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2451                  }                  }
2452    
2453                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2454                  {                          iSAD =
2455                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2456                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2457                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
                         pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);  
2458    
2459                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2460                                  *currMV = newMV;                                  *currMV = newMV;
2461                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2462                          }                          }
# Line 1798  Line 2467 
2467    
2468  EPZS16_Terminate_with_Refine:  EPZS16_Terminate_with_Refine:
2469          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
2470                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2471                                  x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2472                                  currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2473                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
2474    
2475  EPZS16_Terminate_without_Refine:  EPZS16_Terminate_without_Refine:
2476    
2477          *oldMB = *prevMB;          *oldMB = *prevMB;
2478    
2479          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2480          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2481          return iMinSAD;          return iMinSAD;
2482  }  }
2483    
2484    
2485  int32_t EPZSSearch8(  int32_t
2486                                          const uint8_t * const pRef,  EPZSSearch8(const uint8_t * const pRef,
2487                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2488                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2489                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2490                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2491                                          const int x, const int y,                          const int x,
2492                                          const int start_x, const int start_y,                          const int y,
2493                            const int start_x,
2494                            const int start_y,
2495                            const int center_x,
2496                            const int center_y,
2497                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2498                                          const uint32_t iQuant,                                          const uint32_t iQuant,
2499                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1860  Line 2533 
2533          int32_t bPredEq;          int32_t bPredEq;
2534          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2535    
2536          MainSearch8FuncPtr EPZSMainSearchPtr;          MainSearch8FuncPtr MainSearchPtr;
2537    
2538  /* Get maximum range */  /* Get maximum range */
2539          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2540                          x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2541    
2542  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2543    
2544          if (!(MotionFlags & PMV_HALFPEL8 ))          if (!(MotionFlags & PMV_HALFPEL8)) {
2545          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2546            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2547            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2548            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2549          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2550            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2551          bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);          //bPredEq = get_pmvdata(pMBs, x >> 1, y >> 1, iWcount, iSubBlock, pmv[0].x, pmv[0].y, psad);
2552            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2553    
2554    
2555  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
# Line 1888  Line 2562 
2562  // Prepare for main loop  // Prepare for main loop
2563    
2564    
2565          if (!(MotionFlags & PMV_HALFPEL8))          if (!(MotionFlags & PMV_HALFPEL8)) {
         {  
2566                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2567                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2568          }          }
# Line 1906  Line 2579 
2579  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2580    
2581    
2582          iMinSAD = sad8( cur,          iMinSAD =
2583                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  sad8(cur,
2584                  iEdgedWidth);                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2585          iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);                                                  iEdgedWidth), iEdgedWidth);
2586            iMinSAD +=
2587                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2588                                             (uint8_t) iFcode, iQuant);
2589    
2590    
2591  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2592          if (iMinSAD < 256/4 )          if (iMinSAD < 256 / 4) {
                 {  
2593                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2594                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2595                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
# Line 1931  Line 2606 
2606          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
2607    
2608  // left neighbour, if allowed  // left neighbour, if allowed
2609          if (psad[1] != MV_MAX_ERROR)          if (psad[1] != MV_MAX_ERROR) {
2610          {                  if (!(MotionFlags & PMV_HALFPEL8)) {
2611                  if (!(MotionFlags & PMV_HALFPEL8 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2612                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2613                  }                  }
2614                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
2615          }          }
   
2616  // top neighbour, if allowed  // top neighbour, if allowed
2617          if (psad[2] != MV_MAX_ERROR)          if (psad[2] != MV_MAX_ERROR) {
2618          {                  if (!(MotionFlags & PMV_HALFPEL8)) {
2619                  if (!(MotionFlags & PMV_HALFPEL8 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2620                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2621                  }                  }
2622                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
2623    
2624  // top right neighbour, if allowed  // top right neighbour, if allowed
2625                  if (psad[3] != MV_MAX_ERROR)                  if (psad[3] != MV_MAX_ERROR) {
2626                  {                          if (!(MotionFlags & PMV_HALFPEL8)) {
2627                          if (!(MotionFlags & PMV_HALFPEL8 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2628                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2629                          }                          }
2630                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);
# Line 1971  Line 2642 
2642     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
2643  */  */
2644    
2645          if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */          if (iMinSAD < 512 / 4) {        /* T_2 == 512/4 hardcoded */
                 {  
2646                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2647                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2648                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
# Line 1988  Line 2658 
2658    
2659  /* default: use best prediction as starting point for one call of EPZS_MainSearch */  /* default: use best prediction as starting point for one call of EPZS_MainSearch */
2660    
2661  /* // there is no EPZS^2 for inter4v at the moment  // there is no EPZS^2 for inter4v at the moment
2662    
2663          if (MotionFlags & PMV_USESQUARES8)          if (MotionFlags & PMV_USESQUARES8)
2664                  EPZSMainSearchPtr = Square8_MainSearch;        MainSearchPtr = Square8_MainSearch;
2665          else          else
 */  
2666    
2667          EPZSMainSearchPtr = Diamond8_MainSearch;          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2668                    MainSearchPtr = AdvDiamond8_MainSearch;
2669            else
2670                    MainSearchPtr = Diamond8_MainSearch;
2671    
2672          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2673                  x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2674                  currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2675                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2676                  iDiamondSize, iFcode, iQuant, 0);                                                    iQuant, 0);
2677    
2678    
2679          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2680                  *currMV = newMV;                  *currMV = newMV;
2681                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2682          }          }
2683    
2684          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2685  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2686    
2687                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2688                  {                          iSAD =
2689                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2690                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2691                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2692                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, 0);
2693    
2694                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2695                                  *currMV = newMV;                                  *currMV = newMV;
2696                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2697                          }                          }
2698                  }                  }
2699    
2700                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2701                  {                          iSAD =
2702                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2703                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2704                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2705                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iQuant, 0);
2706    
2707                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2708                                  *currMV = newMV;                                  *currMV = newMV;
2709                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2710                          }                          }
# Line 2047  Line 2715 
2715    
2716  EPZS8_Terminate_with_Refine:  EPZS8_Terminate_with_Refine:
2717          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2718                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2719                                  x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2720                                  currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2721                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2722    
2723  EPZS8_Terminate_without_Refine:  EPZS8_Terminate_without_Refine:
2724    
2725          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2726          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2727          return iMinSAD;          return iMinSAD;
2728  }  }
2729    
2730    
2731    
2732    int32_t
2733    PMVfastIntSearch16(const uint8_t * const pRef,
2734                                    const uint8_t * const pRefH,
2735                                    const uint8_t * const pRefV,
2736                                    const uint8_t * const pRefHV,
2737                                    const IMAGE * const pCur,
2738                                    const int x,
2739                                    const int y,
2740                            const int start_x,
2741                            const int start_y,
2742                            const int center_x,
2743                            const int center_y,
2744                                    const uint32_t MotionFlags,
2745                                    const uint32_t iQuant,
2746                                    const uint32_t iFcode,
2747                                    const MBParam * const pParam,
2748                                    const MACROBLOCK * const pMBs,
2749                                    const MACROBLOCK * const prevMBs,
2750                                    VECTOR * const currMV,
2751                                    VECTOR * const currPMV)
2752    {
2753            const uint32_t iWcount = pParam->mb_width;
2754            const int32_t iWidth = pParam->width;
2755            const int32_t iHeight = pParam->height;
2756            const int32_t iEdgedWidth = pParam->edged_width;
2757    
2758            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
2759            const VECTOR zeroMV = { 0, 0 };
2760    
2761            int32_t iDiamondSize;
2762    
2763            int32_t min_dx;
2764            int32_t max_dx;
2765            int32_t min_dy;
2766            int32_t max_dy;
2767    
2768            int32_t iFound;
2769    
2770            VECTOR newMV;
2771            VECTOR backupMV;                        /* just for PMVFAST */
2772    
2773            VECTOR pmv[4];
2774            int32_t psad[4];
2775    
2776            MainSearch16FuncPtr MainSearchPtr;
2777    
2778            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2779            MACROBLOCK *const pMB = pMBs + x + y * iWcount;
2780    
2781            int32_t threshA, threshB;
2782            int32_t bPredEq;
2783            int32_t iMinSAD, iSAD;
2784    
2785    
2786    /* Get maximum range */
2787            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2788                              iFcode);
2789    
2790    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2791    
2792            if ((x == 0) && (y == 0)) {
2793                    threshA = 512;
2794                    threshB = 1024;
2795    
2796                    bPredEq = 0;
2797                    psad[0] = psad[1] = psad[2] = psad[3] = 0;
2798                    *currMV = pmv[0] = pmv[1] = pmv[2] = pmv[3] = zeroMV;
2799    
2800            } else {
2801                    threshA = psad[0];
2802                    threshB = threshA + 256;
2803                    if (threshA < 512)
2804                            threshA = 512;
2805                    if (threshA > 1024)
2806                            threshA = 1024;
2807                    if (threshB > 1792)
2808                            threshB = 1792;
2809    
2810                    bPredEq = get_ipmvdata(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2811                    *currMV = pmv[0];                       /* current best := prediction */
2812            }
2813    
2814            iFound = 0;
2815    
2816    /* Step 4: Calculate SAD around the Median prediction.
2817       MinSAD=SAD
2818       If Motion Vector equal to Previous frame motion vector
2819       and MinSAD<PrevFrmSAD goto Step 10.
2820       If SAD<=256 goto Step 10.
2821    */
2822    
2823            if (currMV->x > max_dx) {
2824                    currMV->x = EVEN(max_dx);
2825            }
2826            if (currMV->x < min_dx) {
2827                    currMV->x = EVEN(min_dx);
2828            }
2829            if (currMV->y > max_dy) {
2830                    currMV->y = EVEN(max_dy);
2831            }
2832            if (currMV->y < min_dy) {
2833                    currMV->y = EVEN(min_dy);
2834            }
2835    
2836            iMinSAD =
2837                    sad16(cur,
2838                              get_iref_mv(pRef, x, y, 16, currMV,
2839                                                     iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2840            iMinSAD +=
2841                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2842                                              (uint8_t) iFcode, iQuant);
2843    
2844            if ((iMinSAD < 256) ||
2845                    ((MVequal(*currMV, prevMB->i_mvs[0])) &&
2846                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2847                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
2848                    {
2849                            if (!MVzero(*currMV)) {
2850                                    iMinSAD += MV16_00_BIAS;
2851                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
2852                                    iMinSAD -= MV16_00_BIAS;
2853                            }
2854                    }
2855    
2856                    if (MotionFlags & PMV_EARLYSTOP16)
2857                            goto PMVfastInt16_Terminate_with_Refine;
2858            }
2859    
2860    
2861    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2862       vector of the median.
2863       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2864    */
2865    
2866            if ((bPredEq) && (MVequal(pmv[0], prevMB->i_mvs[0])))
2867                    iFound = 2;
2868    
2869    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2870       Otherwise select large Diamond Search.
2871    */
2872    
2873            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
2874                    iDiamondSize = 2;               // halfpel units!
2875            else
2876                    iDiamondSize = 4;               // halfpel units!
2877    
2878    /*
2879       Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
2880       Also calculate (0,0) but do not subtract offset.
2881       Let MinSAD be the smallest SAD up to this point.
2882       If MV is (0,0) subtract offset.
2883    */
2884    
2885    // (0,0) is often a good choice
2886    
2887            if (!MVzero(pmv[0]))
2888                    CHECK_MV16_ZERO;
2889    
2890    // previous frame MV is always possible
2891    
2892            if (!MVzero(prevMB->i_mvs[0]))
2893                    if (!MVequal(prevMB->i_mvs[0], pmv[0]))
2894                            CHECK_MV16_CANDIDATE(prevMB->i_mvs[0].x, prevMB->i_mvs[0].y);
2895    
2896    // left neighbour, if allowed
2897    
2898            if (!MVzero(pmv[1]))
2899                    if (!MVequal(pmv[1], prevMB->i_mvs[0]))
2900                            if (!MVequal(pmv[1], pmv[0]))
2901                                    CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
2902    
2903    // top neighbour, if allowed
2904            if (!MVzero(pmv[2]))
2905                    if (!MVequal(pmv[2], prevMB->i_mvs[0]))
2906                            if (!MVequal(pmv[2], pmv[0]))
2907                                    if (!MVequal(pmv[2], pmv[1]))
2908                                            CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
2909    
2910    // top right neighbour, if allowed
2911                                            if (!MVzero(pmv[3]))
2912                                                    if (!MVequal(pmv[3], prevMB->i_mvs[0]))
2913                                                            if (!MVequal(pmv[3], pmv[0]))
2914                                                                    if (!MVequal(pmv[3], pmv[1]))
2915                                                                            if (!MVequal(pmv[3], pmv[2]))
2916                                                                                    CHECK_MV16_CANDIDATE(pmv[3].x,
2917                                                                                                                             pmv[3].y);
2918    
2919            if ((MVzero(*currMV)) &&
2920                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2921                    iMinSAD -= MV16_00_BIAS;
2922    
2923    
2924    /* Step 6: If MinSAD <= thresa goto Step 10.
2925       If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
2926    */
2927    
2928            if ((iMinSAD <= threshA) ||
2929                    (MVequal(*currMV, prevMB->i_mvs[0]) &&
2930                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2931    
2932                    if (MotionFlags & PMV_EARLYSTOP16)
2933                            goto PMVfastInt16_Terminate_with_Refine;
2934            }
2935    
2936    
2937    /************ (Diamond Search)  **************/
2938    /*
2939       Step 7: Perform Diamond search, with either the small or large diamond.
2940       If Found=2 only examine one Diamond pattern, and afterwards goto step 10
2941       Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
2942       If center then goto step 10.
2943       Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
2944       Refine by using small diamond and goto step 10.
2945    */
2946    
2947            if (MotionFlags & PMV_USESQUARES16)
2948                    MainSearchPtr = Square16_MainSearch;
2949            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2950                    MainSearchPtr = AdvDiamond16_MainSearch;
2951            else
2952                    MainSearchPtr = Diamond16_MainSearch;
2953    
2954            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2955    
2956    
2957    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2958            iSAD =
2959                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2960                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2961                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2962                                                      iQuant, iFound);
2963    
2964            if (iSAD < iMinSAD) {
2965                    *currMV = newMV;
2966                    iMinSAD = iSAD;
2967            }
2968    
2969            if (MotionFlags & PMV_EXTSEARCH16) {
2970    /* extended: search (up to) two more times: orignal prediction and (0,0) */
2971    
2972                    if (!(MVequal(pmv[0], backupMV))) {
2973                            iSAD =
2974                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2975                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2976                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2977                                                                      iDiamondSize, iFcode, iQuant, iFound);
2978    
2979                            if (iSAD < iMinSAD) {
2980                                    *currMV = newMV;
2981                                    iMinSAD = iSAD;
2982                            }
2983                    }
2984    
2985                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2986                            iSAD =
2987                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2988                                                                      iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2989                                                                      max_dy, iEdgedWidth, iDiamondSize, iFcode,
2990                                                                      iQuant, iFound);
2991    
2992                            if (iSAD < iMinSAD) {
2993                                    *currMV = newMV;
2994                                    iMinSAD = iSAD;
2995                            }
2996                    }
2997            }
2998    
2999    /*
3000       Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.
3001    */
3002    
3003    PMVfastInt16_Terminate_with_Refine:
3004    
3005            pMB->i_mvs[0] = pMB->i_mvs[1] = pMB->i_mvs[2] = pMB->i_mvs[3] = pMB->i_mv16 = *currMV;
3006            pMB->i_sad8[0] = pMB->i_sad8[1] = pMB->i_sad8[2] = pMB->i_sad8[3] = pMB->i_sad16 = iMinSAD;
3007    
3008            if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
3009                    iMinSAD =
3010                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
3011                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
3012                                                             iFcode, iQuant, iEdgedWidth);
3013    
3014            pmv[0] = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          // get _REAL_ prediction (halfpel possible)
3015    
3016    PMVfastInt16_Terminate_without_Refine:
3017            currPMV->x = currMV->x - center_x;
3018            currPMV->y = currMV->y - center_y;
3019            return iMinSAD;
3020    }
3021    
3022    
3023    
3024  /* ***********************************************************  /* ***********************************************************
# Line 2069  Line 3027 
3027  ***************************************************************/  ***************************************************************/
3028    
3029    
3030  void MotionEstimationBVOP(  #define DIRECT_PENALTY 0
3031                          MBParam * const pParam,  #define DIRECT_UPPERLIMIT 256   // never use direct mode if SAD is larger than this
                         FRAMEINFO * const frame,  
3032    
3033    void
3034    MotionEstimationBVOP(MBParam * const pParam,
3035                                             FRAMEINFO * const frame,
3036                                             const int32_t time_bp,
3037                                             const int32_t time_pp,
3038                          // forward (past) reference                          // forward (past) reference
3039                          const MACROBLOCK * const f_mbs,                          const MACROBLOCK * const f_mbs,
3040                      const IMAGE * const f_ref,                      const IMAGE * const f_ref,
# Line 2086  Line 3048 
3048                      const IMAGE * const b_refV,                      const IMAGE * const b_refV,
3049                          const IMAGE * const b_refHV)                          const IMAGE * const b_refHV)
3050  {  {
3051      const uint32_t mb_width = pParam->mb_width;          const int mb_width = pParam->mb_width;
3052      const uint32_t mb_height = pParam->mb_height;          const int mb_height = pParam->mb_height;
3053          const int32_t edged_width = pParam->edged_width;          const int edged_width = pParam->edged_width;
3054    
3055          uint32_t i,j;          int i, j, k;
3056    
3057          int32_t f_sad16;          static const VECTOR zeroMV={0,0};
3058          int32_t b_sad16;  
3059          int32_t i_sad16;          int f_sad16;    /* forward (as usual) search */
3060          int32_t d_sad16;          int b_sad16;    /* backward (only in b-frames) search */
3061          int32_t best_sad;          int i_sad16;    /* interpolated (both direction, b-frames only) */
3062            int d_sad16;    /* direct mode (assume linear motion) */
3063    
3064            int best_sad;
3065    
3066            VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/
3067          VECTOR pmv_dontcare;          VECTOR pmv_dontcare;
3068    
3069            int f_count=0;
3070            int b_count=0;
3071            int i_count=0;
3072            int d_count=0;
3073            int s_count=0;
3074    
3075            const int64_t TRB = (int32_t)time_pp - (int32_t)time_bp;
3076        const int64_t TRD = (int32_t)time_pp;
3077    
3078            // fprintf(stderr,"TRB = %lld  TRD = %lld  time_bp =%d time_pp =%d\n\n",TRB,TRD,time_bp,time_pp);
3079          // note: i==horizontal, j==vertical          // note: i==horizontal, j==vertical
3080      for (j = 0; j < mb_height; j++)          for (j = 0; j < mb_height; j++) {
3081          {  
3082                  for (i = 0; i < mb_width; i++)                  f_predMV = zeroMV;      /* prediction is reset at left boundary */
3083                  {                  b_predMV = zeroMV;
3084    
3085                    for (i = 0; i < mb_width; i++) {
3086                          MACROBLOCK *mb = &frame->mbs[i + j*mb_width];                          MACROBLOCK *mb = &frame->mbs[i + j*mb_width];
3087                          const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];                          const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];
3088                          const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];                          const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];
3089    
3090                          if (b_mb->mode == MODE_INTER                          mb->deltamv=zeroMV;
3091                                  && b_mb->cbp == 0  
3092                                  && b_mb->mvs[0].x == 0  /* special case, if collocated block is SKIPed: encoding is forward(0,0)  */
3093                                  && b_mb->mvs[0].y == 0)  
3094                          {  #ifndef _DISABLE_SKIP
3095                            if (b_mb->mode == MODE_INTER && b_mb->cbp == 0 &&
3096                                    b_mb->mvs[0].x == 0 && b_mb->mvs[0].y == 0) {
3097                                  mb->mode = MODE_NOT_CODED;                                  mb->mode = MODE_NOT_CODED;
3098                                  mb->mvs[0].x = 0;                                  mb->mvs[0].x = 0;
3099                                  mb->mvs[0].y = 0;                                  mb->mvs[0].y = 0;
# Line 2121  Line 3101 
3101                                  mb->b_mvs[0].y = 0;                                  mb->b_mvs[0].y = 0;
3102                                  continue;                                  continue;
3103                          }                          }
3104    #endif
3105    
3106                            d_sad16 = DIRECT_PENALTY;
3107    
3108                            if (b_mb->mode == MODE_INTER4V)
3109                            {
3110    
3111                            /* same method of scaling as in decoder.c, so we copy from there */
3112                        for (k = 0; k < 4; k++) {
3113    
3114                                            mb->directmv[k] = b_mb->mvs[k];
3115    
3116                                            mb->mvs[k].x = (int32_t) ((TRB * mb->directmv[k].x) / TRD + mb->deltamv.x);
3117                        mb->b_mvs[k].x = (int32_t) ((mb->deltamv.x == 0)
3118                                                                                    ? ((TRB - TRD) * mb->directmv[k].x) / TRD
3119                                                : mb->mvs[k].x - mb->directmv[k].x);
3120    
3121                        mb->mvs[k].y = (int32_t) ((TRB * mb->directmv[k].y) / TRD + mb->deltamv.y);
3122                            mb->b_mvs[k].y = (int32_t) ((mb->directmv[k].y == 0)
3123                                                                                    ? ((TRB - TRD) * mb->directmv[k].y) / TRD
3124                                                : mb->mvs[k].y - mb->directmv[k].y);
3125    
3126                                            d_sad16 +=
3127                                                    sad8bi(frame->image.y + 2*(i+(k&1))*8 + 2*(j+(k>>1))*8*edged_width,
3128                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3129                                                                    2*(i+(k&1)), 2*(j+(k>>1)), 8, &mb->mvs[k], edged_width),
3130                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3131                                                                    2*(i+(k&1)), 2*(j+(k>>1)), 8, &mb->b_mvs[k], edged_width),
3132                                                      edged_width);
3133                                    }
3134                            }
3135                            else
3136                            {
3137                                    mb->directmv[3] = mb->directmv[2] = mb->directmv[1] =
3138                                    mb->directmv[0] = b_mb->mvs[0];
3139    
3140                                    mb->mvs[0].x = (int32_t) ((TRB * mb->directmv[0].x) / TRD + mb->deltamv.x);
3141                        mb->b_mvs[0].x = (int32_t) ((mb->deltamv.x == 0)
3142                                                                            ? ((TRB - TRD) * mb->directmv[0].x) / TRD
3143                                        : mb->mvs[0].x - mb->directmv[0].x);
3144    
3145                        mb->mvs[0].y = (int32_t) ((TRB * mb->directmv[0].y) / TRD + mb->deltamv.y);
3146                    mb->b_mvs[0].y = (int32_t) ((mb->directmv[0].y == 0)
3147                                                                            ? ((TRB - TRD) * mb->directmv[0].y) / TRD
3148                                        : mb->mvs[0].y - mb->directmv[0].y);
3149    
3150                                    d_sad16 += sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,
3151                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3152                                                                    i, j, 16, &mb->mvs[0], edged_width),
3153                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3154                                                                    i, j, 16, &mb->b_mvs[0], edged_width),
3155                                                      edged_width);
3156    
3157                }
3158                        d_sad16 += calc_delta_16(mb->deltamv.x, mb->deltamv.y, 1, frame->quant);
3159    
3160                          // forward search                          // forward search
3161                          f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                          f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3162                                                  &frame->image,                                                  &frame->image, i, j,
3163                                                  i, j,                                                  mb->mvs[0].x, mb->mvs[0].y,                     /* start point f_directMV */
3164                                                  frame->motion_flags,  frame->quant, frame->fcode,                                                  f_predMV.x, f_predMV.y,                         /* center is f-prediction */
3165                                                  pParam,                                                  frame->motion_flags,
3166                                                  f_mbs, f_mbs /* todo */,                                                  frame->quant, frame->fcode, pParam,
3167                                                  &mb->mvs[0], &pmv_dontcare);    // ignore pmv                                                  f_mbs, f_mbs,
3168                                                    &mb->mvs[0], &pmv_dontcare);
3169    
3170    
3171                          // backward search                          // backward search
3172                          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,
3173                                                  &frame->image,                                                  &frame->image, i, j,
3174                                                  i, j,                                                  mb->b_mvs[0].x, mb->b_mvs[0].y,         /* start point b_directMV */
3175                                                  frame->motion_flags,  frame->quant, frame->bcode,                                                  b_predMV.x, b_predMV.y,                         /* center is b-prediction */
3176                                                  pParam,                                                  frame->motion_flags,
3177                                                  b_mbs, b_mbs, /* todo */                                                  frame->quant, frame->bcode, pParam,
3178                                                  &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv                                                  b_mbs, b_mbs,
3179                                                    &mb->b_mvs[0], &pmv_dontcare);
3180                          // interpolate search (simple, but effective)  
3181                          i_sad16 = sad16bi_c(                          i_sad16 =
3182                                          frame->image.y + i*16 + j*16*edged_width,                                  sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,
3183                                          get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                                                    get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3184                                                  i, j, 16, mb->mvs[0].x, mb->mvs[0].y, edged_width),                                                                  i, j, 16, &mb->mvs[0], edged_width),
3185                                          get_ref(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,                                                    get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3186                                                  i, j, 16, mb->b_mvs[0].x, mb->b_mvs[0].x, edged_width),                                                                  i, j, 16, &mb->b_mvs[0], edged_width),
3187                                          edged_width);                                          edged_width);
3188                        i_sad16 += calc_delta_16(mb->mvs[0].x-f_predMV.x, mb->mvs[0].y-f_predMV.y,
3189                                                                    frame->fcode, frame->quant);
3190                        i_sad16 += calc_delta_16(mb->b_mvs[0].x-b_predMV.x, mb->b_mvs[0].y-b_predMV.y,
3191                                                                    frame->bcode, frame->quant);
3192    
3193                          // TODO: direct search                          // TODO: direct search
3194                          // predictor + range of [-32,32]                          // predictor + delta vector in range [-32,32] (fcode=1)
                         d_sad16 = 65535;  
3195    
3196                            i_sad16 = 65535;
3197                            f_sad16 = 65535;
3198                            b_sad16 = 65535;
3199    //                      d_sad16 = 65535;
3200    
3201                          if (f_sad16 < b_sad16)                          if (f_sad16 < b_sad16) {
                         {  
3202                                  best_sad = f_sad16;                                  best_sad = f_sad16;
3203                                  mb->mode = MODE_FORWARD;                                  mb->mode = MODE_FORWARD;
3204                          }                          } else {
                         else  
                         {  
3205                                  best_sad = b_sad16;                                  best_sad = b_sad16;
3206                                  mb->mode = MODE_BACKWARD;                                  mb->mode = MODE_BACKWARD;
3207                          }                          }
3208    
3209                          if (i_sad16 < best_sad)                          if (i_sad16 < best_sad) {
                         {  
3210                                  best_sad = i_sad16;                                  best_sad = i_sad16;
3211                                  mb->mode = MODE_INTERPOLATE;                                  mb->mode = MODE_INTERPOLATE;
3212                          }                          }
3213    
3214                          if (d_sad16 < best_sad)                          if (d_sad16 < best_sad) {
3215    
3216                                    if (b_mb->mode == MODE_INTER4V)
3217                          {                          {
3218    
3219                                    /* same method of scaling as in decoder.c, so we copy from there */
3220                                for (k = 0; k < 4; k++) {
3221    
3222                                                    mb->mvs[k].x = (int32_t) ((TRB * mb->directmv[k].x) / TRD + mb->deltamv.x);
3223                                mb->b_mvs[k].x = (int32_t) ((mb->deltamv.x == 0)
3224                                                                                            ? ((TRB - TRD) * mb->directmv[k].x) / TRD
3225                                                        : mb->mvs[k].x - mb->directmv[k].x);
3226    
3227                                mb->mvs[k].y = (int32_t) ((TRB * mb->directmv[k].y) / TRD + mb->deltamv.y);
3228                            mb->b_mvs[k].y = (int32_t) ((mb->directmv[k].y == 0)
3229                                                                                            ? ((TRB - TRD) * mb->directmv[k].y) / TRD
3230                                                : mb->mvs[k].y - mb->directmv[k].y);
3231                                            }
3232                                    }
3233                                    else
3234                                    {
3235                                            mb->mvs[0].x = (int32_t) ((TRB * mb->directmv[0].x) / TRD + mb->deltamv.x);
3236    
3237                        mb->b_mvs[0].x = (int32_t) ((mb->deltamv.x == 0)
3238                                                                                    ? ((TRB - TRD) * mb->directmv[0].x) / TRD
3239                                            : mb->mvs[0].x - mb->directmv[0].x);
3240    
3241                                mb->mvs[0].y = (int32_t) ((TRB * mb->directmv[0].y) / TRD + mb->deltamv.y);
3242    
3243                            mb->b_mvs[0].y = (int32_t) ((mb->directmv[0].y == 0)
3244                                                                                    ? ((TRB - TRD) * mb->directmv[0].y) / TRD
3245                                                : mb->mvs[0].y - mb->directmv[0].y);
3246    
3247                                            mb->mvs[3] = mb->mvs[2] = mb->mvs[1] = mb->mvs[0];
3248                                            mb->b_mvs[3] = mb->b_mvs[2] = mb->b_mvs[1] = mb->b_mvs[0];
3249                    }
3250    
3251                                  best_sad = d_sad16;                                  best_sad = d_sad16;
3252                                  mb->mode = MODE_DIRECT;                                  mb->mode = MODE_DIRECT;
3253                                    mb->mode = MODE_INTERPOLATE;            // direct mode still broken :-(
3254                            }
3255    
3256                            switch (mb->mode)
3257                            {
3258                                    case MODE_FORWARD:
3259                                            f_count++;
3260                                            f_predMV = mb->mvs[0];
3261                                            break;
3262                                    case MODE_BACKWARD:
3263                                            b_count++;
3264                                            b_predMV = mb->b_mvs[0];
3265    
3266                                            break;
3267                                    case MODE_INTERPOLATE:
3268                                            i_count++;
3269                                            f_predMV = mb->mvs[0];
3270                                            b_predMV = mb->b_mvs[0];
3271                                            break;
3272                                    case MODE_DIRECT:
3273                                            d_count++;
3274                                            break;
3275                                    default:
3276                                            s_count++;              // ???
3277                                            break;
3278                          }                          }
3279    
3280                  }                  }
3281          }          }
3282    
3283    #ifdef _DEBUG_BFRAME_STAT
3284            fprintf(stderr,"B-Stat: F: %04d   B: %04d   I: %04d  D: %04d   S: %04d\n",
3285                                    f_count,b_count,i_count,d_count,s_count);
3286    #endif
3287    
3288  }  }

Legend:
Removed from v.174  
changed lines
  Added in v.345

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