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

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

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

revision 136, Thu Apr 25 06:55:00 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
36   *      25.04.2002 partial prevMB conversion   *      25.04.2002 partial prevMB conversion
37   *  22.04.2002 remove some compile warning by chenm001 <chenm001@163.com>   *  22.04.2002 remove some compile warning by chenm001 <chenm001@163.com>
38   *  14.04.2002 added MotionEstimationBVOP()   *  14.04.2002 added MotionEstimationBVOP()
# Line 46  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)  
   
 /* 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);  
   
80    
 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);  
81    
82  typedef MainSearch16Func* MainSearch16FuncPtr;  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),
84                    (int) (1.49591 + 0.5), (int) (1.68601 + 0.5),
85            (int) (1.89187 + 0.5), (int) (2.11542 + 0.5), (int) (2.35878 + 0.5),
86                    (int) (2.62429 + 0.5), (int) (2.91455 + 0.5),
87            (int) (3.23253 + 0.5), (int) (3.58158 + 0.5), (int) (3.96555 + 0.5),
88                    (int) (4.38887 + 0.5), (int) (4.85673 + 0.5),
89            (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 */
99    
 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);  
100    
 typedef MainSearch8Func* MainSearch8FuncPtr;  
101    
102  // mv.length table  // mv.length table
103  static const uint32_t mvtab[33] = {  static const uint32_t mvtab[33] = {
# Line 192  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 200  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 218  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)  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 * (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)  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 * (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            for (y = 0; y < iHcount; y++)   {
185                    for (x = 0; x < iWcount; x ++)  {
186    
187          /* eventhough we have a seperate prevMBs,                          MACROBLOCK *const pMB = &pMBs[x + y * iWcount];
            pmvfast/epsz does something "funny" with the previous frames data */  
   
         for (i = 0; i < iHcount; i++)  
                 for (j = 0; j < iWcount; j++)  
                 {  
                         pMBs[j + i * iWcount].mvs[0] = prevMBs[j + i * iWcount].mvs[0];  
                         pMBs[j + i * iWcount].mvs[1] = prevMBs[j + i * iWcount].mvs[1];  
                         pMBs[j + i * iWcount].mvs[2] = prevMBs[j + i * iWcount].mvs[2];  
                         pMBs[j + i * iWcount].mvs[3] = prevMBs[j + i * iWcount].mvs[3];  
                 }  
   
         /*dprintf("*** BEFORE ***");  
         for (i = 0; i < iHcount; i++)  
                 for (j = 0; j < iWcount; j++)  
                 {  
                         dprintf("   [%i,%i] mode=%i dquant=%i mvs=(%i %i %i %i) sad8=(%i %i %i %i) sad16=(%i)", j,i,  
                                 pMBs[j + i * iWcount].mode,  
                                 pMBs[j + i * iWcount].dquant,  
                                 pMBs[j + i * iWcount].mvs[0],  
                                 pMBs[j + i * iWcount].mvs[1],  
                                 pMBs[j + i * iWcount].mvs[2],  
                                 pMBs[j + i * iWcount].mvs[3],  
                                 prevMBs[j + i * iWcount].sad8[0],  
                                 prevMBs[j + i * iWcount].sad8[1],  
                                 prevMBs[j + i * iWcount].sad8[2],  
                                 prevMBs[j + i * iWcount].sad8[3],  
                                 prevMBs[j + i * iWcount].sad16);  
                 }  
         */  
188    
189          // note: i==horizontal, j==vertical                          if (pMB->mode == MODE_NOT_CODED)
190          for (i = 0; i < iHcount; i++)                                  continue;
                 for (j = 0; j < iWcount; j++)  
                 {  
                         MACROBLOCK *pMB = &pMBs[j + i * iWcount];  
                         MACROBLOCK *prevMB = &prevMBs[j + i * iWcount];  
191    
192                          sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                          predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
                                          j, i, current->motion_flags, current->quant, current->fcode,  
                                          pParam, pMBs, prevMBs, &mv16, &pmv16);  
                         pMB->sad16=sad16;  
193    
194                            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                          /* decide: MODE_INTER or MODE_INTRA                          if (0 < (pMB->sad16 - MV16_INTER_BIAS)) {
202                             if (dev_intra < sad_inter - 2 * nb) use_intra                                  int32_t deviation;
                         */  
203    
204                          deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width);                                  deviation =
205                                            dev16(pCurrent->y + x * 16 + y * 16 * pParam->edged_width,
206                                                      pParam->edged_width);
207    
208                          if (deviation < (sad16 - INTER_BIAS))                                  if (deviation < (pMB->sad16 - MV16_INTER_BIAS)) {
                         {  
209                                  pMB->mode = MODE_INTRA;                                  pMB->mode = MODE_INTRA;
210                                  pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;                                          pMB->mv16 = pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
211                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;                                                  pMB->mvs[3] = zeroMV;
212                                            pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
213                                  pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = 0;                                                  pMB->sad8[3] = 0;
214    
215                                  iIntra++;                                  iIntra++;
216                                  if(iIntra >= iLimit)                                  if(iIntra >= iLimit)
# Line 340  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->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;
282                                                    pMB->sad8[1] *= 4;
283                                                    pMB->sad8[2] *= 4;
284                                                    pMB->sad8[3] *= 4;
285                                                    continue;
286                          }                          }
287                          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->pmvs[0].x = pmv16.x;  
                                 pMB->pmvs[0].y = pmv16.y;  
                         }  
288                  }                  }
289    
290  /*      dprintf("*** AFTER ***", pMBs[0].b_mvs[0].x);                          pMB->mode = MODE_INTER;
291          for (i = 0; i < iHcount; i++)                          pMB->pmvs[0] = pmv;     /* pMB->pmvs[1] = pMB->pmvs[2] = pMB->pmvs[3]  are not needed for INTER */
292                  for (j = 0; j < iWcount; j++)                          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                          dprintf("   [%i,%i] mode=%i dquant=%i mvs=(%i %i %i %i) sad8=(%i %i %i %i) sad16=(%i)", j,i,                                  pMB->sad16;
295                                  pMBs[j + i * iWcount].mode,                          }
                                 pMBs[j + i * iWcount].dquant,  
                                 pMBs[j + i * iWcount].mvs[0],  
                                 pMBs[j + i * iWcount].mvs[1],  
                                 pMBs[j + i * iWcount].mvs[2],  
                                 pMBs[j + i * iWcount].mvs[3],  
                                 pMBs[j + i * iWcount].sad8[0],  
                                 pMBs[j + i * iWcount].sad8[1],  
                                 pMBs[j + i * iWcount].sad8[2],  
                                 pMBs[j + i * iWcount].sad8[3],  
                                 pMBs[j + i * iWcount].sad16);  
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);\
     if (iSAD <= iQuant * 96)    \  
         iSAD -= MV16_00_BIAS; \  
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 449  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 459  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 469  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 477  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 485  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 495  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 505  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 515  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 541  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 553  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 583  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 595  Line 475 
475          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
476          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
477    
478          if (iDirection)          if (iDirection) {
479                  while (!iFound)                  while (!iFound) {
                 {  
480                          iFound = 1;                          iFound = 1;
481                          backupMV=*currMV;                          backupMV=*currMV;
482                            iDirectionBackup = iDirection;
483    
484                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
485                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
486                          if ( iDirection != 1)                                                                                     backupMV.y, 1);
487                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
488                          if ( iDirection != 4)                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
489                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                     backupMV.y, 2);
490                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
491                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
492                                                                                       backupMV.y - iDiamondSize, 3);
493                            if (iDirectionBackup != 3)
494                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
495                                                                                       backupMV.y + iDiamondSize, 4);
496                  }                  }
497          else          } else {
498          {                  currMV->x = start_x;
499                  currMV->x = startx;                  currMV->y = start_y;
                 currMV->y = starty;  
500          }          }
501          return iMinSAD;          return iMinSAD;
502  }  }
503    
504  int32_t Square16_MainSearch(  int32_t
505                                          const uint8_t * const pRef,  Square16_MainSearch(const uint8_t * const pRef,
506                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
507                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
508                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
509                                          const uint8_t * const cur,                                          const uint8_t * const cur,
510                                          const int x, const int y,                                          const int x,
511                                          int32_t startx, int32_t starty,                                          const int y,
512                                          int32_t iMinSAD,                                     const int start_x,
513                                       const int start_y,
514                                       int iMinSAD,
515                                          VECTOR * const currMV,                                          VECTOR * const currMV,
516                                          const VECTOR * const pmv,                                     const int center_x,
517                                          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
518                                          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
519                                            const int32_t max_dx,
520                                            const int32_t min_dy,
521                                            const int32_t max_dy,
522                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
523                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
524                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 642  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 658  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 772  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 782  Line 718 
718          return iMinSAD;          return iMinSAD;
719  }  }
720    
721  int32_t Full8_MainSearch(  int32_t
722                                          const uint8_t * const pRef,  AdvDiamond16_MainSearch(const uint8_t * const pRef,
723                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
724                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
725                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
726                                          const uint8_t * const cur,                                          const uint8_t * const cur,
727                                          const int x, const int y,                                                  const int x,
728                                          int32_t startx, int32_t starty,                                                  const int y,
729                                          int32_t iMinSAD,                                             int start_x,
730                                               int start_y,
731                                               int iMinSAD,
732                                          VECTOR * const currMV,                                          VECTOR * const currMV,
733                                          const VECTOR * const pmv,                                             const int center_x,
734                                          const int32_t min_dx, const int32_t max_dx,                                             const int center_y,
735                                          const int32_t min_dy, const int32_t max_dy,                                                  const int32_t min_dx,
736                                                    const int32_t max_dx,
737                                                    const int32_t min_dy,
738                                                    const int32_t max_dy,
739                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
740                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
741                                          const int32_t iFcode,                                          const int32_t iFcode,
742                                          const int32_t iQuant,                                          const int32_t iQuant,
743                                          int iFound)                                                  int iDirection)
744  {  {
745    
746          int32_t iSAD;          int32_t iSAD;
         int32_t dx,dy;  
         VECTOR backupMV;  
         backupMV.x = startx;  
         backupMV.y = starty;  
747    
748          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
                 for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)  
                         NOCHECK_MV8_CANDIDATE(dx,dy);  
749    
750          return iMinSAD;          if (iDirection) {
751  }                  CHECK_MV16_CANDIDATE(start_x - iDiamondSize, start_y);
752                    CHECK_MV16_CANDIDATE(start_x + iDiamondSize, start_y);
753                    CHECK_MV16_CANDIDATE(start_x, start_y - iDiamondSize);
754                    CHECK_MV16_CANDIDATE(start_x, start_y + iDiamondSize);
755            } else {
756                    int bDirection = 1 + 2 + 4 + 8;
757    
758                    do {
759                            iDirection = 0;
760                            if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
761                                    CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
762    
763                            if (bDirection & 2)
764                                    CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
765    
766  int32_t Halfpel16_Refine(                          if (bDirection & 4)
767          const uint8_t * const pRef,                                  CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
         const uint8_t * const pRefH,  
         const uint8_t * const pRefV,  
         const uint8_t * const pRefHV,  
         const uint8_t * const cur,  
         const int x, const int y,  
         VECTOR * const currMV,  
         int32_t iMinSAD,  
         const VECTOR * const pmv,  
         const int32_t min_dx, const int32_t max_dx,  
         const int32_t min_dy, const int32_t max_dy,  
         const int32_t iFcode,  
         const int32_t iQuant,  
         const int32_t iEdgedWidth)  
 {  
 /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  
768    
769          int32_t iSAD;                          if (bDirection & 8)
770          VECTOR backupMV = *currMV;                                  CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
771    
772          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y-1);                          /* now we're doing diagonal checks near our candidate */
         CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y-1);  
         CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y-1);  
         CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y);  
         CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y);  
         CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y+1);  
         CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y+1);  
         CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y+1);  
