[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 170, Thu May 9 21:47:51 2002 UTC revision 370, Mon Aug 12 10:07:16 2002 UTC
# Line 1  Line 1 
1  /**************************************************************************  /**************************************************************************
2   *   *
3     *      XVID MPEG-4 VIDEO CODEC
4     *      motion estimation
5     *
6     *      This program is an implementation of a part of one or more MPEG-4
7     *      Video tools as specified in ISO/IEC 14496-2 standard.  Those intending
8     *      to use this software module in hardware or software products are
9     *      advised that its use may infringe existing patents or copyrights, and
10     *      any such use would be at such party's own risk.  The original
11     *      developer of this software module and his/her company, and subsequent
12     *      editors and their companies, will have no liability for use of this
13     *      software or modifications or derivatives thereof.
14     *
15     *      This program is free software; you can redistribute it and/or modify
16     *      it under the terms of the GNU General Public License as published by
17     *      the Free Software Foundation; either version 2 of the License, or
18     *      (at your option) any later version.
19     *
20     *      This program is distributed in the hope that it will be useful,
21     *      but WITHOUT ANY WARRANTY; without even the implied warranty of
22     *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23     *      GNU General Public License for more details.
24     *
25     *      You should have received a copy of the GNU General Public License
26     *      along with this program; if not, write to the Free Software
27     *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28     *
29     *************************************************************************/
30    
31    /**************************************************************************
32     *
33   *  Modifications:   *  Modifications:
34   *   *
35   *      01.05.2002      updated MotionEstimationBVOP   *      01.05.2002      updated MotionEstimationBVOP
# Line 47  Line 77 
77  #include "motion.h"  #include "motion.h"
78  #include "sad.h"  #include "sad.h"
79    
 // very large value  
 #define MV_MAX_ERROR    (4096 * 256)  
   
 // stop search if sdelta < THRESHOLD  
 #define MV16_THRESHOLD  192  
 #define MV8_THRESHOLD   56  
   
 /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */  
 /* nb  = vop pixels * 2^(bpp-8) */  
 #define MV16_00_BIAS    (128+1)  
 #define MV8_00_BIAS     (0)  
   
 /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */  
 #define INTER_BIAS      512  
   
 /* Parameters which control inter/inter4v decision */  
 #define IMV16X16                        5  
   
 /* vector map (vlc delta size) smoother parameters */  
 #define NEIGH_TEND_16X16        2  
 #define NEIGH_TEND_8X8          2  
   
   
 // fast ((A)/2)*2  
 #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)  
   
   
 int32_t PMVfastSearch16(  
                                         const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const uint32_t MotionFlags,  
                                         const uint32_t iQuant,  
                                         const uint32_t iFcode,  
                                         const MBParam * const pParam,  
                                         const MACROBLOCK * const pMBs,  
                                         const MACROBLOCK * const prevMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
 int32_t EPZSSearch16(  
                                         const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const uint32_t MotionFlags,  
                                         const uint32_t iQuant,  
                                         const uint32_t iFcode,  
                                         const MBParam * const pParam,  
                                         const MACROBLOCK * const pMBs,  
                                         const MACROBLOCK * const prevMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
   
 int32_t PMVfastSearch8(  
                                         const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const int start_x, const int start_y,  
                                         const uint32_t MotionFlags,  
                                         const uint32_t iQuant,  
                                         const uint32_t iFcode,  
                                         const MBParam * const pParam,  
                                         const MACROBLOCK * const pMBs,  
                                         const MACROBLOCK * const prevMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
 int32_t EPZSSearch8(  
                                         const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const int start_x, const int start_y,  
                                         const uint32_t MotionFlags,  
                                         const uint32_t iQuant,  
                                         const uint32_t iFcode,  
                                         const MBParam * const pParam,  
                                         const MACROBLOCK * const pMBs,  
                                         const MACROBLOCK * const prevMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
   
 typedef int32_t (MainSearch16Func)(  
         const uint8_t * const pRef,  
         const uint8_t * const pRefH,  
         const uint8_t * const pRefV,  
         const uint8_t * const pRefHV,  
         const uint8_t * const cur,  
         const int x, const int y,  
         int32_t startx, int32_t starty,  
         int32_t iMinSAD,  
         VECTOR * const currMV,  
         const VECTOR * const pmv,  
         const int32_t min_dx, const int32_t max_dx,  
         const int32_t min_dy, const int32_t max_dy,  
         const int32_t iEdgedWidth,  
         const int32_t iDiamondSize,  
         const int32_t iFcode,  
         const int32_t iQuant,  
         int iFound);  
   
 typedef MainSearch16Func* MainSearch16FuncPtr;  
   
   
 typedef int32_t (MainSearch8Func)(  
         const uint8_t * const pRef,  
         const uint8_t * const pRefH,  
         const uint8_t * const pRefV,  
         const uint8_t * const pRefHV,  
         const uint8_t * const cur,  
         const int x, const int y,  
         int32_t startx, int32_t starty,  
         int32_t iMinSAD,  
         VECTOR * const currMV,  
         const VECTOR * const pmv,  
         const int32_t min_dx, const int32_t max_dx,  
         const int32_t min_dy, const int32_t max_dy,  
         const int32_t iEdgedWidth,  
         const int32_t iDiamondSize,  
         const int32_t iFcode,  
         const int32_t iQuant,  
         int iFound);  
80    
 typedef MainSearch8Func* MainSearch8FuncPtr;  
81    
82  static int32_t lambda_vec16[32] =  /* rounded values for lambda param for weight of motion bits as in modified H.26L */  static int32_t lambda_vec16[32] =  /* rounded values for lambda param for weight of motion bits as in modified H.26L */
83          {     0    ,(int)(1.00235+0.5), (int)(1.15582+0.5), (int)(1.31976+0.5), (int)(1.49591+0.5), (int)(1.68601+0.5),  { 0, (int) (1.00235 + 0.5), (int) (1.15582 + 0.5), (int) (1.31976 + 0.5),
84          (int)(1.89187+0.5), (int)(2.11542+0.5), (int)(2.35878+0.5), (int)(2.62429+0.5), (int)(2.91455+0.5),                  (int) (1.49591 + 0.5), (int) (1.68601 + 0.5),
85          (int)(3.23253+0.5), (int)(3.58158+0.5), (int)(3.96555+0.5), (int)(4.38887+0.5), (int)(4.85673+0.5),          (int) (1.89187 + 0.5), (int) (2.11542 + 0.5), (int) (2.35878 + 0.5),
86          (int)(5.37519+0.5), (int)(5.95144+0.5), (int)(6.59408+0.5), (int)(7.31349+0.5), (int)(8.12242+0.5),                  (int) (2.62429 + 0.5), (int) (2.91455 + 0.5),
87          (int)(9.03669+0.5), (int)(10.0763+0.5), (int)(11.2669+0.5), (int)(12.6426+0.5), (int)(14.2493+0.5),          (int) (3.23253 + 0.5), (int) (3.58158 + 0.5), (int) (3.96555 + 0.5),
88          (int)(16.1512+0.5), (int)(18.442+0.5),  (int)(21.2656+0.5), (int)(24.8580+0.5), (int)(29.6436+0.5),                  (int) (4.38887 + 0.5), (int) (4.85673 + 0.5),
89          (int)(36.4949+0.5)      };          (int) (5.37519 + 0.5), (int) (5.95144 + 0.5), (int) (6.59408 + 0.5),
90                    (int) (7.31349 + 0.5), (int) (8.12242 + 0.5),
91            (int) (9.03669 + 0.5), (int) (10.0763 + 0.5), (int) (11.2669 + 0.5),
92                    (int) (12.6426 + 0.5), (int) (14.2493 + 0.5),
93            (int) (16.1512 + 0.5), (int) (18.442 + 0.5), (int) (21.2656 + 0.5),
94                    (int) (24.8580 + 0.5), (int) (29.6436 + 0.5),
95            (int) (36.4949 + 0.5)
96    };
97    
98  static int32_t *lambda_vec8 = lambda_vec16;     /* same table for INTER and INTER4V for now*/  static int32_t *lambda_vec8 = lambda_vec16;     /* same table for INTER and INTER4V for now*/
99    
# Line 207  Line 108 
108  };  };
109    
110    
111  static __inline uint32_t mv_bits(int32_t component, const uint32_t iFcode)  static __inline uint32_t
112    mv_bits(int32_t component,
113                    const uint32_t iFcode)
114  {  {
115      if (component == 0)      if (component == 0)
116                  return 1;                  return 1;
# Line 215  Line 118 
118      if (component < 0)      if (component < 0)
119                  component = -component;                  component = -component;
120    
121      if (iFcode == 1)          if (iFcode == 1) {
     {  
122                  if (component > 32)                  if (component > 32)
123                      component = 32;                      component = 32;
124    
# Line 233  Line 135 
135  }  }
136    
137    
138  static __inline uint32_t calc_delta_16(const int32_t dx, const int32_t dy, const uint32_t iFcode, const uint32_t iQuant)  static __inline uint32_t
139    calc_delta_16(const int32_t dx,
140                              const int32_t dy,
141                              const uint32_t iFcode,
142                              const uint32_t iQuant)
143  {  {
144          return NEIGH_TEND_16X16 * lambda_vec16[iQuant] * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));          return NEIGH_TEND_16X16 * lambda_vec16[iQuant] * (mv_bits(dx, iFcode) +
145                                                                                                              mv_bits(dy, iFcode));
146  }  }
147    
148  static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode, const uint32_t iQuant)  static __inline uint32_t
149    calc_delta_8(const int32_t dx,
150                             const int32_t dy,
151                             const uint32_t iFcode,
152                             const uint32_t iQuant)
153  {  {
154      return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));          return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) +
155                                                                                                       mv_bits(dy, iFcode));
156  }  }
157    
158    bool
159    MotionEstimation(MBParam * const pParam,
   
   
 #ifndef SEARCH16  
 #define SEARCH16        PMVfastSearch16  
 //#define SEARCH16      FullSearch16  
 //#define SEARCH16      EPZSSearch16  
 #endif  
   
 #ifndef SEARCH8  
 #define SEARCH8         PMVfastSearch8  
 //#define SEARCH8       EPZSSearch8  
 #endif  
   
 bool MotionEstimation(  
         MBParam * const pParam,  
160          FRAMEINFO * const current,          FRAMEINFO * const current,
161          FRAMEINFO * const reference,          FRAMEINFO * const reference,
162          const IMAGE * const pRefH,          const IMAGE * const pRefH,
163          const IMAGE * const pRefV,          const IMAGE * const pRefV,
164          const IMAGE * const pRefHV,          const IMAGE * const pRefHV,
165          const uint32_t iLimit)          const uint32_t iLimit)
   
166  {  {
167          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
168          const uint32_t iHcount = pParam->mb_height;          const uint32_t iHcount = pParam->mb_height;
169          MACROBLOCK * pMBs = current->mbs;          MACROBLOCK *const pMBs = current->mbs;
170          IMAGE * pCurrent = &current->image;          MACROBLOCK *const prevMBs = reference->mbs;
171            const IMAGE *const pCurrent = &current->image;
172          MACROBLOCK * prevMBs = reference->mbs;  // previous frame          const IMAGE *const pRef = &reference->image;
173          IMAGE * pRef = &reference->image;  
174            static const VECTOR zeroMV = { 0, 0 };
175            VECTOR predMV;
176          uint32_t i, j, iIntra = 0;  
177            int32_t x, y;
178          VECTOR mv16;          int32_t iIntra = 0;
179          VECTOR pmv16;          VECTOR pmv;
   
         int32_t sad8 = 0;  
         int32_t sad16;  
         int32_t deviation;  
180    
181          if (sadInit)          if (sadInit)
182                  (*sadInit)();                  (*sadInit)();
183    
184          // note: i==horizontal, j==vertical          for (y = 0; y < iHcount; y++)   {
185          for (i = 0; i < iHcount; i++)                  for (x = 0; x < iWcount; x ++)  {
                 for (j = 0; j < iWcount; j++)  
                 {  
                         MACROBLOCK *pMB = &pMBs[j + i * iWcount];  
                         MACROBLOCK *prevMB = &prevMBs[j + i * iWcount];  
186    
187                          sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                          MACROBLOCK *const pMB = &pMBs[x + y * iWcount];
                                          j, i, current->motion_flags, current->quant, current->fcode,  
                                          pParam, pMBs, prevMBs, &mv16, &pmv16);  
                         pMB->sad16=sad16;  
188    
189                            if (pMB->mode == MODE_NOT_CODED)
190                                    continue;
191    
192                          /* decide: MODE_INTER or MODE_INTRA                          predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
                            if (dev_intra < sad_inter - 2 * nb) use_intra  
                         */  
193    
194                          deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width);                          pMB->sad16 =
195                                    SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
196                                                     x, y, predMV.x, predMV.y, predMV.x, predMV.y,
197                                                     current->motion_flags, current->quant,
198                                                     current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,
199                                                     &pMB->pmvs[0]);
200    
201                          if (deviation < (sad16 - INTER_BIAS))                          if (0 < (pMB->sad16 - MV16_INTER_BIAS)) {
202                          {                                  int32_t deviation;
                                 pMB->mode = MODE_INTRA;  
                                 pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;  
                                 pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;  
203    
204                                  pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = 0;                                  deviation =
205                                            dev16(pCurrent->y + x * 16 + y * 16 * pParam->edged_width,
206                                                      pParam->edged_width);
207    
208                                    if (deviation < (pMB->sad16 - MV16_INTER_BIAS)) {
209                                            pMB->mode = MODE_INTRA;
210                                            pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
211                                                    pMB->mvs[3] = zeroMV;
212                                            pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
213                                                    pMB->sad8[3] = 0;
214    
215                                  iIntra++;                                  iIntra++;
216                                  if(iIntra >= iLimit)                                  if(iIntra >= iLimit)
# Line 323  Line 218 
218    
219                                  continue;                                  continue;
220                          }                          }
221                            }
222    
223                            pmv = pMB->pmvs[0];
224                          if (current->global_flags & XVID_INTER4V)                          if (current->global_flags & XVID_INTER4V)
225                          {                                  if ((!(current->global_flags & XVID_LUMIMASKING) ||
226                                  pMB->sad8[0] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                           pMB->dquant == NO_CHANGE)) {
227                                                         2 * j, 2 * i, mv16.x, mv16.y,                                          int32_t sad8 = IMV16X16 * current->quant;
228                                                             current->motion_flags, current->quant, current->fcode,  
229                                                         pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]);                                          if (sad8 < pMB->sad16) {
230                                                    sad8 += pMB->sad8[0] =
231                                  pMB->sad8[1] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
232                                                         2 * j + 1, 2 * i, mv16.x, mv16.y,                                                                          pCurrent, 2 * x, 2 * y,
233                                                             current->motion_flags, current->quant, current->fcode,                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
234                                                         pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]);                                                                          current->motion_flags,
235                                                                            current->quant, current->fcode, pParam,
236                                  pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                                          pMBs, prevMBs, &pMB->mvs[0],
237                                                         2 * j, 2 * i + 1, mv16.x, mv16.y,                                                                          &pMB->pmvs[0]);
238                                                             current->motion_flags, current->quant, current->fcode,                                          }
239                                                         pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]);                                          if (sad8 < pMB->sad16) {
240    
241                                  pMB->sad8[3] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                  predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 1);
242                                                         2 * j + 1, 2 * i + 1, mv16.x, mv16.y,                                                  sad8 += pMB->sad8[1] =
243                                                             current->motion_flags, current->quant, current->fcode,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
244                                                         pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]);                                                                          pCurrent, 2 * x + 1, 2 * y,
245                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
246                                  sad8 = pMB->sad8[0] + pMB->sad8[1] + pMB->sad8[2] + pMB->sad8[3];                                                                          current->motion_flags,
247                                                                            current->quant, current->fcode, pParam,
248                                                                            pMBs, prevMBs, &pMB->mvs[1],
249                                                                            &pMB->pmvs[1]);
250                                            }
251                                            if (sad8 < pMB->sad16) {
252                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 2);
253                                                    sad8 += pMB->sad8[2] =
254                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
255                                                                            pCurrent, 2 * x, 2 * y + 1,
256                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
257                                                                            current->motion_flags,
258                                                                            current->quant, current->fcode, pParam,
259                                                                            pMBs, prevMBs, &pMB->mvs[2],
260                                                                            &pMB->pmvs[2]);
261                                            }
262                                            if (sad8 < pMB->sad16) {
263                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 3);
264                                                    sad8 += pMB->sad8[3] =
265                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
266                                                                            pCurrent, 2 * x + 1, 2 * y + 1,
267                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
268                                                                            current->motion_flags,
269                                                                            current->quant, current->fcode, pParam,
270                                                                            pMBs, prevMBs,
271                                                                            &pMB->mvs[3],
272                                                                            &pMB->pmvs[3]);
273                          }                          }
274    
   