773    
774          return iMinSAD;                          if (iDirection)         //checking if anything found
775                            {
776                                    bDirection = iDirection;
777                                    iDirection = 0;
778                                    start_x = currMV->x;
779                                    start_y = currMV->y;
780                                    if (bDirection & 3)     //our candidate is left or right
781                                    {
782                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
783                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
784                                    } else                  // what remains here is up or down
785                                    {
786                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
787                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
788  }  }
789    
790  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)                                  if (iDirection) {
791                                            bDirection += iDirection;
792                                            start_x = currMV->x;
793  int32_t PMVfastSearch16(                                          start_y = currMV->y;
794                                          const uint8_t * const pRef,                                  }
795                                          const uint8_t * const pRefH,                          } else                          //about to quit, eh? not so fast....
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const uint32_t MotionFlags,  
                                         const uint32_t iQuant,  
                                         const uint32_t iFcode,  
                                         const MBParam * const pParam,  
                                         const MACROBLOCK * const pMBs,  
                                         const MACROBLOCK * const prevMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV)  
796  {  {
797      const uint32_t iWcount = pParam->mb_width;                                  switch (bDirection) {
798          const int32_t iWidth = pParam->width;                                  case 2:
799          const int32_t iHeight = pParam->height;                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
800          const int32_t iEdgedWidth = pParam->edged_width;                                                                                           start_y - iDiamondSize, 2 + 4);
801                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
802          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;                                                                                           start_y + iDiamondSize, 2 + 8);
803                                            break;
804                                    case 1:
805    
806          int32_t iDiamondSize;                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
807                                                                                             start_y - iDiamondSize, 1 + 4);
808                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
809                                                                                             start_y + iDiamondSize, 1 + 8);
810                                            break;
811                                    case 2 + 4:
812                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
813                                                                                             start_y - iDiamondSize, 1 + 4);
814                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
815                                                                                             start_y - iDiamondSize, 2 + 4);
816                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
817                                                                                             start_y + iDiamondSize, 2 + 8);
818                                            break;
819                                    case 4:
820                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
821                                                                                             start_y - iDiamondSize, 2 + 4);
822                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
823                                                                                             start_y - iDiamondSize, 1 + 4);
824                                            break;
825                                    case 8:
826                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
827                                                                                             start_y + iDiamondSize, 2 + 8);
828                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
829                                                                                             start_y + iDiamondSize, 1 + 8);
830                                            break;
831                                    case 1 + 4:
832                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
833                                                                                             start_y + iDiamondSize, 1 + 8);
834                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
835                                                                                             start_y - iDiamondSize, 1 + 4);
836                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
837                                                                                             start_y - iDiamondSize, 2 + 4);
838                                            break;
839                                    case 2 + 8:
840                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
841                                                                                             start_y - iDiamondSize, 1 + 4);
842                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
843                                                                                             start_y + iDiamondSize, 1 + 8);
844                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
845                                                                                             start_y + iDiamondSize, 2 + 8);
846                                            break;
847                                    case 1 + 8:
848                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
849                                                                                             start_y - iDiamondSize, 2 + 4);
850                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
851                                                                                             start_y + iDiamondSize, 2 + 8);
852                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
853                                                                                             start_y + iDiamondSize, 1 + 8);
854                                            break;
855                                    default:                //1+2+4+8 == we didn't find anything at all
856                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
857                                                                                             start_y - iDiamondSize, 1 + 4);
858                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
859                                                                                             start_y + iDiamondSize, 1 + 8);
860                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
861                                                                                             start_y - iDiamondSize, 2 + 4);
862                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
863                                                                                             start_y + iDiamondSize, 2 + 8);
864                                            break;
865                                    }
866                                    if (!iDirection)
867                                            break;          //ok, the end. really
868                                    else {
869                                            bDirection = iDirection;
870                                            start_x = currMV->x;
871                                            start_y = currMV->y;
872                                    }
873                            }
874                    }
875                    while (1);                              //forever
876            }
877            return iMinSAD;
878    }
879    
880    #define CHECK_MV16_F_INTERPOL(X,Y) { \
881      if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
882        && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
883      { \
884        iSAD = sad16bi( cur, \
885                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
886                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
887                            iEdgedWidth); \
888        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
889        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
890        if (iSAD < iMinSAD) \
891        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); } } \
892    }
893    
894    #define CHECK_MV16_F_INTERPOL_FOUND(X,Y) { \
895      if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
896        && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
897      { \
898        iSAD = sad16bi( cur, \
899                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
900                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
901                            iEdgedWidth); \
902        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
903        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
904        if (iSAD < iMinSAD) \
905        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); iFound=0;} } \
906    }
907    
908    #define CHECK_MV16_B_INTERPOL(X,Y) { \
909      if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
910        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
911      { \
912        iSAD = sad16bi( cur, \
913                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
914                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
915                            iEdgedWidth); \
916        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
917        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
918        if (iSAD < iMinSAD) \
919        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); } } \
920    }
921    
922    #define CHECK_MV16_B_INTERPOL_FOUND(X,Y) { \
923      if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
924        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
925      { \
926        iSAD = sad16bi( cur, \
927                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
928                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
929                            iEdgedWidth); \
930        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
931        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
932        if (iSAD < iMinSAD) \
933        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); iFound=0;} } \
934    }
935    
936    int32_t
937    Diamond16_InterpolMainSearch(
938                                            const uint8_t * const f_pRef,
939                                             const uint8_t * const f_pRefH,
940                                             const uint8_t * const f_pRefV,
941                                             const uint8_t * const f_pRefHV,
942    
943                                             const uint8_t * const cur,
944    
945                                            const uint8_t * const b_pRef,
946                                             const uint8_t * const b_pRefH,
947                                             const uint8_t * const b_pRefV,
948                                             const uint8_t * const b_pRefHV,
949    
950                                             const int x,
951                                             const int y,
952    
953                                       const int f_start_x,
954                                       const int f_start_y,
955                                       const int b_start_x,
956                                       const int b_start_y,
957    
958                                       int iMinSAD,
959                                       VECTOR * const f_currMV,
960                                       VECTOR * const b_currMV,
961    
962                                       const int f_center_x,
963                                       const int f_center_y,
964                                       const int b_center_x,
965                                       const int b_center_y,
966    
967                                        const int32_t f_min_dx,
968                                            const int32_t f_max_dx,
969                                            const int32_t f_min_dy,
970                                            const int32_t f_max_dy,
971    
972                                        const int32_t b_min_dx,
973                                            const int32_t b_max_dx,
974                                            const int32_t b_min_dy,
975                                            const int32_t b_max_dy,
976    
977                                            const int32_t iEdgedWidth,
978                                            const int32_t iDiamondSize,
979    
980                                            const int32_t f_iFcode,
981                                            const int32_t b_iFcode,
982    
983                                            const int32_t iQuant,
984                                            int iFound)
985    {
986    /* Do a diamond search around given starting point, return SAD of best */
987    
988            int32_t iSAD;
989    
990            VECTOR f_backupMV;
991            VECTOR b_backupMV;
992    
993            f_currMV->x = f_start_x;
994            f_currMV->y = f_start_y;
995            b_currMV->x = b_start_x;
996            b_currMV->y = b_start_y;
997    
998            do
999            {
1000                    iFound = 1;
1001    
1002                    f_backupMV = *f_currMV;
1003    
1004                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x - iDiamondSize, f_backupMV.y);
1005                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x + iDiamondSize, f_backupMV.y);
1006                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y - iDiamondSize);
1007                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y + iDiamondSize);
1008    
1009                    b_backupMV = *b_currMV;
1010    
1011                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x - iDiamondSize, b_backupMV.y);
1012                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x + iDiamondSize, b_backupMV.y);
1013                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y - iDiamondSize);
1014                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y + iDiamondSize);
1015    
1016            } while (!iFound);
1017    
1018            return iMinSAD;
1019    }
1020    
1021    /* Sorry, these MACROS really got too large... I'll turn them into function soon! */
1022    
1023    #define CHECK_MV16_DIRECT_FOUND(X,Y) \
1024            if ( (X)>=(-32) && (X)<=(31) && ((Y)>=-32) && ((Y)<=31) ) \
1025            { int k;\
1026            VECTOR mvs,b_mvs;       \
1027            iSAD = 0;\
1028            for (k = 0; k < 4; k++) {       \
1029                                            mvs.x = (int32_t) ((TRB * directmv[k].x) / TRD + (X));          \
1030                        b_mvs.x = (int32_t) (((X) == 0)                                                     \
1031                                                                                    ? ((TRB - TRD) * directmv[k].x) / TRD   \
1032                                                : mvs.x - directmv[k].x);                           \
1033                                                                                                                                                                    \
1034                        mvs.y = (int32_t) ((TRB * directmv[k].y) / TRD + (Y));              \
1035                            b_mvs.y = (int32_t) (((Y) == 0)                                                         \
1036                                                                                    ? ((TRB - TRD) * directmv[k].y) / TRD   \
1037                                                : mvs.y - directmv[k].y);                           \
1038                                                                                                                                                                    \
1039      if ( (mvs.x <= max_dx) && (mvs.x >= min_dx) \
1040        && (mvs.y <= max_dy) && (mvs.y >= min_dy)  \
1041            && (b_mvs.x <= max_dx) && (b_mvs.x >= min_dx)  \
1042        && (b_mvs.y <= max_dy) && (b_mvs.y >= min_dy) ) { \
1043                iSAD += sad8bi( cur + 8*(k&1) + 8*(k>>1)*iEdgedWidth,                                                                                                       \
1044                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \
1045                                            mvs.x, mvs.y, iEdgedWidth),                                                             \
1046                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \
1047                                            b_mvs.x, b_mvs.y, iEdgedWidth),                                                         \
1048                            iEdgedWidth); \
1049                    }       \
1050            else    \
1051                    iSAD = 65535;   \
1052            } \
1053            iSAD += calc_delta_16((X),(Y), 1, iQuant);\
1054            if (iSAD < iMinSAD) \
1055                {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iFound=0; } \
1056    }
1057    
1058    
1059    
1060    int32_t
1061    Diamond16_DirectMainSearch(
1062                                            const uint8_t * const f_pRef,
1063                                            const uint8_t * const f_pRefH,
1064                                            const uint8_t * const f_pRefV,
1065                                            const uint8_t * const f_pRefHV,
1066    
1067                                            const uint8_t * const cur,
1068    
1069                                            const uint8_t * const b_pRef,
1070                                            const uint8_t * const b_pRefH,
1071                                            const uint8_t * const b_pRefV,
1072                                            const uint8_t * const b_pRefHV,
1073    
1074                                            const int x,
1075                                            const int y,
1076    
1077                                            const int TRB,
1078                                            const int TRD,
1079    
1080                                        const int start_x,
1081                                        const int start_y,
1082    
1083                                        int iMinSAD,
1084                                        VECTOR * const currMV,
1085                                            const VECTOR * const directmv,
1086    
1087                                        const int32_t min_dx,
1088                                            const int32_t max_dx,
1089                                            const int32_t min_dy,
1090                                            const int32_t max_dy,
1091    
1092                                            const int32_t iEdgedWidth,
1093                                            const int32_t iDiamondSize,
1094    
1095                                            const int32_t iQuant,
1096                                            int iFound)
1097    {
1098    /* Do a diamond search around given starting point, return SAD of best */
1099    
1100            int32_t iSAD;
1101    
1102            VECTOR backupMV;
1103    
1104            currMV->x = start_x;
1105            currMV->y = start_y;
1106    
1107    /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1108    
1109            do
1110            {
1111                    iFound = 1;
1112    
1113                    backupMV = *currMV;
1114    
1115                    CHECK_MV16_DIRECT_FOUND(backupMV.x - iDiamondSize, backupMV.y);
1116                    CHECK_MV16_DIRECT_FOUND(backupMV.x + iDiamondSize, backupMV.y);
1117                    CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y - iDiamondSize);
1118                    CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y + iDiamondSize);
1119    
1120            } while (!iFound);
1121    
1122            return iMinSAD;
1123    }
1124    
1125    
1126    int32_t
1127    AdvDiamond8_MainSearch(const uint8_t * const pRef,
1128                                               const uint8_t * const pRefH,
1129                                               const uint8_t * const pRefV,
1130                                               const uint8_t * const pRefHV,
1131                                               const uint8_t * const cur,
1132                                               const int x,
1133                                               const int y,
1134                                               int start_x,
1135                                               int start_y,
1136                                               int iMinSAD,
1137                                               VECTOR * const currMV,
1138                                               const int center_x,
1139                                               const int center_y,
1140                                               const int32_t min_dx,
1141                                               const int32_t max_dx,
1142                                               const int32_t min_dy,
1143                                               const int32_t max_dy,
1144                                               const int32_t iEdgedWidth,
1145                                               const int32_t iDiamondSize,
1146                                               const int32_t iFcode,
1147                                               const int32_t iQuant,
1148                                               int iDirection)
1149    {
1150    
1151            int32_t iSAD;
1152    
1153    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
1154    
1155            if (iDirection) {
1156                    CHECK_MV8_CANDIDATE(start_x - iDiamondSize, start_y);
1157                    CHECK_MV8_CANDIDATE(start_x + iDiamondSize, start_y);
1158                    CHECK_MV8_CANDIDATE(start_x, start_y - iDiamondSize);
1159                    CHECK_MV8_CANDIDATE(start_x, start_y + iDiamondSize);
1160            } else {
1161                    int bDirection = 1 + 2 + 4 + 8;
1162    
1163                    do {
1164                            iDirection = 0;
1165                            if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
1166                                    CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1167    
1168                            if (bDirection & 2)
1169                                    CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1170    
1171                            if (bDirection & 4)
1172                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1173    
1174                            if (bDirection & 8)
1175                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1176    
1177                            /* now we're doing diagonal checks near our candidate */
1178    
1179                            if (iDirection)         //checking if anything found
1180                            {
1181                                    bDirection = iDirection;
1182                                    iDirection = 0;
1183                                    start_x = currMV->x;
1184                                    start_y = currMV->y;
1185                                    if (bDirection & 3)     //our candidate is left or right
1186                                    {
1187                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1188                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1189                                    } else                  // what remains here is up or down
1190                                    {
1191                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1192                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1193                                    }
1194    
1195                                    if (iDirection) {
1196                                            bDirection += iDirection;
1197                                            start_x = currMV->x;
1198                                            start_y = currMV->y;
1199                                    }
1200                            } else                          //about to quit, eh? not so fast....
1201                            {
1202                                    switch (bDirection) {
1203                                    case 2:
1204                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1205                                                                                            start_y - iDiamondSize, 2 + 4);
1206                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1207                                                                                            start_y + iDiamondSize, 2 + 8);
1208                                            break;
1209                                    case 1:
1210                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1211                                                                                            start_y - iDiamondSize, 1 + 4);
1212                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1213                                                                                            start_y + iDiamondSize, 1 + 8);
1214                                            break;
1215                                    case 2 + 4:
1216                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1217                                                                                            start_y - iDiamondSize, 1 + 4);
1218                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1219                                                                                            start_y - iDiamondSize, 2 + 4);
1220                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1221                                                                                            start_y + iDiamondSize, 2 + 8);
1222                                            break;
1223                                    case 4:
1224                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1225                                                                                            start_y - iDiamondSize, 2 + 4);
1226                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1227                                                                                            start_y - iDiamondSize, 1 + 4);
1228                                            break;
1229                                    case 8:
1230                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1231                                                                                            start_y + iDiamondSize, 2 + 8);
1232                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1233                                                                                            start_y + iDiamondSize, 1 + 8);
1234                                            break;
1235                                    case 1 + 4:
1236                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1237                                                                                            start_y + iDiamondSize, 1 + 8);
1238                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1239                                                                                            start_y - iDiamondSize, 1 + 4);
1240                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1241                                                                                            start_y - iDiamondSize, 2 + 4);
1242                                            break;
1243                                    case 2 + 8:
1244                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1245                                                                                            start_y - iDiamondSize, 1 + 4);
1246                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1247                                                                                            start_y + iDiamondSize, 1 + 8);
1248                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1249                                                                                            start_y + iDiamondSize, 2 + 8);
1250                                            break;
1251                                    case 1 + 8:
1252                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1253                                                                                            start_y - iDiamondSize, 2 + 4);
1254                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1255                                                                                            start_y + iDiamondSize, 2 + 8);
1256                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1257                                                                                            start_y + iDiamondSize, 1 + 8);
1258                                            break;
1259                                    default:                //1+2+4+8 == we didn't find anything at all
1260                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1261                                                                                            start_y - iDiamondSize, 1 + 4);
1262                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1263                                                                                            start_y + iDiamondSize, 1 + 8);
1264                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1265                                                                                            start_y - iDiamondSize, 2 + 4);
1266                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1267                                                                                            start_y + iDiamondSize, 2 + 8);
1268                                            break;
1269                                    }
1270                                    if (!(iDirection))
1271                                            break;          //ok, the end. really
1272                                    else {
1273                                            bDirection = iDirection;
1274                                            start_x = currMV->x;
1275                                            start_y = currMV->y;
1276                                    }
1277                            }
1278                    }
1279                    while (1);                              //forever
1280            }
1281            return iMinSAD;
1282    }
1283    
1284    
1285    int32_t
1286    Full8_MainSearch(const uint8_t * const pRef,
1287                                     const uint8_t * const pRefH,
1288                                     const uint8_t * const pRefV,
1289                                     const uint8_t * const pRefHV,
1290                                     const uint8_t * const cur,
1291                                     const int x,
1292                                     const int y,
1293                               const int start_x,
1294                               const int start_y,
1295                               int iMinSAD,
1296                               VECTOR * const currMV,
1297                               const int center_x,
1298                               const int center_y,
1299                                     const int32_t min_dx,
1300                                     const int32_t max_dx,
1301                                     const int32_t min_dy,
1302                                     const int32_t max_dy,
1303                                     const int32_t iEdgedWidth,
1304                                     const int32_t iDiamondSize,
1305                                     const int32_t iFcode,
1306                                     const int32_t iQuant,
1307                                     int iFound)
1308    {
1309            int32_t iSAD;
1310            int32_t dx, dy;
1311            VECTOR backupMV;
1312    
1313            backupMV.x = start_x;
1314            backupMV.y = start_y;
1315    
1316            for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
1317                    for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
1318                            NOCHECK_MV8_CANDIDATE(dx, dy);
1319    
1320            return iMinSAD;
1321    }
1322    
1323    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1324    
1325    int32_t
1326    Halfpel16_Refine(const uint8_t * const pRef,
1327                                     const uint8_t * const pRefH,
1328                                     const uint8_t * const pRefV,
1329                                     const uint8_t * const pRefHV,
1330                                     const uint8_t * const cur,
1331                                     const int x,
1332                                     const int y,
1333                                     VECTOR * const currMV,
1334                                     int32_t iMinSAD,
1335                               const int center_x,
1336                               const int center_y,
1337                                     const int32_t min_dx,
1338                                     const int32_t max_dx,
1339                                     const int32_t min_dy,
1340                                     const int32_t max_dy,
1341                                     const int32_t iFcode,
1342                                     const int32_t iQuant,
1343                                     const int32_t iEdgedWidth)
1344    {
1345    /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
1346    
1347            int32_t iSAD;
1348            VECTOR backupMV = *currMV;
1349    
1350            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y - 1);
1351            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y - 1);
1352            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y - 1);
1353            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y);
1354            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y);
1355            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y + 1);
1356            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y + 1);
1357            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y + 1);
1358    
1359            return iMinSAD;
1360    }
1361    
1362    #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1363    
1364    
1365    
1366    int32_t
1367    PMVfastSearch16(const uint8_t * const pRef,
1368                                    const uint8_t * const pRefH,
1369                                    const uint8_t * const pRefV,
1370                                    const uint8_t * const pRefHV,
1371                                    const IMAGE * const pCur,
1372                                    const int x,
1373                                    const int y,
1374                                    const int start_x,      /* start is searched first, so it should contain the most */
1375                                    const int start_y,  /* likely motion vector for this block */
1376                                    const int center_x,     /* center is from where length of MVs is measured */
1377                                    const int center_y,
1378                                    const uint32_t MotionFlags,
1379                                    const uint32_t iQuant,
1380                                    const uint32_t iFcode,
1381                                    const MBParam * const pParam,
1382                                    const MACROBLOCK * const pMBs,
1383                                    const MACROBLOCK * const prevMBs,
1384                                    VECTOR * const currMV,
1385                                    VECTOR * const currPMV)
1386    {
1387            const uint32_t iWcount = pParam->mb_width;
1388            const int32_t iWidth = pParam->width;
1389            const int32_t iHeight = pParam->height;
1390            const int32_t iEdgedWidth = pParam->edged_width;
1391    
1392            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
1393    
1394            int32_t iDiamondSize;
1395    
1396          int32_t min_dx;          int32_t min_dx;
1397          int32_t max_dx;          int32_t max_dx;
# Line 890  Line 1406 
1406          VECTOR pmv[4];          VECTOR pmv[4];
1407          int32_t psad[4];          int32_t psad[4];
1408    
1409          const MACROBLOCK * const pMB = pMBs + x + y * iWcount;          MainSearch16FuncPtr MainSearchPtr;
1410    
1411          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1412    
1413          static int32_t threshA,threshB;          int32_t threshA, threshB;
1414          int32_t bPredEq;          int32_t bPredEq;
1415          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1416    
1417  /* Get maximum range */  /* Get maximum range */
1418          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
1419                    x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
1420    
1421  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1422    
1423          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
1424          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1425          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1426          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1427          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1428          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
   
1429    
1430          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1431            //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1432            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1433    
1434          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1435                  threshA =  512;                  threshA =  512;
1436                  threshB = 1024;                  threshB = 1024;
1437            } else {
         }  
         else  
         {  
1438                  threshA = psad[0];                  threshA = psad[0];
1439                  threshB = threshA+256;                  threshB = threshA+256;
1440                  if (threshA< 512) threshA =  512;                  if (threshA < 512)
1441                  if (threshA>1024) threshA = 1024;                          threshA = 512;
1442                  if (threshB>1792) threshB = 1792;                  if (threshA > 1024)
1443                            threshA = 1024;
1444                    if (threshB > 1792)
1445                            threshB = 1792;
1446          }          }
1447    
1448          iFound=0;          iFound=0;
1449    
 /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  
    vector of the median.  
    If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2  
 */  
   
         if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[0]) ) )  
                 iFound=2;  
   
 /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  
    Otherwise select large Diamond Search.  
 */  
   
         if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536) || (bPredEq) )  
                 iDiamondSize=1; // halfpel!  
         else  
                 iDiamondSize=2; // halfpel!  
   
         if (!(MotionFlags & PMV_HALFPELDIAMOND16) )  
                 iDiamondSize*=2;  
   
1450  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1451     MinSAD=SAD     MinSAD=SAD
1452     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 957  Line 1454 
1454     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
1455  */  */
1456    
1457            currMV->x = start_x;
1458            currMV->y = start_y;
1459    
1460  // Prepare for main loop          if (!(MotionFlags & PMV_HALFPEL16)) {   /* This should NOT be necessary! */
   
         *currMV=pmv[0];         /* current best := prediction */  
         if (!(MotionFlags & PMV_HALFPEL16 ))  
         {       /* This should NOT be necessary! */  
1461                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1462                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
1463          }          }
1464    
1465          if (currMV->x > max_dx)          if (currMV->x > max_dx) {
         {  
1466                  currMV->x=max_dx;                  currMV->x=max_dx;
1467          }          }
1468          if (currMV->x < min_dx)          if (currMV->x < min_dx) {
         {  
1469                  currMV->x=min_dx;                  currMV->x=min_dx;
1470          }          }
1471          if (currMV->y > max_dy)          if (currMV->y > max_dy) {
         {  
1472                  currMV->y=max_dy;                  currMV->y=max_dy;
1473          }          }
1474          if (currMV->y < min_dy)          if (currMV->y < min_dy) {
         {  
1475                  currMV->y=min_dy;                  currMV->y=min_dy;
1476          }          }
1477    
1478          iMinSAD = sad16( cur,          iMinSAD =
1479                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1480                           iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1481          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1482            iMinSAD +=
1483          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
1484          {                                            (uint8_t) iFcode, iQuant);
1485    
1486            if ((iMinSAD < 256) ||
1487                    ((MVequal(*currMV, prevMB->mvs[0])) &&
1488                     ((int32_t) iMinSAD < prevMB->sad16))) {
1489                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
1490                    {
1491                            if (!MVzero(*currMV)) {
1492                                    iMinSAD += MV16_00_BIAS;
1493                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
1494                                    iMinSAD -= MV16_00_BIAS;
1495                            }
1496                    }
1497    
1498                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1499                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
# Line 998  Line 1501 
1501                          goto PMVfast16_Terminate_with_Refine;                          goto PMVfast16_Terminate_with_Refine;
1502          }          }
1503    
1504    
1505    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1506       vector of the median.
1507       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1508    */
1509    
1510            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[0])))
1511                    iFound = 2;
1512    
1513    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1514       Otherwise select large Diamond Search.
1515    */
1516    
1517            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
1518                    iDiamondSize = 1;               // halfpel!
1519            else
1520                    iDiamondSize = 2;               // halfpel!
1521    
1522            if (!(MotionFlags & PMV_HALFPELDIAMOND16))
1523                    iDiamondSize *= 2;
1524    
1525  /*  /*
1526     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
1527     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1528     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1529     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1530  */  */
1531    
1532  // (0,0) is always possible  // (0,0) is always possible
1533    
1534            if (!MVzero(pmv[0]))
1535          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1536    
1537  // previous frame MV is always possible  // previous frame MV is always possible
1538    
1539            if (!MVzero(prevMB->mvs[0]))
1540                    if (!MVequal(prevMB->mvs[0], pmv[0]))
1541          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1542    
1543  // left neighbour, if allowed  // left neighbour, if allowed
1544          if (x != 0)  
1545          {          if (!MVzero(pmv[1]))
1546                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!MVequal(pmv[1], prevMB->mvs[0]))
1547                  {       pmv[1].x = EVEN(pmv[1].x);                          if (!MVequal(pmv[1], pmv[0])) {
1548                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1549                                            pmv[1].x = EVEN(pmv[1].x);
1550                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1551                  }                  }
1552    
1553                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1554          }          }
   