275                          /* decide: MODE_INTER or MODE_INTER4V                          /* decide: MODE_INTER or MODE_INTER4V
276                             mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v                                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
277                          */                          */
278    
279                          if (!(current->global_flags & XVID_LUMIMASKING) || pMB->dquant == NO_CHANGE)                                          if (sad8 < pMB->sad16) {
                         {  
                                 if (((current->global_flags & XVID_INTER4V)==0) ||  
                                     (sad16 < (sad8 + (int32_t)(IMV16X16 * current->quant))))  
                                 {  
   
                                         sad8 = sad16;  
                                         pMB->mode = MODE_INTER;  
                                         pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;  
                                         pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;  
                                         pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = sad16;  
                                         pMB->pmvs[0].x = pmv16.x;  
                                         pMB->pmvs[0].y = pmv16.y;  
                                 }  
                                 else  
                                 {  
280                                          pMB->mode = MODE_INTER4V;                                          pMB->mode = MODE_INTER4V;
281                                          pMB->sad8[0] *= 4;                                          pMB->sad8[0] *= 4;
282                                          pMB->sad8[1] *= 4;                                          pMB->sad8[1] *= 4;
283                                          pMB->sad8[2] *= 4;                                          pMB->sad8[2] *= 4;
284                                          pMB->sad8[3] *= 4;                                          pMB->sad8[3] *= 4;
285                                                    continue;
286                                  }                                  }
287    
288                          }                          }
                         else  
                         {  
                                 sad8 = sad16;  
                                 pMB->mode = MODE_INTER;  
                                 pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;  
                                 pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;  
                                 pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = sad16;  
289    
290                                  pMB->pmvs[0].x = pmv16.x;                          pMB->mode = MODE_INTER;
291                                  pMB->pmvs[0].y = pmv16.y;                          pMB->pmvs[0] = pmv;     /* pMB->pmvs[1] = pMB->pmvs[2] = pMB->pmvs[3]  are not needed for INTER */
292                            pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
293                            pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =
294                                    pMB->sad16;
295                          }                          }
296                  }                  }
297    
298          return 0;          return 0;
299  }  }
300    
 #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )  
   
 #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )  
   