1555  // top neighbour, if allowed  // top neighbour, if allowed
1556          if (y != 0)          if (!MVzero(pmv[2]))
1557          {                  if (!MVequal(pmv[2], prevMB->mvs[0]))
1558                  if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!MVequal(pmv[2], pmv[0]))
1559                  {       pmv[2].x = EVEN(pmv[2].x);                                  if (!MVequal(pmv[2], pmv[1])) {
1560                                            if (!(MotionFlags & PMV_HALFPEL16)) {
1561                                                    pmv[2].x = EVEN(pmv[2].x);
1562                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
1563                  }                  }
1564                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1565    
1566  // top right neighbour, if allowed  // top right neighbour, if allowed
1567                  if ((uint32_t)x != (iWcount-1))                                          if (!MVzero(pmv[3]))
1568                  {                                                  if (!MVequal(pmv[3], prevMB->mvs[0]))
1569                          if (!(MotionFlags & PMV_HALFPEL16 ))                                                          if (!MVequal(pmv[3], pmv[0]))
1570                          {       pmv[3].x = EVEN(pmv[3].x);                                                                  if (!MVequal(pmv[3], pmv[1]))
1571                                                                            if (!MVequal(pmv[3], pmv[2])) {
1572                                                                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1573                                                                                            pmv[3].x = EVEN(pmv[3].x);
1574                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1575                          }                          }
1576                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                  CHECK_MV16_CANDIDATE(pmv[3].x,
1577                                                                                                                             pmv[3].y);
1578                  }                  }
1579          }          }
1580    
1581            if ((MVzero(*currMV)) &&
1582                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1583                    iMinSAD -= MV16_00_BIAS;
1584    
1585    
1586  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
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 1065  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 1116  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 1132  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 1154  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 1166  Line 1724 
1724          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
1725          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1726    
1727          if (iDirection)          if (iDirection) {
1728                  while (!iFound)                  while (!iFound) {
                 {  
1729                          iFound = 1;                          iFound = 1;
1730                          backupMV=*currMV;       // since iDirection!=0, this is well defined!                          backupMV=*currMV;       // since iDirection!=0, this is well defined!
1731                            iDirectionBackup = iDirection;
1732    
1733                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
1734                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1735                          if ( iDirection != 1)                                                                                    backupMV.y, 1);
1736                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
1737                          if ( iDirection != 4)                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1738                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                    backupMV.y, 2);
1739                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
1740                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1741                                                                                      backupMV.y - iDiamondSize, 3);
1742                            if (iDirectionBackup != 3)
1743                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1744                                                                                      backupMV.y + iDiamondSize, 4);
1745                  }                  }
1746          else          } else {
1747                    currMV->x = start_x;
1748                    currMV->y = start_y;
1749            }
1750            return iMinSAD;
1751    }
1752    
1753    
1754    
1755    
1756    int32_t
1757    Square8_MainSearch(const uint8_t * const pRef,
1758                                            const uint8_t * const pRefH,
1759                                            const uint8_t * const pRefV,
1760                                            const uint8_t * const pRefHV,
1761                                            const uint8_t * const cur,
1762                                            const int x,
1763                                            const int y,
1764                                            int32_t start_x,
1765                                            int32_t start_y,
1766                                            int32_t iMinSAD,
1767                                            VECTOR * const currMV,
1768                                       const int center_x,
1769                                       const int center_y,
1770                                            const int32_t min_dx,
1771                                            const int32_t max_dx,
1772                                            const int32_t min_dy,
1773                                            const int32_t max_dy,
1774                                            const int32_t iEdgedWidth,
1775                                            const int32_t iDiamondSize,
1776                                            const int32_t iFcode,
1777                                            const int32_t iQuant,
1778                                            int iFound)
1779          {          {
1780                  currMV->x = startx;  /* Do a square search around given starting point, return SAD of best */
1781                  currMV->y = starty;  
1782            int32_t iDirection = 0;
1783            int32_t iSAD;
1784            VECTOR backupMV;
1785    
1786            backupMV.x = start_x;
1787            backupMV.y = start_y;
1788    
1789    /* It's one search with full square pattern, and new parts for all following diamonds */
1790    
1791    /*   new direction are extra, so 1-4 is normal diamond
1792          537
1793          1*2
1794          648
1795    */
1796    
1797            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1798            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1799            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1800            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1801    
1802            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1803                                                             backupMV.y - iDiamondSize, 5);
1804            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1805                                                             backupMV.y + iDiamondSize, 6);
1806            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1807                                                             backupMV.y - iDiamondSize, 7);
1808            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1809                                                             backupMV.y + iDiamondSize, 8);
1810    
1811    
1812            if (iDirection) {
1813                    while (!iFound) {
1814                            iFound = 1;
1815                            backupMV = *currMV;
1816    
1817                            switch (iDirection) {
1818                            case 1:
1819                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1820                                                                                       backupMV.y, 1);
1821                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1822                                                                                     backupMV.y - iDiamondSize, 5);
1823                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1824                                                                                     backupMV.y - iDiamondSize, 7);
1825                                    break;
1826                            case 2:
1827                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1828                                                                                     2);
1829                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1830                                                                                     backupMV.y + iDiamondSize, 6);
1831                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1832                                                                                     backupMV.y + iDiamondSize, 8);
1833                                    break;
1834    
1835                            case 3:
1836                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1837                                                                                     4);
1838                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1839                                                                                     backupMV.y - iDiamondSize, 7);
1840                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1841                                                                                     backupMV.y + iDiamondSize, 8);
1842                                    break;
1843    
1844                            case 4:
1845                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1846                                                                                     3);
1847                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1848                                                                                     backupMV.y - iDiamondSize, 5);
1849                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1850                                                                                     backupMV.y + iDiamondSize, 6);
1851                                    break;
1852    
1853                            case 5:
1854                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1855                                                                                     1);
1856                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1857                                                                                     3);
1858                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1859                                                                                     backupMV.y - iDiamondSize, 5);
1860                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1861                                                                                     backupMV.y + iDiamondSize, 6);
1862                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1863                                                                                     backupMV.y - iDiamondSize, 7);
1864                                    break;
1865    
1866                            case 6:
1867                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1868                                                                                     2);
1869                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1870                                                                                     3);
1871    
1872                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1873                                                                                     backupMV.y - iDiamondSize, 5);
1874                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1875                                                                                     backupMV.y + iDiamondSize, 6);
1876                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1877                                                                                     backupMV.y + iDiamondSize, 8);
1878    
1879                                    break;
1880    
1881                            case 7:
1882                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1883                                                                                       backupMV.y, 1);
1884                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1885                                                                                     4);
1886                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1887                                                                                     backupMV.y - iDiamondSize, 5);
1888                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1889                                                                                     backupMV.y - iDiamondSize, 7);
1890                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1891                                                                                     backupMV.y + iDiamondSize, 8);
1892                                    break;
1893    
1894                            case 8:
1895                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1896                                                                                     2);
1897                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1898                                                                                     4);
1899                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1900                                                                                     backupMV.y + iDiamondSize, 6);
1901                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1902                                                                                     backupMV.y - iDiamondSize, 7);
1903                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1904                                                                                     backupMV.y + iDiamondSize, 8);
1905                                    break;
1906                            default:
1907                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1908                                                                                     1);
1909                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1910                                                                                     2);
1911                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1912                                                                                     3);
1913                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1914                                                                                     4);
1915    
1916                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1917                                                                                     backupMV.y - iDiamondSize, 5);
1918                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1919                                                                                     backupMV.y + iDiamondSize, 6);
1920                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1921                                                                                     backupMV.y - iDiamondSize, 7);
1922                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1923                                                                                     backupMV.y + iDiamondSize, 8);
1924                                    break;
1925                            }
1926                    }
1927            } else {
1928                    currMV->x = start_x;
1929                    currMV->y = start_y;
1930          }          }
1931          return iMinSAD;          return iMinSAD;
1932  }  }
1933    
1934  int32_t Halfpel8_Refine(  
1935          const uint8_t * const pRef,  
1936    
1937    
1938    int32_t
1939    Halfpel8_Refine_c(const uint8_t * const pRef,
1940          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1941          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1942          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1943          const uint8_t * const cur,          const uint8_t * const cur,
1944          const int x, const int y,                                  const int x,
1945                                    const int y,
1946          VECTOR * const currMV,          VECTOR * const currMV,
1947          int32_t iMinSAD,          int32_t iMinSAD,
1948          const VECTOR * const pmv,                             const int center_x,
1949          const int32_t min_dx, const int32_t max_dx,                             const int center_y,
1950          const int32_t min_dy, const int32_t max_dy,                                  const int32_t min_dx,
1951                                    const int32_t max_dx,
1952                                    const int32_t min_dy,
1953                                    const int32_t max_dy,
1954          const int32_t iFcode,          const int32_t iFcode,
1955          const int32_t iQuant,          const int32_t iQuant,
1956          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 1225  Line 1975 
1975    
1976  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1977    
1978  int32_t PMVfastSearch8(  int32_t
1979                                          const uint8_t * const pRef,  PMVfastSearch8(const uint8_t * const pRef,
1980                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1981                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1982                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1983                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1984                                          const int x, const int y,                             const int x,
1985                                          const int start_x, const int start_y,                             const int y,
1986                               const int start_x,
1987                               const int start_y,
1988                                    const int center_x,
1989                                    const int center_y,
1990                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1991                                          const uint32_t iQuant,                                          const uint32_t iQuant,
1992                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1260  Line 2014 
2014          int32_t psad[4];          int32_t psad[4];
2015          VECTOR newMV;          VECTOR newMV;
2016          VECTOR backupMV;          VECTOR backupMV;
2017            VECTOR startMV;
2018    
2019          const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2020          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
2021    
2022          static int32_t threshA,threshB;           int32_t threshA, threshB;
2023          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
2024          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
2025    
2026          int32_t iSubBlock = ((y&1)<<1) + (x&1);          int32_t iSubBlock = (y & 1) + (y & 1) + (x & 1);
2027    
2028  /* Get maximum range */          MainSearch8FuncPtr MainSearchPtr;
         get_range(&min_dx, &max_dx, &min_dy, &max_dy,  
                   x, y, 8, iWidth, iHeight, iFcode);  
2029    
2030  /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */          /* Init variables */
2031            startMV.x = start_x;
2032            startMV.y = start_y;
2033    
2034          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          /* Get maximum range */
2035          { min_dx = EVEN(min_dx);          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2036                              iFcode);
2037    
2038            if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
2039                    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);
         }               /* because we might use IF (dx>max_dx) THEN dx=max_dx; */  
   
   
         bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);  
   
         if ((x==0) && (y==0) )  
         {  
                 threshA =  512/4;  
                 threshB = 1024/4;  
   
         }  
         else  
         {  
                 threshA = psad[0]/4;                    /* good estimate */  
                 threshB = threshA+256/4;  
                 if (threshA< 512/4) threshA =  512/4;  
                 if (threshA>1024/4) threshA = 1024/4;  
                 if (threshB>1792/4) threshB = 1792/4;  
2043          }          }
2044    
2045          iFound=0;          /* 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  /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion          bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
    vector of the median.  
    If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2  
 */  
   
         if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[iSubBlock]) ) )  
                 iFound=2;  
2048    
2049  /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.          if ((x == 0) && (y == 0)) {
2050     Otherwise select large Diamond Search.                  threshA = 512 / 4;
2051  */                  threshB = 1024 / 4;
2052    
2053          if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536/4) || (bPredEq) )          } else {
2054                  iDiamondSize=1; // 1 halfpel!                  threshA = psad[0] / 4;  /* good estimate? */
2055          else                  threshB = threshA + 256 / 4;
2056                  iDiamondSize=2; // 2 halfpel = 1 full pixel!                  if (threshA < 512 / 4)
2057                            threshA = 512 / 4;
2058                    if (threshA > 1024 / 4)
2059                            threshA = 1024 / 4;
2060                    if (threshB > 1792 / 4)
2061                            threshB = 1792 / 4;
2062            }
2063    
2064          if (!(MotionFlags & PMV_HALFPELDIAMOND8) )          iFound = 0;
                 iDiamondSize*=2;  
2065    
2066  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2067     MinSAD=SAD     MinSAD=SAD
# Line 1333  Line 2073 
2073    
2074  // Prepare for main loop  // Prepare for main loop
2075    
2076          currMV->x=start_x;              /* start with mv16 */    if (MotionFlags & PMV_USESQUARES8)
2077          currMV->y=start_y;        MainSearchPtr = Square8_MainSearch;
2078      else
2079    
2080          iMinSAD = sad8( cur,          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2081                          get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  MainSearchPtr = AdvDiamond8_MainSearch;
2082                          iEdgedWidth);          else
2083          iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode) * iQuant;                  MainSearchPtr = Diamond8_MainSearch;
2084    
2085          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )  
2086          {          *currMV = startMV;
2087    
2088            iMinSAD =
2089                    sad8(cur,
2090                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2091                                                    iEdgedWidth), iEdgedWidth);
2092            iMinSAD +=
2093                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2094                                             (uint8_t) iFcode, iQuant);
2095    
2096            if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))
2097                                                                    && ((int32_t) iMinSAD <
2098                                                                            prevMB->sad8[iSubBlock]))) {
2099                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2100                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2101                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
2102                          goto PMVfast8_Terminate_with_Refine;                          goto PMVfast8_Terminate_with_Refine;
2103          }          }
2104    
2105    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2106       vector of the median.
2107       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2108    */
2109    
2110            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[iSubBlock])))
2111                    iFound = 2;
2112    
2113    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2114       Otherwise select large Diamond Search.
2115    */
2116    
2117            if ((!MVzero(pmv[0])) || (threshB < 1536 / 4) || (bPredEq))
2118                    iDiamondSize = 1;               // 1 halfpel!
2119            else
2120                    iDiamondSize = 2;               // 2 halfpel = 1 full pixel!
2121    
2122            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2123                    iDiamondSize *= 2;
2124    
2125    
2126  /*  /*
2127     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
2128     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
2129     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
2130     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
2131  */  */
2132    
2133  // the prediction might be even better than mv16  // the median prediction might be even better than mv16
         CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);  