301    
302  #define CHECK_MV16_ZERO {\  #define CHECK_MV16_ZERO {\
303    if ( (0 <= max_dx) && (0 >= min_dx) \    if ( (0 <= max_dx) && (0 >= min_dx) \
304      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
305    { \    { \
306      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \
307      iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16(-center_x, -center_y, (uint8_t)iFcode, iQuant);\
308      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
309      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
310  }  }
311    
312  #define NOCHECK_MV16_CANDIDATE(X,Y) { \  #define NOCHECK_MV16_CANDIDATE(X,Y) { \
313      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
314      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
315      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
316      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
317  }  }
# Line 420  Line 321 
321      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
322    { \    { \
323      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
324      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
325      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
326      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
327  }  }
# Line 430  Line 331 
331      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
332    { \    { \
333      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
334      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
335      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
336      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
337  }  }
# Line 440  Line 341 
341      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
342    { \    { \
343      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
344      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
345      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
346      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
347  }  }
# Line 448  Line 349 
349    
350  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
351    iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \    iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \
352    iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\    iSAD += calc_delta_8(-center_x, -center_y, (uint8_t)iFcode, iQuant);\
353    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
354    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
355  }  }
# Line 456  Line 357 
357  #define NOCHECK_MV8_CANDIDATE(X,Y) \  #define NOCHECK_MV8_CANDIDATE(X,Y) \
358    { \    { \
359      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
360      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
361      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
362      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
363  }  }
# Line 466  Line 367 
367      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
368    { \    { \
369      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
370      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
371      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
372      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
373  }  }
# Line 476  Line 377 
377      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
378    { \    { \
379      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
380      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
381      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
382      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
383  }  }
# Line 486  Line 387 
387      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
388    { \    { \
389      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
390      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
391      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
392      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
393  }  }
# Line 512  Line 413 
413          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
414          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
415          int32_t iSAD;          int32_t iSAD;
416          int32_t pred_x,pred_y;          VECTOR pred;
417    
418    
419          get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);          pred = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
420    
421          iSAD = sad16( cur,          iSAD = sad16( cur,
422                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),
# Line 524  Line 426 
426    
427          currMV->x = 0;          currMV->x = 0;
428          currMV->y = 0;          currMV->y = 0;
429          currPMV->x = -pred_x;          currPMV->x = -pred.x;
430          currPMV->y = -pred_y;          currPMV->y = -pred.y;
431    
432          return iSAD;          return iSAD;
433    
434  }  }
435  */  */
436    
437  int32_t Diamond16_MainSearch(  int32_t
438          const uint8_t * const pRef,  Diamond16_MainSearch(const uint8_t * const pRef,
439          const uint8_t * const pRefH,          const uint8_t * const pRefH,
440          const uint8_t * const pRefV,          const uint8_t * const pRefV,
441          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
442          const uint8_t * const cur,          const uint8_t * const cur,
443          const int x, const int y,                                           const int x,
444          int32_t startx, int32_t starty,                                           const int y,
445          int32_t iMinSAD,                                     const int start_x,
446                                       const int start_y,
447                                       int iMinSAD,
448          VECTOR * const currMV,          VECTOR * const currMV,
449          const VECTOR * const pmv,                                     const int center_x,
450          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
451          const int32_t min_dy, const int32_t max_dy,                                           const int32_t min_dx,
452                                             const int32_t max_dx,
453                                             const int32_t min_dy,
454                                             const int32_t max_dy,
455          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
456          const int32_t iDiamondSize,          const int32_t iDiamondSize,
457          const int32_t iFcode,          const int32_t iFcode,
# Line 554  Line 461 
461  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
462    
463          int32_t iDirection=0;          int32_t iDirection=0;
464            int32_t iDirectionBackup;
465          int32_t iSAD;          int32_t iSAD;
466          VECTOR backupMV;          VECTOR backupMV;
467          backupMV.x = startx;  
468          backupMV.y = starty;          backupMV.x = start_x;
469            backupMV.y = start_y;
470    
471  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
472    
# Line 566  Line 475 
475          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
476          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
477    
478          if (iDirection)          if (iDirection) {
479                  while (!iFound)                  while (!iFound) {
                 {  
480                          iFound = 1;                          iFound = 1;
481                          backupMV=*currMV;                          backupMV=*currMV;
482                            iDirectionBackup = iDirection;
483    
484                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
485                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
486                          if ( iDirection != 1)                                                                                     backupMV.y, 1);
487                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
488                          if ( iDirection != 4)                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
489                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                     backupMV.y, 2);
490                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
491                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
492                  }                                                                                     backupMV.y - iDiamondSize, 3);
493          else                          if (iDirectionBackup != 3)
494          {                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
495                  currMV->x = startx;                                                                                     backupMV.y + iDiamondSize, 4);
496                  currMV->y = starty;                  }
497            } else {
498                    currMV->x = start_x;
499                    currMV->y = start_y;
500          }          }
501          return iMinSAD;          return iMinSAD;
502  }  }
503    
504  int32_t Square16_MainSearch(  int32_t
505                                          const uint8_t * const pRef,  Square16_MainSearch(const uint8_t * const pRef,
506                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
507                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
508                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
509                                          const uint8_t * const cur,                                          const uint8_t * const cur,
510                                          const int x, const int y,                                          const int x,
511                                          int32_t startx, int32_t starty,                                          const int y,
512                                          int32_t iMinSAD,                                     const int start_x,
513                                       const int start_y,
514                                       int iMinSAD,
515                                          VECTOR * const currMV,                                          VECTOR * const currMV,
516                                          const VECTOR * const pmv,                                     const int center_x,
517                                          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
518                                          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
519                                            const int32_t max_dx,
520                                            const int32_t min_dy,
521                                            const int32_t max_dy,
522                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
523                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
524                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 613  Line 530 
530          int32_t iDirection=0;          int32_t iDirection=0;
531          int32_t iSAD;          int32_t iSAD;
532          VECTOR backupMV;          VECTOR backupMV;
533          backupMV.x = startx;  
534          backupMV.y = starty;          backupMV.x = start_x;
535            backupMV.y = start_y;
536    
537  /* It's one search with full square pattern, and new parts for all following diamonds */  /* It's one search with full square pattern, and new parts for all following diamonds */
538    
# Line 629  Line 547 
547          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
548          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
549    
550          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
551          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                           backupMV.y - iDiamondSize, 5);
552          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
553          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                                           backupMV.y + iDiamondSize, 6);
554            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
555                                                             backupMV.y - iDiamondSize, 7);
556            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
557                                                             backupMV.y + iDiamondSize, 8);
558    
559    
560          if (iDirection)          if (iDirection) {
561                  while (!iFound)                  while (!iFound) {
                 {  
562                          iFound = 1;                          iFound = 1;
563                          backupMV=*currMV;                          backupMV=*currMV;
564    
565                          switch (iDirection)                          switch (iDirection) {
                         {  
566                                  case 1:                                  case 1:
567                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
568                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                     backupMV.y, 1);
569                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
570                                                                                     backupMV.y - iDiamondSize, 5);
571                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
572                                                                                     backupMV.y - iDiamondSize, 7);
573                                          break;                                          break;
574                                  case 2:                                  case 2:
575                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
576                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   2);
577                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
578                                                                                     backupMV.y + iDiamondSize, 6);
579                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
580                                                                                     backupMV.y + iDiamondSize, 8);
581                                          break;                                          break;
582    
583                                  case 3:                                  case 3:
584                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
585                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
586                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
587                                                                                     backupMV.y - iDiamondSize, 7);
588                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
589                                                                                     backupMV.y + iDiamondSize, 8);
590                                          break;                                          break;
591    
592                                  case 4:                                  case 4:
593                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
594                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
595                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
596                                                                                     backupMV.y - iDiamondSize, 5);
597                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
598                                                                                     backupMV.y + iDiamondSize, 6);
599                                          break;                                          break;
600    
601                                  case 5:                                  case 5:
602                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
603                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   1);
604                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
605                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   3);
606                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
607                                                                                     backupMV.y - iDiamondSize, 5);
608                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
609                                                                                     backupMV.y + iDiamondSize, 6);
610                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
611                                                                                     backupMV.y - iDiamondSize, 7);
612                                          break;                                          break;
613    
614                                  case 6:                                  case 6:
615                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
616                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   2);
617                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
618                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
619                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);  
620                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
621                                                                                     backupMV.y - iDiamondSize, 5);
622                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
623                                                                                     backupMV.y + iDiamondSize, 6);
624                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
625                                                                                     backupMV.y + iDiamondSize, 8);
626    
627                                          break;                                          break;
628    
629                                  case 7:                                  case 7:
630                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
631                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                     backupMV.y, 1);
632                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
633                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
634                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
635                                                                                     backupMV.y - iDiamondSize, 5);
636                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
637                                                                                     backupMV.y - iDiamondSize, 7);
638                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
639                                                                                     backupMV.y + iDiamondSize, 8);
640                                          break;                                          break;
641    
642                                  case 8:                                  case 8:
643                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
644                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
645                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
646                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
647                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
648                                                                                     backupMV.y + iDiamondSize, 6);
649                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
650                                                                                     backupMV.y - iDiamondSize, 7);
651                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
652                                                                                     backupMV.y + iDiamondSize, 8);
653                                          break;                                          break;
654                          default:                          default:
655                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
656                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                                                                   1);
657                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
658                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
659                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
660                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
661                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
662                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
663                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);  
664                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
665                                                                                     backupMV.y - iDiamondSize, 5);
666                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
667                                                                                     backupMV.y + iDiamondSize, 6);
668                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
669                                                                                     backupMV.y - iDiamondSize, 7);
670                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
671                                                                                     backupMV.y + iDiamondSize, 8);
672                                          break;                                          break;
673                          }                          }
674                  }                  }
675          else          } else {
676                  {                  currMV->x = start_x;
677                          currMV->x = startx;                  currMV->y = start_y;
                         currMV->y = starty;  
678                  }                  }
679          return iMinSAD;          return iMinSAD;
680  }  }
681    
682    
683  int32_t Full16_MainSearch(  int32_t
684                                          const uint8_t * const pRef,  Full16_MainSearch(const uint8_t * const pRef,
685                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
686                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
687                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
688                                          const uint8_t * const cur,                                          const uint8_t * const cur,
689                                          const int x, const int y,                                    const int x,
690                                          int32_t startx, int32_t starty,                                    const int y,
691                                          int32_t iMinSAD,                                     const int start_x,
692                                       const int start_y,
693                                       int iMinSAD,
694                                          VECTOR * const currMV,                                          VECTOR * const currMV,
695                                          const VECTOR * const pmv,                                     const int center_x,
696                                          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
697                                          const int32_t min_dy, const int32_t max_dy,                                    const int32_t min_dx,
698                                      const int32_t max_dx,
699                                      const int32_t min_dy,
700                                      const int32_t max_dy,
701                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
702                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
703                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 743  Line 707 
707          int32_t iSAD;          int32_t iSAD;
708          int32_t dx,dy;          int32_t dx,dy;
709          VECTOR backupMV;          VECTOR backupMV;
710          backupMV.x = startx;  
711          backupMV.y = starty;          backupMV.x = start_x;
712            backupMV.y = start_y;
713    
714          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
715                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
# Line 753  Line 718 
718          return iMinSAD;          return iMinSAD;
719  }  }
720    
721  int32_t Full8_MainSearch(  int32_t
722                                          const uint8_t * const pRef,  AdvDiamond16_MainSearch(const uint8_t * const pRef,
723                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
724                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
725                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
726                                          const uint8_t * const cur,                                          const uint8_t * const cur,
727                                          const int x, const int y,                                                  const int x,
728                                          int32_t startx, int32_t starty,                                                  const int y,
729                                          int32_t iMinSAD,                                             int start_x,
730                                               int start_y,
731                                               int iMinSAD,
732                                          VECTOR * const currMV,                                          VECTOR * const currMV,
733                                          const VECTOR * const pmv,                                             const int center_x,
734                                          const int32_t min_dx, const int32_t max_dx,                                             const int center_y,
735                                          const int32_t min_dy, const int32_t max_dy,                                                  const int32_t min_dx,
736                                                    const int32_t max_dx,
737                                                    const int32_t min_dy,
738                                                    const int32_t max_dy,
739                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
740                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
741                                          const int32_t iFcode,                                          const int32_t iFcode,
742                                          const int32_t iQuant,                                          const int32_t iQuant,
743                                          int iFound)                                                  int iDirection)
744  {  {
745    
746          int32_t iSAD;          int32_t iSAD;
         int32_t dx,dy;  
         VECTOR backupMV;  
         backupMV.x = startx;  
         backupMV.y = starty;  
747    
748          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
                 for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)  
                         NOCHECK_MV8_CANDIDATE(dx,dy);  
749    
750          return iMinSAD;          if (iDirection) {
751  }                  CHECK_MV16_CANDIDATE(start_x - iDiamondSize, start_y);
752                    CHECK_MV16_CANDIDATE(start_x + iDiamondSize, start_y);
753                    CHECK_MV16_CANDIDATE(start_x, start_y - iDiamondSize);
754                    CHECK_MV16_CANDIDATE(start_x, start_y + iDiamondSize);
755            } else {
756                    int bDirection = 1 + 2 + 4 + 8;
757    
758                    do {
759                            iDirection = 0;
760                            if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
761                                    CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
762    
763                            if (bDirection & 2)
764                                    CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
765    
766  int32_t Halfpel16_Refine(                          if (bDirection & 4)
767          const uint8_t * const pRef,                                  CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
         const uint8_t * const pRefH,  
         const uint8_t * const pRefV,  
         const uint8_t * const pRefHV,  
         const uint8_t * const cur,  
         const int x, const int y,  
         VECTOR * const currMV,  
         int32_t iMinSAD,  
         const VECTOR * const pmv,  
         const int32_t min_dx, const int32_t max_dx,  
         const int32_t min_dy, const int32_t max_dy,  
         const int32_t iFcode,  
         const int32_t iQuant,  
         const int32_t iEdgedWidth)  
 {  
 /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  
768    
769          int32_t iSAD;                          if (bDirection & 8)
770          VECTOR backupMV = *currMV;                                  CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
771    
772          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y-1);                          /* now we're doing diagonal checks near our candidate */
773          CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y-1);  
774          CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y-1);                          if (iDirection)         //checking if anything found
775          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y);                          {
776          CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y);                                  bDirection = iDirection;
777          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y+1);                                  iDirection = 0;
778          CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y+1);                                  start_x = currMV->x;
779          CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y+1);                                  start_y = currMV->y;
780                                    if (bDirection & 3)     //our candidate is left or right
781                                    {
782                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
783                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
784                                    } else                  // what remains here is up or down
785                                    {
786                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
787                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
788                                    }
789    
790                                    if (iDirection) {
791                                            bDirection += iDirection;
792                                            start_x = currMV->x;
793                                            start_y = currMV->y;
794                                    }
795                            } else                          //about to quit, eh? not so fast....
796                            {
797                                    switch (bDirection) {
798                                    case 2:
799                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
800                                                                                             start_y - iDiamondSize, 2 + 4);
801                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
802                                                                                             start_y + iDiamondSize, 2 + 8);
803                                            break;
804                                    case 1:
805    
806                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
807                                                                                             start_y - iDiamondSize, 1 + 4);
808                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
809                                                                                             start_y + iDiamondSize, 1 + 8);
810                                            break;
811                                    case 2 + 4:
812                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
813                                                                                             start_y - iDiamondSize, 1 + 4);
814                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
815                                                                                             start_y - iDiamondSize, 2 + 4);
816                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
817                                                                                             start_y + iDiamondSize, 2 + 8);
818                                            break;
819                                    case 4:
820                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
821                                                                                             start_y - iDiamondSize, 2 + 4);
822                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
823                                                                                             start_y - iDiamondSize, 1 + 4);
824                                            break;
825                                    case 8:
826                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
827                                                                                             start_y + iDiamondSize, 2 + 8);
828                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
829                                                                                             start_y + iDiamondSize, 1 + 8);
830                                            break;
831                                    case 1 + 4:
832                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
833                                                                                             start_y + iDiamondSize, 1 + 8);
834                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
835                                                                                             start_y - iDiamondSize, 1 + 4);
836                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
837                                                                                             start_y - iDiamondSize, 2 + 4);
838                                            break;
839                                    case 2 + 8:
840                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
841                                                                                             start_y - iDiamondSize, 1 + 4);
842                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
843                                                                                             start_y + iDiamondSize, 1 + 8);
844                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
845                                                                                             start_y + iDiamondSize, 2 + 8);
846                                            break;
847                                    case 1 + 8:
848                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
849                                                                                             start_y - iDiamondSize, 2 + 4);
850                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
851                                                                                             start_y + iDiamondSize, 2 + 8);
852                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
853                                                                                             start_y + iDiamondSize, 1 + 8);
854                                            break;
855                                    default:                //1+2+4+8 == we didn't find anything at all
856                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
857                                                                                             start_y - iDiamondSize, 1 + 4);
858                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
859                                                                                             start_y + iDiamondSize, 1 + 8);
860                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
861                                                                                             start_y - iDiamondSize, 2 + 4);
862                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
863                                                                                             start_y + iDiamondSize, 2 + 8);
864                                            break;
865                                    }
866                                    if (!iDirection)
867                                            break;          //ok, the end. really
868                                    else {
869                                            bDirection = iDirection;
870                                            start_x = currMV->x;
871                                            start_y = currMV->y;
872                                    }
873                            }
874                    }
875                    while (1);                              //forever
876            }
877          return iMinSAD;          return iMinSAD;
878  }  }
879    
880  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  #define CHECK_MV16_F_INTERPOL(X,Y) { \
881      if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
882        && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
883      { \
884        iSAD = sad16bi( cur, \
885                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
886                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
887                            iEdgedWidth); \
888        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
889        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
890        if (iSAD < iMinSAD) \
891        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); } } \
892    }
893    
894    #define CHECK_MV16_F_INTERPOL_FOUND(X,Y) { \
895      if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
896        && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
897      { \
898        iSAD = sad16bi( cur, \
899                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
900                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
901                            iEdgedWidth); \
902        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
903        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
904        if (iSAD < iMinSAD) \
905        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); iFound=0;} } \
906    }
907    
908  int32_t PMVfastSearch16(  #define CHECK_MV16_B_INTERPOL(X,Y) { \
909                                          const uint8_t * const pRef,    if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
910        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
911      { \
912        iSAD = sad16bi( cur, \
913                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
914                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
915                            iEdgedWidth); \
916        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
917        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
918        if (iSAD < iMinSAD) \
919        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); } } \
920    }
921    
922    #define CHECK_MV16_B_INTERPOL_FOUND(X,Y) { \
923      if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
924        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
925      { \
926        iSAD = sad16bi( cur, \
927                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
928                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
929                            iEdgedWidth); \
930        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
931        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
932        if (iSAD < iMinSAD) \
933        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); iFound=0;} } \
934    }
935    
936    int32_t
937    Diamond16_InterpolMainSearch(
938                                            const uint8_t * const f_pRef,
939                                             const uint8_t * const f_pRefH,
940                                             const uint8_t * const f_pRefV,
941                                             const uint8_t * const f_pRefHV,
942    
943                                             const uint8_t * const cur,
944    
945                                            const uint8_t * const b_pRef,
946                                             const uint8_t * const b_pRefH,
947                                             const uint8_t * const b_pRefV,
948                                             const uint8_t * const b_pRefHV,
949    
950                                             const int x,
951                                             const int y,
952    
953                                       const int f_start_x,
954                                       const int f_start_y,
955                                       const int b_start_x,
956                                       const int b_start_y,
957    
958                                       int iMinSAD,
959                                       VECTOR * const f_currMV,
960                                       VECTOR * const b_currMV,
961    
962                                       const int f_center_x,
963                                       const int f_center_y,
964                                       const int b_center_x,
965                                       const int b_center_y,
966    
967                                        const int32_t f_min_dx,
968                                            const int32_t f_max_dx,
969                                            const int32_t f_min_dy,
970                                            const int32_t f_max_dy,
971    
972                                        const int32_t b_min_dx,
973                                            const int32_t b_max_dx,
974                                            const int32_t b_min_dy,
975                                            const int32_t b_max_dy,
976    
977                                            const int32_t iEdgedWidth,
978                                            const int32_t iDiamondSize,
979    
980                                            const int32_t f_iFcode,
981                                            const int32_t b_iFcode,
982    
983                                            const int32_t iQuant,
984                                            int iFound)
985    {
986    /* Do a diamond search around given starting point, return SAD of best */
987    
988            int32_t iSAD;
989    
990            VECTOR f_backupMV;
991            VECTOR b_backupMV;
992    
993            f_currMV->x = f_start_x;
994            f_currMV->y = f_start_y;
995            b_currMV->x = b_start_x;
996            b_currMV->y = b_start_y;
997    
998            do
999            {
1000                    iFound = 1;
1001    
1002                    f_backupMV = *f_currMV;
1003    
1004                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x - iDiamondSize, f_backupMV.y);
1005                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x + iDiamondSize, f_backupMV.y);
1006                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y - iDiamondSize);
1007                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y + iDiamondSize);
1008    
1009                    b_backupMV = *b_currMV;
1010    
1011                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x - iDiamondSize, b_backupMV.y);
1012                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x + iDiamondSize, b_backupMV.y);
1013                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y - iDiamondSize);
1014                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y + iDiamondSize);
1015    
1016            } while (!iFound);
1017    
1018            return iMinSAD;
1019    }
1020    
1021    /* Sorry, these MACROS really got too large... I'll turn them into function soon! */
1022    
1023    #define CHECK_MV16_DIRECT_FOUND(X,Y) \
1024            if ( (X)>=(-32) && (X)<=(31) && ((Y)>=-32) && ((Y)<=31) ) \
1025            { int k;\
1026            VECTOR mvs,b_mvs;       \
1027            iSAD = 0;\
1028            for (k = 0; k < 4; k++) {       \
1029                                            mvs.x = (int32_t) ((TRB * directmv[k].x) / TRD + (X));          \
1030                        b_mvs.x = (int32_t) (((X) == 0)                                                     \
1031                                                                                    ? ((TRB - TRD) * directmv[k].x) / TRD   \
1032                                                : mvs.x - directmv[k].x);                           \
1033                                                                                                                                                                    \
1034                        mvs.y = (int32_t) ((TRB * directmv[k].y) / TRD + (Y));              \
1035                            b_mvs.y = (int32_t) (((Y) == 0)                                                         \
1036                                                                                    ? ((TRB - TRD) * directmv[k].y) / TRD   \
1037                                                : mvs.y - directmv[k].y);                           \
1038                                                                                                                                                                    \
1039      if ( (mvs.x <= max_dx) && (mvs.x >= min_dx) \
1040        && (mvs.y <= max_dy) && (mvs.y >= min_dy)  \
1041            && (b_mvs.x <= max_dx) && (b_mvs.x >= min_dx)  \
1042        && (b_mvs.y <= max_dy) && (b_mvs.y >= min_dy) ) { \
1043                iSAD += sad8bi( cur + 8*(k&1) + 8*(k>>1)*iEdgedWidth,                                                                                                       \
1044                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \
1045                                            mvs.x, mvs.y, iEdgedWidth),                                                             \
1046                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \
1047                                            b_mvs.x, b_mvs.y, iEdgedWidth),                                                         \
1048                            iEdgedWidth); \
1049                    }       \
1050            else    \
1051                    iSAD = 65535;   \
1052            } \
1053            iSAD += calc_delta_16((X),(Y), 1, iQuant);\
1054            if (iSAD < iMinSAD) \
1055                {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iFound=0; } \
1056    }
1057    
1058    
1059    
1060    int32_t
1061    Diamond16_DirectMainSearch(
1062                                            const uint8_t * const f_pRef,
1063                                            const uint8_t * const f_pRefH,
1064                                            const uint8_t * const f_pRefV,
1065                                            const uint8_t * const f_pRefHV,
1066    
1067                                            const uint8_t * const cur,
1068    
1069                                            const uint8_t * const b_pRef,
1070                                            const uint8_t * const b_pRefH,
1071                                            const uint8_t * const b_pRefV,
1072                                            const uint8_t * const b_pRefHV,
1073    
1074                                            const int x,
1075                                            const int y,
1076    
1077                                            const int TRB,
1078                                            const int TRD,
1079    
1080                                        const int start_x,
1081                                        const int start_y,
1082    
1083                                        int iMinSAD,
1084                                        VECTOR * const currMV,
1085                                            const VECTOR * const directmv,
1086    
1087                                        const int32_t min_dx,
1088                                            const int32_t max_dx,
1089                                            const int32_t min_dy,
1090                                            const int32_t max_dy,
1091    
1092                                            const int32_t iEdgedWidth,
1093                                            const int32_t iDiamondSize,
1094    
1095                                            const int32_t iQuant,
1096                                            int iFound)
1097    {
1098    /* Do a diamond search around given starting point, return SAD of best */
1099    
1100            int32_t iSAD;
1101    
1102            VECTOR backupMV;
1103    
1104            currMV->x = start_x;
1105            currMV->y = start_y;
1106    
1107    /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1108    
1109            do
1110            {
1111                    iFound = 1;
1112    
1113                    backupMV = *currMV;
1114    
1115                    CHECK_MV16_DIRECT_FOUND(backupMV.x - iDiamondSize, backupMV.y);
1116                    CHECK_MV16_DIRECT_FOUND(backupMV.x + iDiamondSize, backupMV.y);
1117                    CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y - iDiamondSize);
1118                    CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y + iDiamondSize);
1119    
1120            } while (!iFound);
1121    
1122            return iMinSAD;
1123    }
1124    
1125    
1126    int32_t
1127    AdvDiamond8_MainSearch(const uint8_t * const pRef,
1128                                               const uint8_t * const pRefH,
1129                                               const uint8_t * const pRefV,
1130                                               const uint8_t * const pRefHV,
1131                                               const uint8_t * const cur,
1132                                               const int x,
1133                                               const int y,
1134                                               int start_x,
1135                                               int start_y,
1136                                               int iMinSAD,
1137                                               VECTOR * const currMV,
1138                                               const int center_x,
1139                                               const int center_y,
1140                                               const int32_t min_dx,
1141                                               const int32_t max_dx,
1142                                               const int32_t min_dy,
1143                                               const int32_t max_dy,
1144                                               const int32_t iEdgedWidth,
1145                                               const int32_t iDiamondSize,
1146                                               const int32_t iFcode,
1147                                               const int32_t iQuant,
1148                                               int iDirection)
1149    {
1150    
1151            int32_t iSAD;
1152    
1153    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
1154    
1155            if (iDirection) {
1156                    CHECK_MV8_CANDIDATE(start_x - iDiamondSize, start_y);
1157                    CHECK_MV8_CANDIDATE(start_x + iDiamondSize, start_y);
1158                    CHECK_MV8_CANDIDATE(start_x, start_y - iDiamondSize);
1159                    CHECK_MV8_CANDIDATE(start_x, start_y + iDiamondSize);
1160            } else {
1161                    int bDirection = 1 + 2 + 4 + 8;
1162    
1163                    do {
1164                            iDirection = 0;
1165                            if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
1166                                    CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1167    
1168                            if (bDirection & 2)
1169                                    CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1170    
1171                            if (bDirection & 4)
1172                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1173    
1174                            if (bDirection & 8)
1175                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1176    
1177                            /* now we're doing diagonal checks near our candidate */
1178    
1179                            if (iDirection)         //checking if anything found
1180                            {
1181                                    bDirection = iDirection;
1182                                    iDirection = 0;
1183                                    start_x = currMV->x;
1184                                    start_y = currMV->y;
1185                                    if (bDirection & 3)     //our candidate is left or right
1186                                    {
1187                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1188                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1189                                    } else                  // what remains here is up or down
1190                                    {
1191                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1192                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1193                                    }
1194    
1195                                    if (iDirection) {
1196                                            bDirection += iDirection;
1197                                            start_x = currMV->x;
1198                                            start_y = currMV->y;
1199                                    }
1200                            } else                          //about to quit, eh? not so fast....
1201                            {
1202                                    switch (bDirection) {
1203                                    case 2:
1204                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1205                                                                                            start_y - iDiamondSize, 2 + 4);
1206                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1207                                                                                            start_y + iDiamondSize, 2 + 8);
1208                                            break;
1209                                    case 1:
1210                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1211                                                                                            start_y - iDiamondSize, 1 + 4);
1212                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1213                                                                                            start_y + iDiamondSize, 1 + 8);
1214                                            break;
1215                                    case 2 + 4:
1216                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1217                                                                                            start_y - iDiamondSize, 1 + 4);
1218                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1219                                                                                            start_y - iDiamondSize, 2 + 4);
1220                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1221                                                                                            start_y + iDiamondSize, 2 + 8);
1222                                            break;
1223                                    case 4:
1224                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1225                                                                                            start_y - iDiamondSize, 2 + 4);
1226                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1227                                                                                            start_y - iDiamondSize, 1 + 4);
1228                                            break;
1229                                    case 8:
1230                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1231                                                                                            start_y + iDiamondSize, 2 + 8);
1232                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1233                                                                                            start_y + iDiamondSize, 1 + 8);
1234                                            break;
1235                                    case 1 + 4:
1236                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1237                                                                                            start_y + iDiamondSize, 1 + 8);
1238                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1239                                                                                            start_y - iDiamondSize, 1 + 4);
1240                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1241                                                                                            start_y - iDiamondSize, 2 + 4);
1242                                            break;
1243                                    case 2 + 8:
1244                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1245                                                                                            start_y - iDiamondSize, 1 + 4);
1246                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1247                                                                                            start_y + iDiamondSize, 1 + 8);
1248                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1249                                                                                            start_y + iDiamondSize, 2 + 8);
1250                                            break;
1251                                    case 1 + 8:
1252                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1253                                                                                            start_y - iDiamondSize, 2 + 4);
1254                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1255                                                                                            start_y + iDiamondSize, 2 + 8);
1256                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1257                                                                                            start_y + iDiamondSize, 1 + 8);
1258                                            break;
1259                                    default:                //1+2+4+8 == we didn't find anything at all
1260                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1261                                                                                            start_y - iDiamondSize, 1 + 4);
1262                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1263                                                                                            start_y + iDiamondSize, 1 + 8);
1264                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1265                                                                                            start_y - iDiamondSize, 2 + 4);
1266                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1267                                                                                            start_y + iDiamondSize, 2 + 8);
1268                                            break;
1269                                    }
1270                                    if (!(iDirection))
1271                                            break;          //ok, the end. really
1272                                    else {
1273                                            bDirection = iDirection;
1274                                            start_x = currMV->x;
1275                                            start_y = currMV->y;
1276                                    }
1277                            }
1278                    }
1279                    while (1);                              //forever
1280            }
1281            return iMinSAD;
1282    }
1283    
1284    
1285    int32_t
1286    Full8_MainSearch(const uint8_t * const pRef,
1287                                     const uint8_t * const pRefH,
1288                                     const uint8_t * const pRefV,
1289                                     const uint8_t * const pRefHV,
1290                                     const uint8_t * const cur,
1291                                     const int x,
1292                                     const int y,
1293                               const int start_x,
1294                               const int start_y,
1295                               int iMinSAD,
1296                               VECTOR * const currMV,
1297                               const int center_x,
1298                               const int center_y,
1299                                     const int32_t min_dx,
1300                                     const int32_t max_dx,
1301                                     const int32_t min_dy,
1302                                     const int32_t max_dy,
1303                                     const int32_t iEdgedWidth,
1304                                     const int32_t iDiamondSize,
1305                                     const int32_t iFcode,
1306                                     const int32_t iQuant,
1307                                     int iFound)
1308    {
1309            int32_t iSAD;
1310            int32_t dx, dy;
1311            VECTOR backupMV;
1312    
1313            backupMV.x = start_x;
1314            backupMV.y = start_y;
1315    
1316            for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
1317                    for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
1318                            NOCHECK_MV8_CANDIDATE(dx, dy);
1319    
1320            return iMinSAD;
1321    }
1322    
1323    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1324    
1325    int32_t
1326    Halfpel16_Refine(const uint8_t * const pRef,
1327                                     const uint8_t * const pRefH,
1328                                     const uint8_t * const pRefV,
1329                                     const uint8_t * const pRefHV,
1330                                     const uint8_t * const cur,
1331                                     const int x,
1332                                     const int y,
1333                                     VECTOR * const currMV,
1334                                     int32_t iMinSAD,
1335                               const int center_x,
1336                               const int center_y,
1337                                     const int32_t min_dx,
1338                                     const int32_t max_dx,
1339                                     const int32_t min_dy,
1340                                     const int32_t max_dy,
1341                                     const int32_t iFcode,
1342                                     const int32_t iQuant,
1343                                     const int32_t iEdgedWidth)
1344    {
1345    /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
1346    
1347            int32_t iSAD;
1348            VECTOR backupMV = *currMV;
1349    
1350            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y - 1);
1351            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y - 1);
1352            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y - 1);
1353            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y);
1354            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y);
1355            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y + 1);
1356            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y + 1);
1357            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y + 1);
1358    
1359            return iMinSAD;
1360    }
1361    
1362    #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1363    
1364    
1365    
1366    int32_t
1367    PMVfastSearch16(const uint8_t * const pRef,
1368                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1369                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1370                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1371                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1372                                          const int x, const int y,                                  const int x,
1373                                    const int y,
1374                                    const int start_x,      /* start is searched first, so it should contain the most */
1375                                    const int start_y,  /* likely motion vector for this block */
1376                                    const int center_x,     /* center is from where length of MVs is measured */
1377                                    const int center_y,
1378                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1379                                          const uint32_t iQuant,                                          const uint32_t iQuant,
1380                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 861  Line 1406 
1406          VECTOR pmv[4];          VECTOR pmv[4];
1407          int32_t psad[4];          int32_t psad[4];
1408    
1409          const MACROBLOCK * const pMB = pMBs + x + y * iWcount;          MainSearch16FuncPtr MainSearchPtr;
1410    
1411          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1412    
1413          static int32_t threshA,threshB;          int32_t threshA, threshB;
1414          int32_t bPredEq;          int32_t bPredEq;
1415          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1416    
1417  /* Get maximum range */  /* Get maximum range */
1418          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
1419                    x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
1420    
1421  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1422    
1423          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
1424          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1425          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1426          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1427          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1428          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
   
1429    
1430          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1431            //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1432            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1433    
1434          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1435                  threshA =  512;                  threshA =  512;
1436                  threshB = 1024;                  threshB = 1024;
1437            } else {
         }  
         else  
         {  
1438                  threshA = psad[0];                  threshA = psad[0];
1439                  threshB = threshA+256;                  threshB = threshA+256;
1440                  if (threshA< 512) threshA =  512;                  if (threshA < 512)
1441                  if (threshA>1024) threshA = 1024;                          threshA = 512;
1442                  if (threshB>1792) threshB = 1792;                  if (threshA > 1024)
1443                            threshA = 1024;
1444                    if (threshB > 1792)
1445                            threshB = 1792;
1446          }          }
1447    
1448          iFound=0;          iFound=0;
# Line 908  Line 1454 
1454     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
1455  */  */
1456    
1457          *currMV=pmv[0];         /* current best := prediction */          currMV->x = start_x;
1458          if (!(MotionFlags & PMV_HALFPEL16 ))          currMV->y = start_y;
1459          {       /* This should NOT be necessary! */  
1460            if (!(MotionFlags & PMV_HALFPEL16)) {   /* This should NOT be necessary! */
1461                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1462                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
1463          }          }
1464    
1465          if (currMV->x > max_dx)          if (currMV->x > max_dx) {
         {  
1466                  currMV->x=max_dx;                  currMV->x=max_dx;
1467          }          }
1468          if (currMV->x < min_dx)          if (currMV->x < min_dx) {
         {  
1469                  currMV->x=min_dx;                  currMV->x=min_dx;
1470          }          }
1471          if (currMV->y > max_dy)          if (currMV->y > max_dy) {
         {  
1472                  currMV->y=max_dy;                  currMV->y=max_dy;
1473          }          }
1474          if (currMV->y < min_dy)          if (currMV->y < min_dy) {
         {  
1475                  currMV->y=min_dy;                  currMV->y=min_dy;
1476          }          }
1477    
1478          iMinSAD = sad16( cur,          iMinSAD =
1479                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1480                           iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1481          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1482            iMinSAD +=
1483          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
1484          {                                            (uint8_t) iFcode, iQuant);
1485    
1486            if ((iMinSAD < 256) ||
1487                    ((MVequal(*currMV, prevMB->mvs[0])) &&
1488                     ((int32_t) iMinSAD < prevMB->sad16))) {
1489                  if (iMinSAD < 2*iQuant) // high chances for SKIP-mode                  if (iMinSAD < 2*iQuant) // high chances for SKIP-mode
1490                  {                  {
1491                          if (!MVzero(*currMV))                          if (!MVzero(*currMV)) {
                         {  
1492                                  iMinSAD += MV16_00_BIAS;                                  iMinSAD += MV16_00_BIAS;
1493                                  CHECK_MV16_ZERO;                // (0,0) saves space for letterboxed pictures                                  CHECK_MV16_ZERO;                // (0,0) saves space for letterboxed pictures
1494                                  iMinSAD -= MV16_00_BIAS;                                  iMinSAD -= MV16_00_BIAS;
# Line 998  Line 1544 
1544    
1545          if (!MVzero(pmv[1]))          if (!MVzero(pmv[1]))
1546          if (!MVequal(pmv[1],prevMB->mvs[0]))          if (!MVequal(pmv[1],prevMB->mvs[0]))
1547          if (!MVequal(pmv[1],pmv[0]))                          if (!MVequal(pmv[1], pmv[0])) {
1548          {                                  if (!(MotionFlags & PMV_HALFPEL16)) {
1549                  if (!(MotionFlags & PMV_HALFPEL16 ))                                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
1550                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
1551                  }                  }
1552    
1553                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1554          }          }
   
1555  // top neighbour, if allowed  // top neighbour, if allowed
1556          if (!MVzero(pmv[2]))          if (!MVzero(pmv[2]))
1557          if (!MVequal(pmv[2],prevMB->mvs[0]))          if (!MVequal(pmv[2],prevMB->mvs[0]))
1558          if (!MVequal(pmv[2],pmv[0]))          if (!MVequal(pmv[2],pmv[0]))
1559          if (!MVequal(pmv[2],pmv[1]))                                  if (!MVequal(pmv[2], pmv[1])) {
1560          {                                          if (!(MotionFlags & PMV_HALFPEL16)) {
1561                  if (!(MotionFlags & PMV_HALFPEL16 ))                                                  pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
1562                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
1563                  }                  }
1564                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
# Line 1025  Line 1568 
1568                  if (!MVequal(pmv[3],prevMB->mvs[0]))                  if (!MVequal(pmv[3],prevMB->mvs[0]))
1569                  if (!MVequal(pmv[3],pmv[0]))                  if (!MVequal(pmv[3],pmv[0]))
1570                  if (!MVequal(pmv[3],pmv[1]))                  if (!MVequal(pmv[3],pmv[1]))
1571                  if (!MVequal(pmv[3],pmv[2]))                                                                          if (!MVequal(pmv[3], pmv[2])) {
1572                  {                                                                                  if (!(MotionFlags & PMV_HALFPEL16)) {
1573                          if (!(MotionFlags & PMV_HALFPEL16 ))                                                                                          pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
1574                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
1575                          }                          }
1576                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                  CHECK_MV16_CANDIDATE(pmv[3].x,
1577                                                                                                                             pmv[3].y);
1578                  }                  }
1579          }          }
1580    
1581          if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96)*/ )          if ((MVzero(*currMV)) &&
1582                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1583                  iMinSAD -= MV16_00_BIAS;                  iMinSAD -= MV16_00_BIAS;
1584    
1585    
# Line 1043  Line 1587 
1587     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
1588  */  */
1589    
1590          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ((iMinSAD <= threshA) ||
1591          {                  (MVequal(*currMV, prevMB->mvs[0]) &&
1592                     ((int32_t) iMinSAD < prevMB->sad16))) {
1593                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1594                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
1595                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1062  Line 1607 
1607     Refine by using small diamond and goto step 10.     Refine by using small diamond and goto step 10.
1608  */  */
1609    
1610            if (MotionFlags & PMV_USESQUARES16)
1611                    MainSearchPtr = Square16_MainSearch;
1612            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
1613                    MainSearchPtr = AdvDiamond16_MainSearch;
1614            else
1615                    MainSearchPtr = Diamond16_MainSearch;
1616    
1617          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1618    
1619    
1620  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1621          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1622                                            x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1623                                            currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->x, currMV->y, iMinSAD, &newMV, center_x, center_y,
1624                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dx, max_dx,
1625                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1626                                                      iQuant, iFound);
1627    
1628          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1629                  *currMV = newMV;                  *currMV = newMV;
1630                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1631          }          }
1632    
1633          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
1634  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1635    
1636                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1637                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1638                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1639                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    center_x, center_y, iMinSAD, &newMV, center_x, center_y,
1640                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1641                                                                      iDiamondSize, iFcode, iQuant, iFound);
1642    
1643                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1644                          *currMV = newMV;                          *currMV = newMV;
1645                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1646                  }                  }
1647                  }                  }
1648    
1649                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1650                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1651                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1652                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y,
1653                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy,
1654                                                                      iEdgedWidth, iDiamondSize, iFcode,
1655                                                                      iQuant, iFound);
1656    
1657                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1658                          *currMV = newMV;                          *currMV = newMV;
1659                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1660                  }                  }
# Line 1113  Line 1667 
1667    
1668  PMVfast16_Terminate_with_Refine:  PMVfast16_Terminate_with_Refine:
1669          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1670                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1671                                    x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1672                                    currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1673                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1674    
1675  PMVfast16_Terminate_without_Refine:  PMVfast16_Terminate_without_Refine:
1676          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
1677          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
1678          return iMinSAD;          return iMinSAD;
1679  }  }
1680    
# Line 1129  Line 1683 
1683    
1684    
1685    
1686  int32_t Diamond8_MainSearch(  int32_t
1687          const uint8_t * const pRef,  Diamond8_MainSearch(const uint8_t * const pRef,
1688          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1689          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1690          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1691          const uint8_t * const cur,          const uint8_t * const cur,
1692          const int x, const int y,                                          const int x,
1693          int32_t startx, int32_t starty,                                          const int y,
1694                                            int32_t start_x,
1695                                            int32_t start_y,
1696          int32_t iMinSAD,          int32_t iMinSAD,
1697          VECTOR * const currMV,          VECTOR * const currMV,
1698          const VECTOR * const pmv,                                     const int center_x,
1699          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
1700          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
1701                                            const int32_t max_dx,
1702                                            const int32_t min_dy,
1703                                            const int32_t max_dy,
1704          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
1705          const int32_t iDiamondSize,          const int32_t iDiamondSize,
1706          const int32_t iFcode,          const int32_t iFcode,
# Line 1151  Line 1710 
1710  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
1711    
1712          int32_t iDirection=0;          int32_t iDirection=0;
1713            int32_t iDirectionBackup;
1714          int32_t iSAD;          int32_t iSAD;
1715          VECTOR backupMV;          VECTOR backupMV;
1716          backupMV.x = startx;  
1717          backupMV.y = starty;          backupMV.x = start_x;
1718            backupMV.y = start_y;
1719    
1720  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1721    
# Line 1163  Line 1724 
1724          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
1725          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1726    
1727          if (iDirection)          if (iDirection) {
1728                  while (!iFound)                  while (!iFound) {
                 {  
1729                          iFound = 1;                          iFound = 1;
1730                          backupMV=*currMV;       // since iDirection!=0, this is well defined!                          backupMV=*currMV;       // since iDirection!=0, this is well defined!
1731                            iDirectionBackup = iDirection;
1732    
1733                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
1734                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1735                          if ( iDirection != 1)                                                                                    backupMV.y, 1);
1736                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
1737                          if ( iDirection != 4)                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1738                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                    backupMV.y, 2);
1739                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
1740                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1741                  }                                                                                    backupMV.y - iDiamondSize, 3);
1742          else                          if (iDirectionBackup != 3)
1743          {                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1744                  currMV->x = startx;                                                                                    backupMV.y + iDiamondSize, 4);
1745                  currMV->y = starty;                  }
1746            } else {
1747                    currMV->x = start_x;
1748                    currMV->y = start_y;
1749          }          }
1750          return iMinSAD;          return iMinSAD;
1751  }  }
1752    
1753  int32_t Halfpel8_Refine(  
1754          const uint8_t * const pRef,  
1755    
1756    int32_t
1757    Square8_MainSearch(const uint8_t * const pRef,
1758          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1759          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1760          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1761          const uint8_t * const cur,          const uint8_t * const cur,
1762          const int x, const int y,                                          const int x,
1763          VECTOR * const currMV,                                          const int y,
1764                                            int32_t start_x,
1765                                            int32_t start_y,
1766          int32_t iMinSAD,          int32_t iMinSAD,
1767          const VECTOR * const pmv,                                          VECTOR * const currMV,
1768          const int32_t min_dx, const int32_t max_dx,                                     const int center_x,
1769          const int32_t min_dy, const int32_t max_dy,                                     const int center_y,
1770                                            const int32_t min_dx,
1771                                            const int32_t max_dx,
1772                                            const int32_t min_dy,
1773                                            const int32_t max_dy,
1774                                            const int32_t iEdgedWidth,
1775                                            const int32_t iDiamondSize,
1776          const int32_t iFcode,          const int32_t iFcode,
1777          const int32_t iQuant,          const int32_t iQuant,
1778          const int32_t iEdgedWidth)                                          int iFound)
1779  {  {
1780  /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  /* Do a square search around given starting point, return SAD of best */
1781    
1782            int32_t iDirection = 0;
1783          int32_t iSAD;          int32_t iSAD;
1784          VECTOR backupMV = *currMV;          VECTOR backupMV;
1785    
1786          CHECK_MV8_CANDIDATE(backupMV.x-1,backupMV.y-1);          backupMV.x = start_x;
1787          CHECK_MV8_CANDIDATE(backupMV.x  ,backupMV.y-1);          backupMV.y = start_y;
         CHECK_MV8_CANDIDATE(backupMV.x+1,backupMV.y-1);  
         CHECK_MV8_CANDIDATE(backupMV.x-1,backupMV.y);  
         CHECK_MV8_CANDIDATE(backupMV.x+1,backupMV.y);  
         CHECK_MV8_CANDIDATE(backupMV.x-1,backupMV.y+1);  
         CHECK_MV8_CANDIDATE(backupMV.x  ,backupMV.y+1);  
         CHECK_MV8_CANDIDATE(backupMV.x+1,backupMV.y+1);  
1788    
1789          return iMinSAD;  /* It's one search with full square pattern, and new parts for all following diamonds */
1790    
1791    /*   new direction are extra, so 1-4 is normal diamond
1792          537
1793          1*2
1794          648
1795    */
1796    
1797            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1798            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1799            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1800            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1801    
1802            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1803                                                             backupMV.y - iDiamondSize, 5);
1804            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1805                                                             backupMV.y + iDiamondSize, 6);
1806            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1807                                                             backupMV.y - iDiamondSize, 7);
1808            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1809                                                             backupMV.y + iDiamondSize, 8);
1810    
1811    
1812            if (iDirection) {
1813                    while (!iFound) {
1814                            iFound = 1;
1815                            backupMV = *currMV;
1816    
1817                            switch (iDirection) {
1818                            case 1:
1819                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1820                                                                                       backupMV.y, 1);
1821                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1822                                                                                     backupMV.y - iDiamondSize, 5);
1823                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1824                                                                                     backupMV.y - iDiamondSize, 7);
1825                                    break;
1826                            case 2:
1827                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1828                                                                                     2);
1829                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1830                                                                                     backupMV.y + iDiamondSize, 6);
1831                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1832                                                                                     backupMV.y + iDiamondSize, 8);
1833                                    break;
1834    
1835                            case 3:
1836                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1837                                                                                     4);
1838                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1839                                                                                     backupMV.y - iDiamondSize, 7);
1840                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1841                                                                                     backupMV.y + iDiamondSize, 8);
1842                                    break;
1843    
1844                            case 4:
1845                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1846                                                                                     3);
1847                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1848                                                                                     backupMV.y - iDiamondSize, 5);
1849                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1850                                                                                     backupMV.y + iDiamondSize, 6);
1851                                    break;
1852    
1853                            case 5:
1854                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1855                                                                                     1);
1856                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1857                                                                                     3);
1858                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1859                                                                                     backupMV.y - iDiamondSize, 5);
1860                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1861                                                                                     backupMV.y + iDiamondSize, 6);
1862                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1863                                                                                     backupMV.y - iDiamondSize, 7);
1864                                    break;
1865    
1866                            case 6:
1867                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1868                                                                                     2);
1869                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1870                                                                                     3);
1871    
1872                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1873                                                                                     backupMV.y - iDiamondSize, 5);
1874                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1875                                                                                     backupMV.y + iDiamondSize, 6);
1876                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1877                                                                                     backupMV.y + iDiamondSize, 8);
1878    
1879                                    break;
1880    
1881                            case 7:
1882                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1883                                                                                       backupMV.y, 1);
1884                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1885                                                                                     4);
1886                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1887                                                                                     backupMV.y - iDiamondSize, 5);
1888                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1889                                                                                     backupMV.y - iDiamondSize, 7);
1890                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1891                                                                                     backupMV.y + iDiamondSize, 8);
1892                                    break;
1893    
1894                            case 8:
1895                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1896                                                                                     2);
1897                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1898                                                                                     4);
1899                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1900                                                                                     backupMV.y + iDiamondSize, 6);
1901                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1902                                                                                     backupMV.y - iDiamondSize, 7);
1903                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1904                                                                                     backupMV.y + iDiamondSize, 8);
1905                                    break;
1906                            default:
1907                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1908                                                                                     1);
1909                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1910                                                                                     2);
1911                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1912                                                                                     3);
1913                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1914                                                                                     4);
1915    
1916                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1917                                                                                     backupMV.y - iDiamondSize, 5);
1918                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1919                                                                                     backupMV.y + iDiamondSize, 6);
1920                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1921                                                                                     backupMV.y - iDiamondSize, 7);
1922                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1923                                                                                     backupMV.y + iDiamondSize, 8);
1924                                    break;
1925                            }
1926                    }
1927            } else {
1928                    currMV->x = start_x;
1929                    currMV->y = start_y;
1930            }
1931            return iMinSAD;
1932    }
1933    
1934    
1935    
1936    
1937    
1938    int32_t
1939    Halfpel8_Refine_c(const uint8_t * const pRef,
1940                                    const uint8_t * const pRefH,
1941                                    const uint8_t * const pRefV,
1942                                    const uint8_t * const pRefHV,
1943                                    const uint8_t * const cur,
1944                                    const int x,
1945                                    const int y,
1946                                    VECTOR * const currMV,
1947                                    int32_t iMinSAD,
1948                               const int center_x,
1949                               const int center_y,
1950                                    const int32_t min_dx,
1951                                    const int32_t max_dx,
1952                                    const int32_t min_dy,
1953                                    const int32_t max_dy,
1954                                    const int32_t iFcode,
1955                                    const int32_t iQuant,
1956                                    const int32_t iEdgedWidth)
1957    {
1958    /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
1959    
1960            int32_t iSAD;
1961            VECTOR backupMV = *currMV;
1962    
1963            CHECK_MV8_CANDIDATE(backupMV.x - 1, backupMV.y - 1);
1964            CHECK_MV8_CANDIDATE(backupMV.x, backupMV.y - 1);
1965            CHECK_MV8_CANDIDATE(backupMV.x + 1, backupMV.y - 1);
1966            CHECK_MV8_CANDIDATE(backupMV.x - 1, backupMV.y);
1967            CHECK_MV8_CANDIDATE(backupMV.x + 1, backupMV.y);
1968            CHECK_MV8_CANDIDATE(backupMV.x - 1, backupMV.y + 1);
1969            CHECK_MV8_CANDIDATE(backupMV.x, backupMV.y + 1);
1970            CHECK_MV8_CANDIDATE(backupMV.x + 1, backupMV.y + 1);
1971    
1972            return iMinSAD;
1973  }  }
1974    
1975    
1976  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1977    
1978  int32_t PMVfastSearch8(  int32_t
1979                                          const uint8_t * const pRef,  PMVfastSearch8(const uint8_t * const pRef,
1980                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1981                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1982                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1983                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1984                                          const int x, const int y,                             const int x,
1985                                          const int start_x, const int start_y,                             const int y,
1986                               const int start_x,
1987                               const int start_y,
1988                                    const int center_x,
1989                                    const int center_y,
1990                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1991                                          const uint32_t iQuant,                                          const uint32_t iQuant,
1992                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1259  Line 2016 
2016          VECTOR backupMV;          VECTOR backupMV;
2017          VECTOR startMV;          VECTOR startMV;
2018    
2019          const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2020          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
2021    
2022          static int32_t threshA,threshB;           int32_t threshA, threshB;
2023          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
2024          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
2025    
2026          int32_t iSubBlock = (y&1)+(y&1) + (x&1);          int32_t iSubBlock = (y&1)+(y&1) + (x&1);
2027    
2028            MainSearch8FuncPtr MainSearchPtr;
2029    
2030          /* Init variables */          /* Init variables */
2031          startMV.x = start_x;          startMV.x = start_x;
2032          startMV.y = start_y;          startMV.y = start_y;
2033    
2034          /* Get maximum range */          /* Get maximum range */
2035          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2036                    x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2037    
2038          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
2039          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2040            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2041            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2042            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2043          }               /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          }
   
2044    
2045          bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
2046            //bPredEq = get_pmvdata(pMBs, (x >> 1), (y >> 1), iWcount, iSubBlock, pmv, psad);
2047            bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
2048    
2049          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
2050                  threshA =  512/4;                  threshA =  512/4;
2051                  threshB = 1024/4;                  threshB = 1024/4;
2052    
2053          }          } else {
2054          else                  threshA = psad[0] / 4;  /* good estimate? */
         {  
                 threshA = psad[0]/4;                    /* good estimate */  
2055                  threshB = threshA+256/4;                  threshB = threshA+256/4;
2056                  if (threshA< 512/4) threshA =  512/4;                  if (threshA < 512 / 4)
2057                  if (threshA>1024/4) threshA = 1024/4;                          threshA = 512 / 4;
2058                  if (threshB>1792/4) threshB = 1792/4;                  if (threshA > 1024 / 4)
2059                            threshA = 1024 / 4;
2060                    if (threshB > 1792 / 4)
2061                            threshB = 1792 / 4;
2062          }          }
2063    
2064          iFound=0;          iFound=0;
# Line 1313  Line 2073 
2073    
2074  // Prepare for main loop  // Prepare for main loop
2075    
2076      if (MotionFlags & PMV_USESQUARES8)
2077          MainSearchPtr = Square8_MainSearch;
2078      else
2079    
2080            if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2081                    MainSearchPtr = AdvDiamond8_MainSearch;
2082            else
2083                    MainSearchPtr = Diamond8_MainSearch;
2084    
2085    
2086          *currMV = startMV;          *currMV = startMV;
2087    
2088          iMinSAD = sad8( cur,          iMinSAD =
2089                          get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  sad8(cur,
2090                          iEdgedWidth);                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2091          iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode, iQuant);                                                  iEdgedWidth), iEdgedWidth);
2092            iMinSAD +=
2093                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2094                                             (uint8_t) iFcode, iQuant);
2095    
2096          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock]))          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock]))
2097                                  && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )                                                                  && ((int32_t) iMinSAD <
2098          {                                                                          prevMB->sad8[iSubBlock]))) {
2099                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2100                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2101                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1360  Line 2133 
2133  // the median prediction might be even better than mv16  // the median prediction might be even better than mv16
2134    
2135          if (!MVequal(pmv[0],startMV))          if (!MVequal(pmv[0],startMV))
2136                  CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);                  CHECK_MV8_CANDIDATE(center_x, center_y);
2137    
2138  // (0,0) if needed  // (0,0) if needed
2139          if (!MVzero(pmv[0]))          if (!MVzero(pmv[0]))
# Line 1371  Line 2144 
2144          if (!MVzero(prevMB->mvs[iSubBlock]))          if (!MVzero(prevMB->mvs[iSubBlock]))
2145          if (!MVequal(prevMB->mvs[iSubBlock],startMV))          if (!MVequal(prevMB->mvs[iSubBlock],startMV))
2146          if (!MVequal(prevMB->mvs[iSubBlock],pmv[0]))          if (!MVequal(prevMB->mvs[iSubBlock],pmv[0]))
2147          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);                                  CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,
2148                                                                            prevMB->mvs[iSubBlock].y);
2149    
2150          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
2151          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2152                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2153                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2154                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2155                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
2156                          goto PMVfast8_Terminate_with_Refine;                          goto PMVfast8_Terminate_with_Refine;
2157          }          }
2158    
   