2134    
2135  // (0,0) is always possible          if (!MVequal(pmv[0], startMV))
2136                    CHECK_MV8_CANDIDATE(center_x, center_y);
2137    
2138    // (0,0) if needed
2139            if (!MVzero(pmv[0]))
2140                    if (!MVzero(startMV))
2141          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
2142    
2143  // previous frame MV is always possible  // previous frame MV if needed
2144          CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);          if (!MVzero(prevMB->mvs[iSubBlock]))
2145                    if (!MVequal(prevMB->mvs[iSubBlock], startMV))
2146                            if (!MVequal(prevMB->mvs[iSubBlock], pmv[0]))
2147                                    CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,
2148                                                                            prevMB->mvs[iSubBlock].y);
2149    
2150            if ((iMinSAD <= threshA) ||
2151                    (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2152                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2153                    if (MotionFlags & PMV_QUICKSTOP16)
2154                            goto PMVfast8_Terminate_without_Refine;
2155                    if (MotionFlags & PMV_EARLYSTOP16)
2156                            goto PMVfast8_Terminate_with_Refine;
2157            }
2158    
2159  // left neighbour, if allowed  // left neighbour, if allowed and needed
2160          if (psad[1] != MV_MAX_ERROR)          if (!MVzero(pmv[1]))
2161          {                  if (!MVequal(pmv[1], startMV))
2162                  if (!(MotionFlags & PMV_HALFPEL8 ))                          if (!MVequal(pmv[1], prevMB->mvs[iSubBlock]))
2163                  {       pmv[1].x = EVEN(pmv[1].x);                                  if (!MVequal(pmv[1], pmv[0])) {
2164                                            if (!(MotionFlags & PMV_HALFPEL8)) {
2165                                                    pmv[1].x = EVEN(pmv[1].x);
2166                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
2167                  }                  }
2168                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
2169          }          }
2170    // top neighbour, if allowed and needed
2171  // top neighbour, if allowed          if (!MVzero(pmv[2]))
2172          if (psad[2] != MV_MAX_ERROR)                  if (!MVequal(pmv[2], startMV))
2173          {                          if (!MVequal(pmv[2], prevMB->mvs[iSubBlock]))
2174                  if (!(MotionFlags & PMV_HALFPEL8 ))                                  if (!MVequal(pmv[2], pmv[0]))
2175                  {       pmv[2].x = EVEN(pmv[2].x);                                          if (!MVequal(pmv[2], pmv[1])) {
2176                                                    if (!(MotionFlags & PMV_HALFPEL8)) {
2177                                                            pmv[2].x = EVEN(pmv[2].x);
2178                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
2179                  }                  }
2180                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
2181    
2182  // top right neighbour, if allowed  // top right neighbour, if allowed and needed
2183                  if (psad[3] != MV_MAX_ERROR)                                                  if (!MVzero(pmv[3]))
2184                  {                                                          if (!MVequal(pmv[3], startMV))
2185                          if (!(MotionFlags & PMV_HALFPEL8 ))                                                                  if (!MVequal(pmv[3], prevMB->mvs[iSubBlock]))
2186                          {       pmv[3].x = EVEN(pmv[3].x);                                                                          if (!MVequal(pmv[3], pmv[0]))
2187                                                                                    if (!MVequal(pmv[3], pmv[1]))
2188                                                                                            if (!MVequal(pmv[3], pmv[2])) {
2189                                                                                                    if (!
2190                                                                                                            (MotionFlags &
2191                                                                                                             PMV_HALFPEL8)) {
2192                                                                                                            pmv[3].x = EVEN(pmv[3].x);
2193                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
2194                          }                          }
2195                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                                  CHECK_MV8_CANDIDATE(pmv[3].x,
2196                                                                                                                                            pmv[3].y);
2197                  }                  }
2198          }          }
2199    
2200            if ((MVzero(*currMV)) &&
2201                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2202                    iMinSAD -= MV8_00_BIAS;
2203    
2204    
2205  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
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,pMB->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 1421  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 1469  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 1519  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(1,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);
   
 /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  
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 1559  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 1577  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,pMB->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 1594  Line 2410 
2410  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2411    
2412  // previous frame MV  // previous frame MV
2413          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
2414    
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 1616  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 1650  Line 2459 
2459  */  */
2460    
2461          if ( (iMinSAD <= thresh2)          if ( (iMinSAD <= thresh2)
2462                  || ( MVequal(*currMV,pMB->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 1660  Line 2469 
2469    
2470  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
2471    
2472          backupMV = pMB->mvs[0];                 // last MV          backupMV = prevMB->mvs[0];      // collocated MV
2473          backupMV.x += (pMB->mvs[0].x - oldMB->mvs[0].x );       // acceleration X          backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x);     // acceleration X
2474          backupMV.y += (pMB->mvs[0].y - oldMB->mvs[0].y );       // acceleration Y          backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y);     // acceleration Y
2475    
2476          CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);          CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);
2477    
2478  // left neighbour  // left neighbour
2479          if (x != 0)          if (x != 0)
2480                  CHECK_MV16_CANDIDATE((oldMB-1)->mvs[0].x,oldMB->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB - 1)->mvs[0].x, (prevMB - 1)->mvs[0].y);
2481    
2482    // top neighbour
2483            if (y != 0)
2484                    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
2488    
2489            if ((uint32_t) x != iWcount - 1)
2490                    CHECK_MV16_CANDIDATE((prevMB + 1)->mvs[0].x, (prevMB + 1)->mvs[0].y);
2491    
2492    // bottom neighbour, dito
2493            if ((uint32_t) y != iHcount - 1)
2494                    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)  */
2498            if (iMinSAD <= thresh2) {
2499                    if (MotionFlags & PMV_QUICKSTOP16)
2500                            goto EPZS16_Terminate_without_Refine;
2501                    if (MotionFlags & PMV_EARLYSTOP16)
2502                            goto EPZS16_Terminate_with_Refine;
2503            }
2504    
2505    /************ (if Diamond Search)  **************/
2506    
2507            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2508    
2509            if (MotionFlags & PMV_USESQUARES16)
2510                    MainSearchPtr = Square16_MainSearch;
2511            else
2512             if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2513                    MainSearchPtr = AdvDiamond16_MainSearch;
2514            else
2515                    MainSearchPtr = Diamond16_MainSearch;
2516    
2517    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2518    
2519            iSAD =
2520                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2521                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2522                                                      min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2523    
2524            if (iSAD < iMinSAD) {
2525                    *currMV = newMV;
2526                    iMinSAD = iSAD;
2527            }
2528    
2529    
2530            if (MotionFlags & PMV_EXTSEARCH16) {
2531    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2532    
2533                    if (!(MVequal(pmv[0], backupMV))) {
2534                            iSAD =
2535                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2536                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2537                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2538                                                                      2, iFcode, iQuant, 0);
2539                    }
2540    
2541                    if (iSAD < iMinSAD) {
2542                            *currMV = newMV;
2543                            iMinSAD = iSAD;
2544                    }
2545    
2546                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2547                            iSAD =
2548                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2549                                                                      iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2550                                                                      max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2551    
2552                            if (iSAD < iMinSAD) {
2553                                    *currMV = newMV;
2554                                    iMinSAD = iSAD;
2555                            }
2556                    }
2557            }
2558    
2559    /***************        Choose best MV found     **************/
2560    
2561      EPZS16_Terminate_with_Refine:
2562            if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
2563                    iMinSAD =
2564                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2565                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2566                                                             iFcode, iQuant, iEdgedWidth);
2567    
2568      EPZS16_Terminate_without_Refine:
2569    
2570            *oldMB = *prevMB;
2571    
2572            currPMV->x = currMV->x - center_x;
2573            currPMV->y = currMV->y - center_y;
2574            return iMinSAD;
2575    }
2576    
2577    
2578    int32_t
2579    EPZSSearch8(const uint8_t * const pRef,
2580                            const uint8_t * const pRefH,
2581                            const uint8_t * const pRefV,
2582                            const uint8_t * const pRefHV,
2583                            const IMAGE * const pCur,
2584                            const int x,
2585                            const int y,
2586                            const int start_x,
2587                            const int start_y,
2588                            const int center_x,
2589                            const int center_y,
2590                            const uint32_t MotionFlags,
2591                            const uint32_t iQuant,
2592                            const uint32_t iFcode,
2593                            const MBParam * const pParam,
2594                            const MACROBLOCK * const pMBs,
2595                            const MACROBLOCK * const prevMBs,
2596                            VECTOR * const currMV,
2597                            VECTOR * const currPMV)
2598    {
2599    /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
2600    
2601            const uint32_t iWcount = pParam->mb_width;
2602            const int32_t iWidth = pParam->width;
2603            const int32_t iHeight = pParam->height;
2604            const int32_t iEdgedWidth = pParam->edged_width;
2605    
2606            const uint8_t *cur = pCur->y + x * 8 + y * 8 * iEdgedWidth;
2607    
2608            int32_t iDiamondSize = 1;
2609    
2610            int32_t min_dx;
2611            int32_t max_dx;
2612            int32_t min_dy;
2613            int32_t max_dy;
2614    
2615            VECTOR newMV;
2616            VECTOR backupMV;
2617    
2618            VECTOR pmv[4];
2619            int32_t psad[8];
2620    
2621            const int32_t iSubBlock = ((y & 1) << 1) + (x & 1);
2622    
2623    //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2624            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
2625    
2626            int32_t bPredEq;
2627            int32_t iMinSAD, iSAD = 9999;
2628    
2629            MainSearch8FuncPtr MainSearchPtr;
2630    
2631    /* Get maximum range */
2632            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2633                              iFcode);
2634    
2635    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2636    
2637            if (!(MotionFlags & PMV_HALFPEL8)) {
2638                    min_dx = EVEN(min_dx);
2639                    max_dx = EVEN(max_dx);
2640                    min_dy = EVEN(min_dy);
2641                    max_dy = EVEN(max_dy);
2642            }
2643            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2644            //bPredEq = get_pmvdata(pMBs, x >> 1, y >> 1, iWcount, iSubBlock, pmv[0].x, pmv[0].y, psad);
2645            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2646    
2647    
2648    /* Step 4: Calculate SAD around the Median prediction.
2649            MinSAD=SAD
2650            If Motion Vector equal to Previous frame motion vector
2651                    and MinSAD<PrevFrmSAD goto Step 10.
2652            If SAD<=256 goto Step 10.
2653    */
2654    
2655    // Prepare for main loop
2656    
2657    
2658            if (!(MotionFlags & PMV_HALFPEL8)) {
2659                    currMV->x = EVEN(currMV->x);
2660                    currMV->y = EVEN(currMV->y);
2661            }
2662    
2663            if (currMV->x > max_dx)
2664                    currMV->x = max_dx;
2665            if (currMV->x < min_dx)
2666                    currMV->x = min_dx;
2667            if (currMV->y > max_dy)
2668                    currMV->y = max_dy;
2669            if (currMV->y < min_dy)
2670                    currMV->y = min_dy;
2671    
2672    /***************** This is predictor SET A: only median prediction ******************/
2673    
2674    
2675            iMinSAD =
2676                    sad8(cur,
2677                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2678                                                    iEdgedWidth), iEdgedWidth);
2679            iMinSAD +=
2680                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2681                                             (uint8_t) iFcode, iQuant);
2682    
2683    
2684    // thresh1 is fixed to 256
2685            if (iMinSAD < 256 / 4) {
2686                    if (MotionFlags & PMV_QUICKSTOP8)
2687                            goto EPZS8_Terminate_without_Refine;
2688                    if (MotionFlags & PMV_EARLYSTOP8)
2689                            goto EPZS8_Terminate_with_Refine;
2690            }
2691    
2692    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2693    
2694    
2695    // MV=(0,0) is often a good choice
2696            CHECK_MV8_ZERO;
2697    
2698    // previous frame MV
2699            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x, prevMB->mvs[iSubBlock].y);
2700    
2701    // left neighbour, if allowed
2702            if (psad[1] != MV_MAX_ERROR) {
2703                    if (!(MotionFlags & PMV_HALFPEL8)) {
2704                            pmv[1].x = EVEN(pmv[1].x);
2705                            pmv[1].y = EVEN(pmv[1].y);
2706                    }
2707                    CHECK_MV8_CANDIDATE(pmv[1].x, pmv[1].y);
2708            }
2709    // top neighbour, if allowed
2710            if (psad[2] != MV_MAX_ERROR) {
2711                    if (!(MotionFlags & PMV_HALFPEL8)) {
2712                            pmv[2].x = EVEN(pmv[2].x);
2713                            pmv[2].y = EVEN(pmv[2].y);
2714                    }
2715                    CHECK_MV8_CANDIDATE(pmv[2].x, pmv[2].y);
2716    
2717    // top right neighbour, if allowed
2718                    if (psad[3] != MV_MAX_ERROR) {
2719                            if (!(MotionFlags & PMV_HALFPEL8)) {
2720                                    pmv[3].x = EVEN(pmv[3].x);
2721                                    pmv[3].y = EVEN(pmv[3].y);
2722                            }
2723                            CHECK_MV8_CANDIDATE(pmv[3].x, pmv[3].y);
2724                    }
2725            }
2726    
2727  // top neighbour  /*  // this bias is zero anyway, at the moment!
         if (y != 0)  
                 CHECK_MV16_CANDIDATE((oldMB-iWcount)->mvs[0].x,oldMB->mvs[0].y);  