2159  // left neighbour, if allowed and needed  // left neighbour, if allowed and needed
2160          if (!MVzero(pmv[1]))          if (!MVzero(pmv[1]))
2161          if (!MVequal(pmv[1],startMV))          if (!MVequal(pmv[1],startMV))
2162          if (!MVequal(pmv[1],prevMB->mvs[iSubBlock]))          if (!MVequal(pmv[1],prevMB->mvs[iSubBlock]))
2163          if (!MVequal(pmv[1],pmv[0]))                                  if (!MVequal(pmv[1], pmv[0])) {
2164          {                                          if (!(MotionFlags & PMV_HALFPEL8)) {
2165                  if (!(MotionFlags & PMV_HALFPEL8 ))                                                  pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2166                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2167                  }                  }
2168                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
2169          }          }
   
2170  // top neighbour, if allowed and needed  // top neighbour, if allowed and needed
2171          if (!MVzero(pmv[2]))          if (!MVzero(pmv[2]))
2172          if (!MVequal(pmv[2],startMV))          if (!MVequal(pmv[2],startMV))
2173          if (!MVequal(pmv[2],prevMB->mvs[iSubBlock]))          if (!MVequal(pmv[2],prevMB->mvs[iSubBlock]))
2174          if (!MVequal(pmv[2],pmv[0]))          if (!MVequal(pmv[2],pmv[0]))
2175          if (!MVequal(pmv[2],pmv[1]))                                          if (!MVequal(pmv[2], pmv[1])) {
2176          {                                                  if (!(MotionFlags & PMV_HALFPEL8)) {
2177                  if (!(MotionFlags & PMV_HALFPEL8 ))                                                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2178                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2179                  }                  }
2180                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
# Line 1414  Line 2185 
2185          if (!MVequal(pmv[3],prevMB->mvs[iSubBlock]))          if (!MVequal(pmv[3],prevMB->mvs[iSubBlock]))
2186          if (!MVequal(pmv[3],pmv[0]))          if (!MVequal(pmv[3],pmv[0]))
2187          if (!MVequal(pmv[3],pmv[1]))          if (!MVequal(pmv[3],pmv[1]))
2188          if (!MVequal(pmv[3],pmv[2]))                                                                                          if (!MVequal(pmv[3], pmv[2])) {
2189                  {                                                                                                  if (!
2190                          if (!(MotionFlags & PMV_HALFPEL8 ))                                                                                                          (MotionFlags &
2191                          {       pmv[3].x = EVEN(pmv[3].x);                                                                                                           PMV_HALFPEL8)) {
2192                                                                                                            pmv[3].x = EVEN(pmv[3].x);
2193                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2194                          }                          }
2195                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                                  CHECK_MV8_CANDIDATE(pmv[3].x,
2196                                                                                                                                            pmv[3].y);
2197                  }                  }
2198          }          }
2199    
2200          if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )          if ((MVzero(*currMV)) &&
2201                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2202                  iMinSAD -= MV8_00_BIAS;                  iMinSAD -= MV8_00_BIAS;
2203    
2204    
# Line 1432  Line 2206 
2206     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
2207  */  */
2208    
2209          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
2210          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2211                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2212                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2213                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2214                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1453  Line 2228 
2228          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2229    
2230  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2231          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2232                                           x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2233                                           currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2234                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2235                                                      iQuant, iFound);
2236    
2237          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2238                  *currMV = newMV;                  *currMV = newMV;
2239                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2240          }          }
2241    
2242          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2243  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
2244    
2245                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2246                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2247                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2248                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2249                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2250                                                                      iDiamondSize, iFcode, iQuant, iFound);
2251    
2252                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2253                          *currMV = newMV;                          *currMV = newMV;
2254                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2255                  }                  }
2256                  }                  }
2257    
2258                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2259                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2260                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2261                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2262                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2263                                                                      iQuant, iFound);
2264    
2265                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2266                          *currMV = newMV;                          *currMV = newMV;
2267                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2268                  }                  }
# Line 1501  Line 2275 
2275    
2276  PMVfast8_Terminate_with_Refine:  PMVfast8_Terminate_with_Refine:
2277          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2278                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2279                                                   x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2280                                                   currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2281                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2282    
2283    
2284  PMVfast8_Terminate_without_Refine:  PMVfast8_Terminate_without_Refine:
2285          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2286          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2287    
2288          return iMinSAD;          return iMinSAD;
2289  }  }
2290    
2291  int32_t EPZSSearch16(  int32_t
2292                                          const uint8_t * const pRef,  EPZSSearch16(const uint8_t * const pRef,
2293                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2294                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2295                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2296                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2297                                          const int x, const int y,                           const int x,
2298                             const int y,
2299                            const int start_x,
2300                            const int start_y,
2301                            const int center_x,
2302                            const int center_y,
2303                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2304                                          const uint32_t iQuant,                                          const uint32_t iQuant,
2305                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1551  Line 2330 
2330          int32_t psad[8];          int32_t psad[8];
2331    
2332          static MACROBLOCK * oldMBs = NULL;          static MACROBLOCK * oldMBs = NULL;
2333          const MACROBLOCK * const pMB = pMBs + x + y * iWcount;  
2334    //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
2335          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
2336          MACROBLOCK * oldMB = NULL;          MACROBLOCK * oldMB = NULL;
2337    
2338          static int32_t thresh2;           int32_t thresh2;
2339          int32_t bPredEq;          int32_t bPredEq;
2340          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2341    
2342          MainSearch16FuncPtr EPZSMainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
2343    
2344          if (oldMBs == NULL)          if (oldMBs == NULL) {
2345          {       oldMBs = (MACROBLOCK*) calloc(iWcount*iHcount,sizeof(MACROBLOCK));                  oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
2346  //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));  //              fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
2347          }          }
2348          oldMB = oldMBs + x + y * iWcount;          oldMB = oldMBs + x + y * iWcount;
2349    
2350  /* Get maximum range */  /* Get maximum range */
2351          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2352                          x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
2353    
2354          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
2355          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2356            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2357            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2358            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2359          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2360            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2361          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
2362            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2363    
2364  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2365          MinSAD=SAD          MinSAD=SAD
# Line 1589  Line 2370 
2370    
2371  // Prepare for main loop  // Prepare for main loop
2372    
2373          *currMV=pmv[0];         /* current best := median prediction */          currMV->x = start_x;
2374          if (!(MotionFlags & PMV_HALFPEL16))          currMV->y = start_y;
2375          {  
2376            if (!(MotionFlags & PMV_HALFPEL16)) {
2377                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2378                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2379          }          }
# Line 1607  Line 2389 
2389    
2390  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2391    
2392          iMinSAD = sad16( cur,          iMinSAD =
2393                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
2394                  iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2395          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2396            iMinSAD +=
2397                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2398                                              (uint8_t) iFcode, iQuant);
2399    
2400  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2401          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV, prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ((iMinSAD < 256) ||
2402                  {                  ((MVequal(*currMV, prevMB->mvs[0])) &&
2403                     ((int32_t) iMinSAD < prevMB->sad16))) {
2404                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2405                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2406                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1629  Line 2415 
2415  // set threshhold based on Min of Prediction and SAD of collocated block  // set threshhold based on Min of Prediction and SAD of collocated block
2416  // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want  // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
2417    
2418          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
2419                  thresh2 =  512;                  thresh2 =  512;
2420          }          } else {
         else  
         {  
2421  /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */  /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */
2422    
2423                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
# Line 1646  Line 2429 
2429    
2430    
2431  // left neighbour, if allowed  // left neighbour, if allowed
2432          if (x != 0)          if (x != 0) {
2433          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2434                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2435                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2436                  }                  }
2437                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
2438          }          }
   
2439  // top neighbour, if allowed  // top neighbour, if allowed
2440          if (y != 0)          if (y != 0) {
2441          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2442                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2443                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2444                  }                  }
2445                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
2446    
2447  // top right neighbour, if allowed  // top right neighbour, if allowed
2448                  if ((uint32_t)x != (iWcount-1))                  if ((uint32_t) x != (iWcount - 1)) {
2449                  {                          if (!(MotionFlags & PMV_HALFPEL16)) {
2450                          if (!(MotionFlags & PMV_HALFPEL16 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2451                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2452                          }                          }
2453                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
# Line 1680  Line 2459 
2459  */  */
2460    
2461          if ( (iMinSAD <= thresh2)          if ( (iMinSAD <= thresh2)
2462                  || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )                  || (MVequal(*currMV, prevMB->mvs[0]) &&
2463                  {                          ((int32_t) iMinSAD <= prevMB->sad16))) {
2464                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2465                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2466                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1702  Line 2481 
2481    
2482  // top neighbour  // top neighbour
2483          if (y != 0)          if (y != 0)
2484                  CHECK_MV16_CANDIDATE((prevMB-iWcount)->mvs[0].x,(prevMB-iWcount)->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,
2485                                                             (prevMB - iWcount)->mvs[0].y);
2486    
2487  // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs  // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
2488    
# Line 1711  Line 2491 
2491    
2492  // bottom neighbour, dito  // bottom neighbour, dito
2493          if ((uint32_t)y != iHcount-1)          if ((uint32_t)y != iHcount-1)
2494                  CHECK_MV16_CANDIDATE((prevMB+iWcount)->mvs[0].x,(prevMB+iWcount)->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,
2495                                                             (prevMB + iWcount)->mvs[0].y);
2496    
2497  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
2498          if (iMinSAD <= thresh2)          if (iMinSAD <= thresh2) {
                 {  
2499                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2500                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2501                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1726  Line 2506 
2506    
2507          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2508    
 /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  
   
2509          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
2510                  EPZSMainSearchPtr = Square16_MainSearch;                  MainSearchPtr = Square16_MainSearch;
2511          else          else
2512                  EPZSMainSearchPtr = Diamond16_MainSearch;           if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2513                    MainSearchPtr = AdvDiamond16_MainSearch;
2514            else
2515                    MainSearchPtr = Diamond16_MainSearch;
2516    
2517          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);  
2518    
2519          if (iSAD < iMinSAD)          iSAD =
2520          {                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2521                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2522                                                      min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2523    
2524            if (iSAD < iMinSAD) {
2525                  *currMV = newMV;                  *currMV = newMV;
2526                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2527          }          }
2528    
2529    
2530          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
2531  /* 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) */
2532    
2533                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2534                  {                          iSAD =
2535                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2536                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2537                                  pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2538                                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    2, iFcode, iQuant, 0);
2539                  }                  }
2540    
2541                  if (iSAD < iMinSAD)                  if (iSAD < iMinSAD) {
                 {  
2542                          *currMV = newMV;                          *currMV = newMV;
2543                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2544                  }                  }
2545    
2546                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2547                  {                          iSAD =
2548                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2549                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2550                          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);  
2551    
2552                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2553                                  *currMV = newMV;                                  *currMV = newMV;
2554                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2555                          }                          }
# Line 1782  Line 2560 
2560    
2561  EPZS16_Terminate_with_Refine:  EPZS16_Terminate_with_Refine:
2562          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
2563                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2564                                  x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2565                                  currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2566                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
2567    
2568  EPZS16_Terminate_without_Refine:  EPZS16_Terminate_without_Refine:
2569    
2570          *oldMB = *prevMB;          *oldMB = *prevMB;
2571    
2572          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2573          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2574          return iMinSAD;          return iMinSAD;
2575  }  }
2576    
2577    
2578  int32_t EPZSSearch8(  int32_t
2579                                          const uint8_t * const pRef,  EPZSSearch8(const uint8_t * const pRef,
2580                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2581                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2582                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2583                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2584                                          const int x, const int y,                          const int x,
2585                                          const int start_x, const int start_y,                          const int y,
2586                            const int start_x,
2587                            const int start_y,
2588                            const int center_x,
2589                            const int center_y,
2590                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2591                                          const uint32_t iQuant,                                          const uint32_t iQuant,
2592                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1838  Line 2620 
2620    
2621          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);
2622    
2623          const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2624          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
2625    
2626          int32_t bPredEq;          int32_t bPredEq;
2627          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2628    
2629          MainSearch8FuncPtr EPZSMainSearchPtr;          MainSearch8FuncPtr MainSearchPtr;
2630    
2631  /* Get maximum range */  /* Get maximum range */
2632          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,
2633                          x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2634    
2635  /* 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 */
2636    
2637          if (!(MotionFlags & PMV_HALFPEL8 ))          if (!(MotionFlags & PMV_HALFPEL8)) {
2638          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2639            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2640            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2641            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2642          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2643            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2644          bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);          //bPredEq = get_pmvdata(pMBs, x >> 1, y >> 1, iWcount, iSubBlock, pmv[0].x, pmv[0].y, psad);
2645            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2646    
2647    
2648  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
# Line 1872  Line 2655 
2655  // Prepare for main loop  // Prepare for main loop
2656    
2657    
2658          if (!(MotionFlags & PMV_HALFPEL8))          if (!(MotionFlags & PMV_HALFPEL8)) {
         {  
2659                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2660                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2661          }          }
# Line 1890  Line 2672 
2672  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2673    
2674    
2675          iMinSAD = sad8( cur,          iMinSAD =
2676                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  sad8(cur,
2677                  iEdgedWidth);                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2678          iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode, iQuant);                                                  iEdgedWidth), iEdgedWidth);
2679            iMinSAD +=
2680                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2681                                             (uint8_t) iFcode, iQuant);
2682    
2683    
2684  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2685          if (iMinSAD < 256/4 )          if (iMinSAD < 256 / 4) {
                 {  
2686                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2687                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2688                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
# Line 1915  Line 2699 
2699          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y);
2700    
2701  // left neighbour, if allowed  // left neighbour, if allowed
2702          if (psad[1] != MV_MAX_ERROR)          if (psad[1] != MV_MAX_ERROR) {
2703          {                  if (!(MotionFlags & PMV_HALFPEL8)) {
2704                  if (!(MotionFlags & PMV_HALFPEL8 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2705                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2706                  }                  }
2707                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
2708          }          }
   
2709  // top neighbour, if allowed  // top neighbour, if allowed
2710          if (psad[2] != MV_MAX_ERROR)          if (psad[2] != MV_MAX_ERROR) {
2711          {                  if (!(MotionFlags & PMV_HALFPEL8)) {
2712                  if (!(MotionFlags & PMV_HALFPEL8 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2713                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2714                  }                  }
2715                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
2716    
2717  // top right neighbour, if allowed  // top right neighbour, if allowed
2718                  if (psad[3] != MV_MAX_ERROR)                  if (psad[3] != MV_MAX_ERROR) {
2719                  {                          if (!(MotionFlags & PMV_HALFPEL8)) {
2720                          if (!(MotionFlags & PMV_HALFPEL8 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2721                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2722                          }                          }
2723                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);
# Line 1955  Line 2735 
2735     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]
2736  */  */
2737    
2738          if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */          if (iMinSAD < 512 / 4) {        /* T_2 == 512/4 hardcoded */
                 {  
2739                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2740                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2741                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
# Line 1972  Line 2751 
2751    
2752  /* 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 */
2753    
2754  /* // there is no EPZS^2 for inter4v at the moment  // there is no EPZS^2 for inter4v at the moment
2755    
2756          if (MotionFlags & PMV_USESQUARES8)          if (MotionFlags & PMV_USESQUARES8)
2757                  EPZSMainSearchPtr = Square8_MainSearch;        MainSearchPtr = Square8_MainSearch;
2758          else          else
 */  
2759    
2760          EPZSMainSearchPtr = Diamond8_MainSearch;          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2761                    MainSearchPtr = AdvDiamond8_MainSearch;
2762            else
2763                    MainSearchPtr = Diamond8_MainSearch;
2764    
2765          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2766                  x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2767                  currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2768                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2769                  iDiamondSize, iFcode, iQuant, 0);                                                    iQuant, 0);
2770    
2771    
2772          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2773                  *currMV = newMV;                  *currMV = newMV;
2774                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2775          }          }
2776    
2777          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2778  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2779    
2780                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2781                  {                          iSAD =
2782                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2783                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2784                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2785                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, 0);
2786    
2787                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2788                                  *currMV = newMV;                                  *currMV = newMV;
2789                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2790                          }                          }
2791                  }                  }
2792    
2793                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2794                  {                          iSAD =
2795                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2796                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2797                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2798                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iQuant, 0);
2799    
2800                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2801                                  *currMV = newMV;                                  *currMV = newMV;
2802                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2803                          }                          }
# Line 2031  Line 2808 
2808    
2809  EPZS8_Terminate_with_Refine:  EPZS8_Terminate_with_Refine:
2810          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2811                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2812                                  x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2813                                  currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2814                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2815    
2816  EPZS8_Terminate_without_Refine:  EPZS8_Terminate_without_Refine:
2817    
2818          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2819          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2820          return iMinSAD;          return iMinSAD;
2821  }  }
2822    
2823    
2824    
2825    int32_t
2826    PMVfastIntSearch16(const uint8_t * const pRef,
2827                                    const uint8_t * const pRefH,
2828                                    const uint8_t * const pRefV,
2829                                    const uint8_t * const pRefHV,
2830                                    const IMAGE * const pCur,
2831                                    const int x,
2832                                    const int y,
2833                                    const int start_x,              /* start should be most likely vector */
2834                                    const int start_y,
2835                                    const int center_x,             /* center is from where length of MVs is measured */
2836                                    const int center_y,
2837                                    const uint32_t MotionFlags,
2838                                    const uint32_t iQuant,
2839                                    const uint32_t iFcode,
2840                                    const MBParam * const pParam,
2841                                    const MACROBLOCK * const pMBs,
2842                                    const MACROBLOCK * const prevMBs,
2843                                    VECTOR * const currMV,
2844                                    VECTOR * const currPMV)
2845    {
2846            const uint32_t iWcount = pParam->mb_width;
2847            const int32_t iWidth = pParam->width;
2848            const int32_t iHeight = pParam->height;
2849            const int32_t iEdgedWidth = pParam->edged_width;
2850    
2851            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
2852            const VECTOR zeroMV = { 0, 0 };
2853    
2854            int32_t iDiamondSize;
2855    
2856            int32_t min_dx;
2857            int32_t max_dx;
2858            int32_t min_dy;
2859            int32_t max_dy;
2860    
2861            int32_t iFound;
2862    
2863            VECTOR newMV;
2864            VECTOR backupMV;
2865    
2866            VECTOR pmv[4];
2867            int32_t psad[4];
2868    
2869            MainSearch16FuncPtr MainSearchPtr;
2870    
2871            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2872            MACROBLOCK *const pMB = pMBs + x + y * iWcount;
2873    
2874            int32_t threshA, threshB;
2875            int32_t bPredEq;
2876            int32_t iMinSAD, iSAD;
2877    
2878    
2879    /* Get maximum range */
2880            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2881                              iFcode);
2882    
2883    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2884    
2885            if ((x == 0) && (y == 0)) {
2886                    threshA = 512;
2887                    threshB = 1024;
2888    
2889                    bPredEq = 0;
2890                    psad[0] = psad[1] = psad[2] = psad[3] = 0;
2891                    *currMV = pmv[0] = pmv[1] = pmv[2] = pmv[3] = zeroMV;
2892    
2893            } else {
2894    
2895                    bPredEq = get_ipmvdata(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2896    
2897                    threshA = psad[0];
2898                    threshB = threshA + 256;
2899                    if (threshA < 512)
2900                            threshA = 512;
2901                    if (threshA > 1024)
2902                            threshA = 1024;
2903                    if (threshB > 1792)
2904                            threshB = 1792;
2905    
2906                    *currMV = pmv[0];                       /* current best := prediction */
2907            }
2908    
2909            iFound = 0;
2910    
2911    /* Step 4: Calculate SAD around the Median prediction.
2912       MinSAD=SAD
2913       If Motion Vector equal to Previous frame motion vector
2914       and MinSAD<PrevFrmSAD goto Step 10.
2915       If SAD<=256 goto Step 10.
2916    */
2917    
2918            if (currMV->x > max_dx) {
2919                    currMV->x = EVEN(max_dx);
2920            }
2921            if (currMV->x < min_dx) {
2922                    currMV->x = EVEN(min_dx);
2923            }
2924            if (currMV->y > max_dy) {
2925                    currMV->y = EVEN(max_dy);
2926            }
2927            if (currMV->y < min_dy) {
2928                    currMV->y = EVEN(min_dy);
2929            }
2930    
2931            iMinSAD =
2932                    sad16(cur,
2933                              get_iref_mv(pRef, x, y, 16, currMV,
2934                                                     iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2935            iMinSAD +=
2936                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2937                                              (uint8_t) iFcode, iQuant);
2938    
2939            if ((iMinSAD < 256) ||
2940                    ((MVequal(*currMV, prevMB->i_mvs[0])) &&
2941                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2942                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
2943                    {
2944                            if (!MVzero(*currMV)) {
2945                                    iMinSAD += MV16_00_BIAS;
2946                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
2947                                    iMinSAD -= MV16_00_BIAS;
2948                            }
2949                    }
2950    
2951                    if (MotionFlags & PMV_EARLYSTOP16)
2952                            goto PMVfastInt16_Terminate_with_Refine;
2953            }
2954    
2955    
2956    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2957       vector of the median.
2958       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2959    */
2960    
2961            if ((bPredEq) && (MVequal(pmv[0], prevMB->i_mvs[0])))
2962                    iFound = 2;
2963    
2964    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2965       Otherwise select large Diamond Search.
2966    */
2967    
2968            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
2969                    iDiamondSize = 2;               // halfpel units!
2970            else
2971                    iDiamondSize = 4;               // halfpel units!
2972    
2973    /*
2974       Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
2975       Also calculate (0,0) but do not subtract offset.
2976       Let MinSAD be the smallest SAD up to this point.
2977       If MV is (0,0) subtract offset.
2978    */
2979    
2980    // (0,0) is often a good choice
2981    
2982            if (!MVzero(pmv[0]))
2983                    CHECK_MV16_ZERO;
2984    
2985    // previous frame MV is always possible
2986    
2987            if (!MVzero(prevMB->i_mvs[0]))
2988                    if (!MVequal(prevMB->i_mvs[0], pmv[0]))
2989                            CHECK_MV16_CANDIDATE(prevMB->i_mvs[0].x, prevMB->i_mvs[0].y);
2990    
2991    // left neighbour, if allowed
2992    
2993            if (!MVzero(pmv[1]))
2994                    if (!MVequal(pmv[1], prevMB->i_mvs[0]))
2995                            if (!MVequal(pmv[1], pmv[0]))
2996                                    CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
2997    
2998    // top neighbour, if allowed
2999            if (!MVzero(pmv[2]))
3000                    if (!MVequal(pmv[2], prevMB->i_mvs[0]))
3001                            if (!MVequal(pmv[2], pmv[0]))
3002                                    if (!MVequal(pmv[2], pmv[1]))
3003                                            CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
3004    
3005    // top right neighbour, if allowed
3006                                            if (!MVzero(pmv[3]))
3007                                                    if (!MVequal(pmv[3], prevMB->i_mvs[0]))
3008                                                            if (!MVequal(pmv[3], pmv[0]))
3009                                                                    if (!MVequal(pmv[3], pmv[1]))
3010                                                                            if (!MVequal(pmv[3], pmv[2]))
3011                                                                                    CHECK_MV16_CANDIDATE(pmv[3].x,
3012                                                                                                                             pmv[3].y);
3013    
3014            if ((MVzero(*currMV)) &&
3015                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
3016                    iMinSAD -= MV16_00_BIAS;
3017    
3018    
3019    /* Step 6: If MinSAD <= thresa goto Step 10.
3020       If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
3021    */
3022    
3023            if ((iMinSAD <= threshA) ||
3024                    (MVequal(*currMV, prevMB->i_mvs[0]) &&
3025                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
3026    
3027                    if (MotionFlags & PMV_EARLYSTOP16)
3028                            goto PMVfastInt16_Terminate_with_Refine;
3029            }
3030    
3031    
3032    /************ (Diamond Search)  **************/
3033    /*
3034       Step 7: Perform Diamond search, with either the small or large diamond.
3035       If Found=2 only examine one Diamond pattern, and afterwards goto step 10
3036       Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
3037       If center then goto step 10.
3038       Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
3039       Refine by using small diamond and goto step 10.
3040    */
3041    
3042            if (MotionFlags & PMV_USESQUARES16)
3043                    MainSearchPtr = Square16_MainSearch;
3044            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
3045                    MainSearchPtr = AdvDiamond16_MainSearch;
3046            else
3047                    MainSearchPtr = Diamond16_MainSearch;
3048    
3049            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
3050    
3051    
3052    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
3053            iSAD =
3054                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
3055                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
3056                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
3057                                                      iQuant, iFound);
3058    
3059            if (iSAD < iMinSAD) {
3060                    *currMV = newMV;
3061                    iMinSAD = iSAD;
3062            }
3063    
3064            if (MotionFlags & PMV_EXTSEARCH16) {
3065    /* extended: search (up to) two more times: orignal prediction and (0,0) */
3066    
3067                    if (!(MVequal(pmv[0], backupMV))) {
3068                            iSAD =
3069                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
3070                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
3071                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
3072                                                                      iDiamondSize, iFcode, iQuant, iFound);
3073    
3074                            if (iSAD < iMinSAD) {
3075                                    *currMV = newMV;
3076                                    iMinSAD = iSAD;
3077                            }
3078                    }
3079    
3080                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
3081                            iSAD =
3082                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
3083                                                                      iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
3084                                                                      max_dy, iEdgedWidth, iDiamondSize, iFcode,
3085                                                                      iQuant, iFound);
3086    
3087                            if (iSAD < iMinSAD) {
3088                                    *currMV = newMV;
3089                                    iMinSAD = iSAD;
3090                            }
3091                    }
3092            }
3093    
3094    /*
3095       Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.
3096    */
3097    
3098    PMVfastInt16_Terminate_with_Refine:
3099    
3100            pMB->i_mvs[0] = pMB->i_mvs[1] = pMB->i_mvs[2] = pMB->i_mvs[3] = pMB->i_mv16 = *currMV;
3101            pMB->i_sad8[0] = pMB->i_sad8[1] = pMB->i_sad8[2] = pMB->i_sad8[3] = pMB->i_sad16 = iMinSAD;
3102    
3103            if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
3104                    iMinSAD =
3105                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
3106                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
3107                                                             iFcode, iQuant, iEdgedWidth);
3108    
3109            pmv[0] = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          // get _REAL_ prediction (halfpel possible)
3110    
3111    PMVfastInt16_Terminate_without_Refine:
3112            currPMV->x = currMV->x - center_x;
3113            currPMV->y = currMV->y - center_y;
3114            return iMinSAD;
3115    }
3116    
3117    
3118    
3119  /* ***********************************************************  /* ***********************************************************
3120          bvop motion estimation          bvop motion estimation
 // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)  
3121  ***************************************************************/  ***************************************************************/
3122    
3123    void
3124  void MotionEstimationBVOP(  MotionEstimationBVOP(MBParam * const pParam,
                         MBParam * const pParam,  
3125                          FRAMEINFO * const frame,                          FRAMEINFO * const frame,
3126                                             const int32_t time_bp,
3127                                             const int32_t time_pp,
3128                          // forward (past) reference                          // forward (past) reference
3129                          const MACROBLOCK * const f_mbs,                          const MACROBLOCK * const f_mbs,
3130                      const IMAGE * const f_ref,                      const IMAGE * const f_ref,
# Line 2070  Line 3138 
3138                      const IMAGE * const b_refV,                      const IMAGE * const b_refV,
3139                          const IMAGE * const b_refHV)                          const IMAGE * const b_refHV)
3140  {  {
3141      const uint32_t mb_width = pParam->mb_width;          const int mb_width = pParam->mb_width;
3142      const uint32_t mb_height = pParam->mb_height;          const int mb_height = pParam->mb_height;
3143          const int32_t edged_width = pParam->edged_width;          const int edged_width = pParam->edged_width;
3144    
3145          uint32_t i,j;          const int32_t iWidth = pParam->width;
3146            const int32_t iHeight = pParam->height;
3147          int32_t f_sad16;  
3148          int32_t b_sad16;          int i, j, k;
3149          int32_t i_sad16;  
3150          int32_t d_sad16;          static const VECTOR zeroMV={0,0};
3151          int32_t best_sad;  
3152            int f_sad16;    /* forward (as usual) search */
3153            int b_sad16;    /* backward (only in b-frames) search */
3154            int i_sad16;    /* interpolated (both direction, b-frames only) */
3155            int d_sad16;    /* direct mode (assume almost linear motion) */
3156    
3157            int best_sad;
3158    
3159            VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/
3160            VECTOR f_interpolMV, b_interpolMV;
3161          VECTOR pmv_dontcare;          VECTOR pmv_dontcare;
3162    
3163            int min_dx, max_dx, min_dy, max_dy;
3164            int f_min_dx, f_max_dx, f_min_dy, f_max_dy;
3165            int b_min_dx, b_max_dx, b_min_dy, b_max_dy;
3166    
3167            int f_count=0;
3168            int b_count=0;
3169            int i_count=0;
3170            int d_count=0;
3171    
3172            const int64_t TRB = (int32_t)time_pp - (int32_t)time_bp;
3173        const int64_t TRD = (int32_t)time_pp;
3174    
3175            // fprintf(stderr,"TRB = %lld  TRD = %lld  time_bp =%d time_pp =%d\n\n",TRB,TRD,time_bp,time_pp);
3176          // note: i==horizontal, j==vertical          // note: i==horizontal, j==vertical
3177      for (j = 0; j < mb_height; j++)          for (j = 0; j < mb_height; j++) {
3178          {  
3179                  for (i = 0; i < mb_width; i++)                  f_predMV = zeroMV;      /* prediction is reset at left boundary */
3180                  {                  b_predMV = zeroMV;
3181    
3182                    for (i = 0; i < mb_width; i++) {
3183                          MACROBLOCK *mb = &frame->mbs[i + j*mb_width];                          MACROBLOCK *mb = &frame->mbs[i + j*mb_width];
3184                          const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];                          const MACROBLOCK *f_mb = &f_mbs[i + j*mb_width];
3185                          const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];                          const MACROBLOCK *b_mb = &b_mbs[i + j*mb_width];
3186    
3187                          if (b_mb->mode == MODE_INTER                          mb->deltamv=zeroMV;
3188                                  && b_mb->cbp == 0  
3189                                  && b_mb->mvs[0].x == 0  /* special case, if collocated block is SKIPed: encoding is forward (0,0), cpb=0 without further ado */
3190                                  && b_mb->mvs[0].y == 0)  
3191                          {                          if (b_mb->mode == MODE_INTER && b_mb->cbp == 0 &&
3192                                    b_mb->mvs[0].x == 0 && b_mb->mvs[0].y == 0) {
3193                                  mb->mode = MODE_NOT_CODED;                                  mb->mode = MODE_NOT_CODED;
3194                                  mb->mvs[0].x = 0;                                  mb->b_mvs[0] = mb->mvs[0] = zeroMV;
                                 mb->mvs[0].y = 0;  
                                 mb->b_mvs[0].x = 0;  
                                 mb->b_mvs[0].y = 0;  
3195                                  continue;                                  continue;
3196                          }                          }
3197    
3198                            if (b_mb->mode == MODE_INTER4V)
3199                            {
3200                                    d_sad16 = 0;
3201                            /* same method of scaling as in decoder.c, so we copy from there */
3202                        for (k = 0; k < 4; k++) {
3203    
3204                                            mb->directmv[k] = b_mb->mvs[k];
3205    
3206                                            mb->mvs[k].x = (int32_t) ((TRB * mb->directmv[k].x) / TRD + mb->deltamv.x);
3207                        mb->b_mvs[k].x = (int32_t) ((mb->deltamv.x == 0)
3208                                                                                    ? ((TRB - TRD) * mb->directmv[k].x) / TRD
3209                                                : mb->mvs[k].x - mb->directmv[k].x);
3210    
3211                        mb->mvs[k].y = (int32_t) ((TRB * mb->directmv[k].y) / TRD + mb->deltamv.y);
3212                            mb->b_mvs[k].y = (int32_t) ((mb->deltamv.y == 0)
3213                                                                                    ? ((TRB - TRD) * mb->directmv[k].y) / TRD
3214                                                : mb->mvs[k].y - mb->directmv[k].y);
3215    
3216                                            d_sad16 +=
3217                                                    sad8bi(frame->image.y + (2*i+(k&1))*8 + (2*j+(k>>1))*8*edged_width,
3218                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3219                                                                    (2*i+(k&1)), (2*j+(k>>1)), 8, &mb->mvs[k], edged_width),
3220                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3221                                                                    (2*i+(k&1)), (2*j+(k>>1)), 8, &mb->b_mvs[k], edged_width),
3222                                                      edged_width);
3223                                    }
3224                            }
3225                            else
3226                            {
3227                                    mb->directmv[3] = mb->directmv[2] = mb->directmv[1] =
3228                                            mb->directmv[0] = b_mb->mvs[0];
3229    
3230                                    mb->mvs[0].x = (int32_t) ((TRB * mb->directmv[0].x) / TRD + mb->deltamv.x);
3231                        mb->b_mvs[0].x = (int32_t) ((mb->deltamv.x == 0)
3232                                                                            ? ((TRB - TRD) * mb->directmv[0].x) / TRD
3233                                        : mb->mvs[0].x - mb->directmv[0].x);
3234    
3235                        mb->mvs[0].y = (int32_t) ((TRB * mb->directmv[0].y) / TRD + mb->deltamv.y);
3236                    mb->b_mvs[0].y = (int32_t) ((mb->directmv[0].y == 0)
3237                                                                            ? ((TRB - TRD) * mb->directmv[0].y) / TRD
3238                                        : mb->mvs[0].y - mb->directmv[0].y);
3239    
3240                                    d_sad16 = sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,
3241                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3242                                                                    i, j, 16, &mb->mvs[0], edged_width),
3243                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3244                                                                    i, j, 16, &mb->b_mvs[0], edged_width),
3245                                                      edged_width);
3246    
3247                }
3248                        d_sad16 += calc_delta_16(mb->deltamv.x, mb->deltamv.y, 1, frame->quant);
3249    
3250                          // forward search                          // forward search
3251                          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,
3252                                                  &frame->image,                                                  &frame->image, i, j,
3253                                                  i, j,                                                  mb->mvs[0].x, mb->mvs[0].y,                     /* start point f_directMV */
3254                                                  frame->motion_flags,  frame->quant, frame->fcode,                                                  f_predMV.x, f_predMV.y,                         /* center is f-prediction */
3255                                                  pParam,                                                  frame->motion_flags,
3256                                                  f_mbs, f_mbs /* todo */,                                                  frame->quant, frame->fcode, pParam,
3257                                                  &mb->mvs[0], &pmv_dontcare);    // ignore pmv                                                  f_mbs, f_mbs,
3258                                                    &mb->mvs[0], &pmv_dontcare);
3259    
3260    
3261                          // backward search                          // backward search
3262                          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,
3263                                                  &frame->image,                                                  &frame->image, i, j,
3264                                                    mb->b_mvs[0].x, mb->b_mvs[0].y,         /* start point b_directMV */
3265                                                    b_predMV.x, b_predMV.y,                         /* center is b-prediction */
3266                                                    frame->motion_flags,
3267                                                    frame->quant, frame->bcode, pParam,
3268                                                    b_mbs, b_mbs,
3269                                                    &mb->b_mvs[0], &pmv_dontcare);
3270    
3271                            i_sad16 =
3272                                    sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,
3273                                                      get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3274                                                                    i, j, 16, &mb->mvs[0], edged_width),
3275                                                      get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3276                                                                    i, j, 16, &mb->b_mvs[0], edged_width),
3277                                                      edged_width);
3278                        i_sad16 += calc_delta_16(mb->mvs[0].x-f_predMV.x, mb->mvs[0].y-f_predMV.y,
3279                                                                    frame->fcode, frame->quant);
3280                        i_sad16 += calc_delta_16(mb->b_mvs[0].x-b_predMV.x, mb->b_mvs[0].y-b_predMV.y,
3281                                                                    frame->bcode, frame->quant);
3282    
3283                            get_range(&f_min_dx, &f_max_dx, &f_min_dy, &f_max_dy, i, j, 16, iWidth, iHeight,
3284                              frame->fcode);
3285                            get_range(&b_min_dx, &b_max_dx, &b_min_dy, &b_max_dy, i, j, 16, iWidth, iHeight,
3286                              frame->bcode);
3287    
3288    /* Interpolated MC motion vector search, this is tedious and more complicated because there are
3289       two values for everything, always one for backward and one for forward ME. Still, we don't gain
3290       much from this search, maybe it should simply be skipped and simply current i_sad16 value used
3291       as "optimal". */
3292    
3293                            i_sad16 = Diamond16_InterpolMainSearch(
3294                                                    f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3295                                                    frame->image.y + i * 16 + j * 16 * edged_width,
3296                                                    b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3297                                                  i, j,                                                  i, j,
3298                                                  frame->motion_flags,  frame->quant, frame->bcode,                                                  mb->mvs[0].x, mb->mvs[0].y,
3299                                                  pParam,                                                  mb->b_mvs[0].x, mb->b_mvs[0].y,
3300                                                  b_mbs, b_mbs, /* todo */                                                  i_sad16,
3301                                                  &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv                                                  &f_interpolMV, &b_interpolMV,
3302                                                    f_predMV.x, f_predMV.y, b_predMV.x, b_predMV.y,
3303                                                    f_min_dx, f_max_dx, f_min_dy, f_max_dy,
3304                                                    b_min_dx, b_max_dx, b_min_dy, b_max_dy,
3305                                                    edged_width,  2,
3306                                                    frame->fcode, frame->bcode,frame->quant,0);
3307    
3308                          // interpolate search (simple, but effective)                          i_sad16 = Diamond16_InterpolMainSearch(
3309                          i_sad16 = sad16bi_c(                                                  f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3310                                          frame->image.y + i*16 + j*16*edged_width,                                          frame->image.y + i*16 + j*16*edged_width,
3311                                          get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,                                                  b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3312                                                  i, j, 16, mb->mvs[0].x, mb->mvs[0].y, edged_width),                                                  i, j,
3313                                          get_ref(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,                                                  f_interpolMV.x, f_interpolMV.y,
3314                                                  i, j, 16, mb->b_mvs[0].x, mb->b_mvs[0].x, edged_width),                                                  b_interpolMV.x, b_interpolMV.y,
3315                                          edged_width);                                                  i_sad16,
3316                                                    &f_interpolMV, &b_interpolMV,
3317                                                    f_predMV.x, f_predMV.y, b_predMV.x, b_predMV.y,
3318                                                    f_min_dx, f_max_dx, f_min_dy, f_max_dy,
3319                                                    b_min_dx, b_max_dx, b_min_dy, b_max_dy,
3320                                                    edged_width,  1,
3321                                                    frame->fcode, frame->bcode,frame->quant,0);             // equiv to halfpel refine
3322    
3323    
3324    /*  DIRECT MODE DELTA VECTOR SEARCH.
3325        This has to be made more effective, but at the moment I'm happy it's running at all */
3326    
3327    /* There are two range restrictions for direct mode: deltaMV is limited to [-32,31] in halfpel units, and
3328       absolute vector must not lie outside of image dimensions. Constraint one is dealt with by CHECK_MV16_DIRECT
3329       and for constraint two we need distance to boundary. This is done by get_range very large fcode (hack!) */
3330    
3331                          // TODO: direct search                          get_range(&min_dx, &max_dx, &min_dy, &max_dy, i, j, 16, iWidth, iHeight, 19);
                         // predictor + range of [-32,32]  
                         d_sad16 = 65535;  