2728    
2729  // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs          if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
2730                    iMinSAD -= MV8_00_BIAS;
2731    
2732          if ((uint32_t)x != iWcount-1)  */
                 CHECK_MV16_CANDIDATE((pMB+1)->mvs[0].x,oldMB->mvs[0].y);  
2733    
2734  // bottom neighbour, dito  /* Terminate if MinSAD <= T_2
2735          if ((uint32_t)y != iHcount-1)     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
2736                  CHECK_MV16_CANDIDATE((pMB+iWcount)->mvs[0].x,oldMB->mvs[0].y);  */
2737    
2738  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */          if (iMinSAD < 512 / 4) {        /* T_2 == 512/4 hardcoded */
2739          if (iMinSAD <= thresh2)                  if (MotionFlags & PMV_QUICKSTOP8)
2740                  {                          goto EPZS8_Terminate_without_Refine;
2741                          if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_EARLYSTOP8)
2742                                  goto EPZS16_Terminate_without_Refine;                          goto EPZS8_Terminate_with_Refine;
                         if (MotionFlags & PMV_EARLYSTOP16)  
                                 goto EPZS16_Terminate_with_Refine;  
2743                  }                  }
2744    
2745  /************ (if Diamond Search)  **************/  /************ (Diamond Search)  **************/
2746    
2747          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2748    
2749  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */          if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2750                    iDiamondSize *= 2;
2751    
2752          if (MotionFlags & PMV_USESQUARES16)  /* default: use best prediction as starting point for one call of EPZS_MainSearch */
2753                  EPZSMainSearchPtr = Square16_MainSearch;  
2754    // there is no EPZS^2 for inter4v at the moment
2755    
2756      if (MotionFlags & PMV_USESQUARES8)
2757          MainSearchPtr = Square8_MainSearch;
2758          else          else
                 EPZSMainSearchPtr = Diamond16_MainSearch;  
2759    
2760          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2761                          x, y,                  MainSearchPtr = AdvDiamond8_MainSearch;
2762                          currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,          else
2763                          2, iFcode, iQuant, 0);                  MainSearchPtr = Diamond8_MainSearch;
2764    
2765          if (iSAD < iMinSAD)          iSAD =
2766          {                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2767                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2768                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2769                                                      iQuant, 0);
2770    
2771    
2772            if (iSAD < iMinSAD) {
2773                  *currMV = newMV;                  *currMV = newMV;
2774                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2775          }          }
2776    
2777            if (MotionFlags & PMV_EXTSEARCH8) {
         if (MotionFlags & PMV_EXTSEARCH16)  
         {  
2778  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2779    
2780                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2781                  {                          iSAD =
2782                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2783                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2784                                  pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2785                                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, 0);
                 }  
2786    
2787                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2788                          *currMV = newMV;                          *currMV = newMV;
2789                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2790                  }                  }
2791                    }
2792    
2793                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2794                  {                          iSAD =
2795                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2796                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2797                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2798                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, /*iDiamondSize*/ 2, iFcode, iQuant, 0);                                                                    iQuant, 0);
2799    
2800                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2801                                  *currMV = newMV;                                  *currMV = newMV;
2802                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2803                          }                          }
# Line 1750  Line 2806 
2806    
2807  /***************        Choose best MV found     **************/  /***************        Choose best MV found     **************/
2808    
2809  EPZS16_Terminate_with_Refine:    EPZS8_Terminate_with_Refine:
2810          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step
2811                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2812                                  x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2813                                  currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2814                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
   
 EPZS16_Terminate_without_Refine:  
2815    
2816          *oldMB = *pMB;    EPZS8_Terminate_without_Refine:
2817    
2818          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2819          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2820          return iMinSAD;          return iMinSAD;
2821  }  }
2822    
2823    
2824  int32_t EPZSSearch8(  
2825                                          const uint8_t * const pRef,  int32_t
2826    PMVfastIntSearch16(const uint8_t * const pRef,
2827                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2828                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2829                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2830                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2831                                          const int x, const int y,                                  const int x,
2832                                          const int start_x, const int start_y,                                  const int y,
2833                                    const int start_x,              /* start should be most likely vector */
2834                                    const int start_y,
2835                                    const int center_x,             /* center is from where length of MVs is measured */
2836                                    const int center_y,
2837                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2838                                          const uint32_t iQuant,                                          const uint32_t iQuant,
2839                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1789  Line 2848 
2848          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
2849          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
2850    
2851          const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;          const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
2852            const VECTOR zeroMV = { 0, 0 };
2853    
2854          int32_t iDiamondSize=1;          int32_t iDiamondSize;