3332    
3333                            d_sad16 = Diamond16_DirectMainSearch(
3334                                                    f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3335                                                    frame->image.y + i*16 + j*16*edged_width,
3336                                                    b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3337                                                    i, j,
3338                                                    TRB,TRD,
3339                                                    0,0,
3340                                                    d_sad16,
3341                                                    &mb->deltamv,
3342                                                    mb->directmv, // this has to be pre-initialized with b_mb->mvs[]
3343                                            min_dx, max_dx, min_dy, max_dy,
3344                                                    edged_width, 2, frame->quant, 0);
3345    
3346                          if (f_sad16 < b_sad16)                          d_sad16 = Diamond16_DirectMainSearch(
3347                          {                                                  f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
3348                                                    frame->image.y + i*16 + j*16*edged_width,
3349                                                    b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
3350                                                    i, j,
3351                                                    TRB,TRD,
3352                                                    mb->deltamv.x, mb->deltamv.y,
3353                                                    d_sad16,
3354                                                    &mb->deltamv,
3355                                                    mb->directmv, // this has to be pre-initialized with b_mb->mvs[]
3356                                            min_dx, max_dx, min_dy, max_dy,
3357                                                    edged_width, 1, frame->quant, 0);               // equiv to halfpel refine
3358    
3359    
3360    //                      i_sad16 = 65535;                /* remove the comment to disable any of the MODEs */
3361    //                      f_sad16 = 65535;
3362    //                      b_sad16 = 65535;
3363    //                      d_sad16 = 65535;
3364    
3365                            if (f_sad16 < b_sad16) {
3366                                  best_sad = f_sad16;                                  best_sad = f_sad16;
3367                                  mb->mode = MODE_FORWARD;                                  mb->mode = MODE_FORWARD;
3368                          }                          } else {
                         else  
                         {  
3369                                  best_sad = b_sad16;                                  best_sad = b_sad16;
3370                                  mb->mode = MODE_BACKWARD;                                  mb->mode = MODE_BACKWARD;
3371                          }                          }
3372    
3373                          if (i_sad16 < best_sad)                          if (i_sad16 < best_sad) {
                         {  
3374                                  best_sad = i_sad16;                                  best_sad = i_sad16;
3375                                  mb->mode = MODE_INTERPOLATE;                                  mb->mode = MODE_INTERPOLATE;
3376                          }                          }
3377    
3378                          if (d_sad16 < best_sad)                          if (d_sad16 < best_sad) {
3379    
3380                                    if (b_mb->mode == MODE_INTER4V)
3381                          {                          {
3382    
3383                                    /* how to calc vectors is defined in standard. mvs[] and b_mvs[] are only for motion compensation */
3384                                    /* for the bitstream, the value mb->deltamv is read directly */
3385    
3386                                for (k = 0; k < 4; k++) {
3387    
3388                                                    mb->mvs[k].x = (int32_t) ((TRB * mb->directmv[k].x) / TRD + mb->deltamv.x);
3389                                mb->b_mvs[k].x = (int32_t) ((mb->deltamv.x == 0)
3390                                                                                            ? ((TRB - TRD) * mb->directmv[k].x) / TRD
3391                                                        : mb->mvs[k].x - mb->directmv[k].x);
3392    
3393                                mb->mvs[k].y = (int32_t) ((TRB * mb->directmv[k].y) / TRD + mb->deltamv.y);
3394                            mb->b_mvs[k].y = (int32_t) ((mb->deltamv.y == 0)
3395                                                                                            ? ((TRB - TRD) * mb->directmv[k].y) / TRD
3396                                                : mb->mvs[k].y - mb->directmv[k].y);
3397                                            }
3398                                    }
3399                                    else
3400                                    {
3401                                            mb->mvs[0].x = (int32_t) ((TRB * mb->directmv[0].x) / TRD + mb->deltamv.x);
3402    
3403                        mb->b_mvs[0].x = (int32_t) ((mb->deltamv.x == 0)
3404                                                                                    ? ((TRB - TRD) * mb->directmv[0].x) / TRD
3405                                            : mb->mvs[0].x - mb->directmv[0].x);
3406    
3407                                mb->mvs[0].y = (int32_t) ((TRB * mb->directmv[0].y) / TRD + mb->deltamv.y);
3408    
3409                            mb->b_mvs[0].y = (int32_t) ((mb->deltamv.y == 0)
3410                                                                                    ? ((TRB - TRD) * mb->directmv[0].y) / TRD
3411                                                : mb->mvs[0].y - mb->directmv[0].y);
3412    
3413                                            mb->mvs[3] = mb->mvs[2] = mb->mvs[1] = mb->mvs[0];
3414                                            mb->b_mvs[3] = mb->b_mvs[2] = mb->b_mvs[1] = mb->b_mvs[0];
3415                    }
3416    
3417                                  best_sad = d_sad16;                                  best_sad = d_sad16;
3418                                  mb->mode = MODE_DIRECT;                                  mb->mode = MODE_DIRECT;
3419                          }                          }
3420    
3421                            switch (mb->mode)
3422                            {
3423                                    case MODE_FORWARD:
3424                                            f_count++;
3425                                            f_predMV = mb->mvs[0];
3426                                            break;
3427                                    case MODE_BACKWARD:
3428                                            b_count++;
3429                                            b_predMV = mb->b_mvs[0];
3430    
3431                                            break;
3432                                    case MODE_INTERPOLATE:
3433                                            i_count++;
3434                                            mb->mvs[0] = f_interpolMV;
3435                                            mb->b_mvs[0] = b_interpolMV;
3436                                            f_predMV = mb->mvs[0];
3437                                            b_predMV = mb->b_mvs[0];
3438                                            break;
3439                                    case MODE_DIRECT:
3440                                            d_count++;
3441                                            break;
3442                                    default:
3443                                            break;
3444                            }
3445    
3446                  }                  }
3447          }          }
3448    
3449    #ifdef _DEBUG_BFRAME_STAT
3450            fprintf(stderr,"B-Stat: F: %04d   B: %04d   I: %04d  D: %04d\n",
3451                                    f_count,b_count,i_count,d_count);
3452    #endif
3453    
3454  }  }

Legend:
Removed from v.170  
changed lines
  Added in v.370

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