[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 344, Sat Jul 27 23:07:33 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);  
                 }  
         */  
   
         // note: i==horizontal, j==vertical  
         for (i = 0; i < iHcount; i++)  
                 for (j = 0; j < iWcount; j++)  
                 {  
                         MACROBLOCK *pMB = &pMBs[j + i * iWcount];  
                         MACROBLOCK *prevMB = &prevMBs[j + i * iWcount];  
188    
189                          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;  
190    
191                            pMB->sad16 =
192                                    SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
193                                                     x, y, predMV.x, predMV.y, predMV.x, predMV.y,
194                                                     current->motion_flags, current->quant,
195                                                     current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,
196                                                     &pMB->pmvs[0]);
197    
198                          /* decide: MODE_INTER or MODE_INTRA                          if (0 < (pMB->sad16 - MV16_INTER_BIAS)) {
199                             if (dev_intra < sad_inter - 2 * nb) use_intra                                  int32_t deviation;
                         */  
200    
201                          deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width);                                  deviation =
202                                            dev16(pCurrent->y + x * 16 + y * 16 * pParam->edged_width,
203                                                      pParam->edged_width);
204    
205                          if (deviation < (sad16 - INTER_BIAS))                                  if (deviation < (pMB->sad16 - MV16_INTER_BIAS)) {
                         {  
206                                  pMB->mode = MODE_INTRA;                                  pMB->mode = MODE_INTRA;
207                                  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] =
208                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;                                                  pMB->mvs[3] = zeroMV;
209                                            pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
210                                  pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = 0;                                                  pMB->sad8[3] = 0;
211    
212                                  iIntra++;                                  iIntra++;
213                                  if(iIntra >= iLimit)                                  if(iIntra >= iLimit)
# Line 340  Line 215 
215    
216                                  continue;                                  continue;
217                          }                          }
218                            }
219    
220                            pmv = pMB->pmvs[0];
221                          if (current->global_flags & XVID_INTER4V)                          if (current->global_flags & XVID_INTER4V)
222                          {                                  if ((!(current->global_flags & XVID_LUMIMASKING) ||
223                                  pMB->sad8[0] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                           pMB->dquant == NO_CHANGE)) {
224                                                         2 * j, 2 * i, mv16.x, mv16.y,                                          int32_t sad8 = IMV16X16 * current->quant;
225                                                             current->motion_flags, current->quant, current->fcode,  
226                                                         pParam, pMBs, prevMBs, &pMB->mvs[0], &pMB->pmvs[0]);                                          if (sad8 < pMB->sad16) {
227                                                    sad8 += pMB->sad8[0] =
228                                  pMB->sad8[1] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
229                                                         2 * j + 1, 2 * i, mv16.x, mv16.y,                                                                          pCurrent, 2 * x, 2 * y,
230                                                             current->motion_flags, current->quant, current->fcode,                                                                          pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
231                                                         pParam, pMBs, prevMBs, &pMB->mvs[1], &pMB->pmvs[1]);                                                                          current->motion_flags,
232                                                                            current->quant, current->fcode, pParam,
233                                  pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                                          pMBs, prevMBs, &pMB->mvs[0],
234                                                         2 * j, 2 * i + 1, mv16.x, mv16.y,                                                                          &pMB->pmvs[0]);
235                                                             current->motion_flags, current->quant, current->fcode,                                          }
236                                                         pParam, pMBs, prevMBs, &pMB->mvs[2], &pMB->pmvs[2]);                                          if (sad8 < pMB->sad16) {
237    
238                                  pMB->sad8[3] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                                                  predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 1);
239                                                         2 * j + 1, 2 * i + 1, mv16.x, mv16.y,                                                  sad8 += pMB->sad8[1] =
240                                                             current->motion_flags, current->quant, current->fcode,                                                          SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
241                                                         pParam, pMBs, prevMBs, &pMB->mvs[3], &pMB->pmvs[3]);                                                                          pCurrent, 2 * x + 1, 2 * y,
242                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
243                                  sad8 = pMB->sad8[0] + pMB->sad8[1] + pMB->sad8[2] + pMB->sad8[3];                                                                          current->motion_flags,
244                                                                            current->quant, current->fcode, pParam,
245                                                                            pMBs, prevMBs, &pMB->mvs[1],
246                                                                            &pMB->pmvs[1]);
247                                            }
248                                            if (sad8 < pMB->sad16) {
249                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 2);
250                                                    sad8 += pMB->sad8[2] =
251                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
252                                                                            pCurrent, 2 * x, 2 * y + 1,
253                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
254                                                                            current->motion_flags,
255                                                                            current->quant, current->fcode, pParam,
256                                                                            pMBs, prevMBs, &pMB->mvs[2],
257                                                                            &pMB->pmvs[2]);
258                                            }
259                                            if (sad8 < pMB->sad16) {
260                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 3);
261                                                    sad8 += pMB->sad8[3] =
262                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
263                                                                            pCurrent, 2 * x + 1, 2 * y + 1,
264                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
265                                                                            current->motion_flags,
266                                                                            current->quant, current->fcode, pParam,
267                                                                            pMBs, prevMBs,
268                                                                            &pMB->mvs[3],
269                                                                            &pMB->pmvs[3]);
270                          }                          }
271    
   
272                          /* decide: MODE_INTER or MODE_INTER4V                          /* decide: MODE_INTER or MODE_INTER4V
273                             mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v                                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
274                          */                          */
275    
276                          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  
277                                          pMB->mode = MODE_INTER4V;                                          pMB->mode = MODE_INTER4V;
278                                                    pMB->sad8[0] *= 4;
279                                                    pMB->sad8[1] *= 4;
280                                                    pMB->sad8[2] *= 4;
281                                                    pMB->sad8[3] *= 4;
282                                                    continue;
283                          }                          }
284                          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;  
                         }  
285                  }                  }
286    
287  /*      dprintf("*** AFTER ***", pMBs[0].b_mvs[0].x);                          pMB->mode = MODE_INTER;
288          for (i = 0; i < iHcount; i++)                          pMB->pmvs[0] = pmv;     /* pMB->pmvs[1] = pMB->pmvs[2] = pMB->pmvs[3]  are not needed for INTER */
289                  for (j = 0; j < iWcount; j++)                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
290                  {                          pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =
291                          dprintf("   [%i,%i] mode=%i dquant=%i mvs=(%i %i %i %i) sad8=(%i %i %i %i) sad16=(%i)", j,i,                                  pMB->sad16;
292                                  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);  
293                  }                  }
         */  
294    
295          return 0;          return 0;
296  }  }
297    
 #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )  
   
 #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )  
   
298    
299  #define CHECK_MV16_ZERO {\  #define CHECK_MV16_ZERO {\
300    if ( (0 <= max_dx) && (0 >= min_dx) \    if ( (0 <= max_dx) && (0 >= min_dx) \
301      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
302    { \    { \
303      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); \
304      iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16(-center_x, -center_y, (uint8_t)iFcode, iQuant);\
     if (iSAD <= iQuant * 96)    \  
         iSAD -= MV16_00_BIAS; \  
305      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
306      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
307  }  }
308    
309  #define NOCHECK_MV16_CANDIDATE(X,Y) { \  #define NOCHECK_MV16_CANDIDATE(X,Y) { \
310      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
311      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
312      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
313      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
314  }  }
# Line 449  Line 318 
318      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
319    { \    { \
320      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
321      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
322      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
323      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
324  }  }
# Line 459  Line 328 
328      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
329    { \    { \
330      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
331      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
332      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
333      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
334  }  }
# Line 469  Line 338 
338      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
339    { \    { \
340      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
341      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
342      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
343      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
344  }  }
# Line 477  Line 346 
346    
347  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
348    iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \    iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); \
349    iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\    iSAD += calc_delta_8(-center_x, -center_y, (uint8_t)iFcode, iQuant);\
350    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
351    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
352  }  }
# Line 485  Line 354 
354  #define NOCHECK_MV8_CANDIDATE(X,Y) \  #define NOCHECK_MV8_CANDIDATE(X,Y) \
355    { \    { \
356      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
357      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
358      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
359      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
360  }  }
# Line 495  Line 364 
364      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
365    { \    { \
366      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
367      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
368      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
369      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
370  }  }
# Line 505  Line 374 
374      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
375    { \    { \
376      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
377      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
378      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
379      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
380  }  }
# Line 515  Line 384 
384      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
385    { \    { \
386      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
387      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
388      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
389      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
390  }  }
# Line 541  Line 410 
410          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
411          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
412          int32_t iSAD;          int32_t iSAD;
413          int32_t pred_x,pred_y;          VECTOR pred;
414    
415    
416          get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);          pred = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
417    
418          iSAD = sad16( cur,          iSAD = sad16( cur,
419                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),
# Line 553  Line 423 
423    
424          currMV->x = 0;          currMV->x = 0;
425          currMV->y = 0;          currMV->y = 0;
426          currPMV->x = -pred_x;          currPMV->x = -pred.x;
427          currPMV->y = -pred_y;          currPMV->y = -pred.y;
428    
429          return iSAD;          return iSAD;
430    
431  }  }
432  */  */
433    
434  int32_t Diamond16_MainSearch(  int32_t
435          const uint8_t * const pRef,  Diamond16_MainSearch(const uint8_t * const pRef,
436          const uint8_t * const pRefH,          const uint8_t * const pRefH,
437          const uint8_t * const pRefV,          const uint8_t * const pRefV,
438          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
439          const uint8_t * const cur,          const uint8_t * const cur,
440          const int x, const int y,                                           const int x,
441          int32_t startx, int32_t starty,                                           const int y,
442          int32_t iMinSAD,                                     const int start_x,
443                                       const int start_y,
444                                       int iMinSAD,
445          VECTOR * const currMV,          VECTOR * const currMV,
446          const VECTOR * const pmv,                                     const int center_x,
447          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
448          const int32_t min_dy, const int32_t max_dy,                                           const int32_t min_dx,
449                                             const int32_t max_dx,
450                                             const int32_t min_dy,
451                                             const int32_t max_dy,
452          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
453          const int32_t iDiamondSize,          const int32_t iDiamondSize,
454          const int32_t iFcode,          const int32_t iFcode,
# Line 583  Line 458 
458  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
459    
460          int32_t iDirection=0;          int32_t iDirection=0;
461            int32_t iDirectionBackup;
462          int32_t iSAD;          int32_t iSAD;
463          VECTOR backupMV;          VECTOR backupMV;
464          backupMV.x = startx;  
465          backupMV.y = starty;          backupMV.x = start_x;
466            backupMV.y = start_y;
467    
468  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
469    
# Line 595  Line 472 
472          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
473          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
474    
475          if (iDirection)          if (iDirection) {
476                  while (!iFound)                  while (!iFound) {
                 {  
477                          iFound = 1;                          iFound = 1;
478                          backupMV=*currMV;                          backupMV=*currMV;
479                            iDirectionBackup = iDirection;
480    
481                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
482                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
483                          if ( iDirection != 1)                                                                                     backupMV.y, 1);
484                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
485                          if ( iDirection != 4)                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
486                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                     backupMV.y, 2);
487                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
488                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
489                                                                                       backupMV.y - iDiamondSize, 3);
490                            if (iDirectionBackup != 3)
491                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
492                                                                                       backupMV.y + iDiamondSize, 4);
493                  }                  }
494          else          } else {
495          {                  currMV->x = start_x;
496                  currMV->x = startx;                  currMV->y = start_y;
                 currMV->y = starty;  
497          }          }
498          return iMinSAD;          return iMinSAD;
499  }  }
500    
501  int32_t Square16_MainSearch(  int32_t
502                                          const uint8_t * const pRef,  Square16_MainSearch(const uint8_t * const pRef,
503                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
504                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
505                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
506                                          const uint8_t * const cur,                                          const uint8_t * const cur,
507                                          const int x, const int y,                                          const int x,
508                                          int32_t startx, int32_t starty,                                          const int y,
509                                          int32_t iMinSAD,                                     const int start_x,
510                                       const int start_y,
511                                       int iMinSAD,
512                                          VECTOR * const currMV,                                          VECTOR * const currMV,
513                                          const VECTOR * const pmv,                                     const int center_x,
514                                          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
515                                          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
516                                            const int32_t max_dx,
517                                            const int32_t min_dy,
518                                            const int32_t max_dy,
519                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
520                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
521                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 642  Line 527 
527          int32_t iDirection=0;          int32_t iDirection=0;
528          int32_t iSAD;          int32_t iSAD;
529          VECTOR backupMV;          VECTOR backupMV;
530          backupMV.x = startx;  
531          backupMV.y = starty;          backupMV.x = start_x;
532            backupMV.y = start_y;
533    
534  /* It's one search with full square pattern, and new parts for all following diamonds */  /* It's one search with full square pattern, and new parts for all following diamonds */
535    
# Line 658  Line 544 
544          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
545          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
546    
547          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
548          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                           backupMV.y - iDiamondSize, 5);
549          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
550          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                                           backupMV.y + iDiamondSize, 6);
551            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
552                                                             backupMV.y - iDiamondSize, 7);
553            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
554                                                             backupMV.y + iDiamondSize, 8);
555    
556    
557          if (iDirection)          if (iDirection)
558                  while (!iFound)                  while (!iFound) {
                 {  
559                          iFound = 1;                          iFound = 1;
560                          backupMV=*currMV;                          backupMV=*currMV;
561    
562                          switch (iDirection)                          switch (iDirection) {
                         {  
563                                  case 1:                                  case 1:
564                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
565                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                     backupMV.y, 1);
566                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
567                                                                                     backupMV.y - iDiamondSize, 5);
568                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
569                                                                                     backupMV.y - iDiamondSize, 7);
570                                          break;                                          break;
571                                  case 2:                                  case 2:
572                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
573                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   2);
574                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
575                                                                                     backupMV.y + iDiamondSize, 6);
576                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
577                                                                                     backupMV.y + iDiamondSize, 8);
578                                          break;                                          break;
579    
580                                  case 3:                                  case 3:
581                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
582                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
583                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
584                                                                                     backupMV.y - iDiamondSize, 7);
585                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
586                                                                                     backupMV.y + iDiamondSize, 8);
587                                          break;                                          break;
588    
589                                  case 4:                                  case 4:
590                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
591                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
592                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
593                                                                                     backupMV.y - iDiamondSize, 5);
594                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
595                                                                                     backupMV.y + iDiamondSize, 6);
596                                          break;                                          break;
597    
598                                  case 5:                                  case 5:
599                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y,
600                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   1);
601                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
602                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   3);
603                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
604                                                                                     backupMV.y - iDiamondSize, 5);
605                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
606                                                                                     backupMV.y + iDiamondSize, 6);
607                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
608                                                                                     backupMV.y - iDiamondSize, 7);
609                                          break;                                          break;
610    
611                                  case 6:                                  case 6:
612                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
613                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   2);
614                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
615                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
616                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);  
617                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
618                                                                                     backupMV.y - iDiamondSize, 5);
619                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
620                                                                                     backupMV.y + iDiamondSize, 6);
621                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
622                                                                                     backupMV.y + iDiamondSize, 8);
623    
624                                          break;                                          break;
625    
626                                  case 7:                                  case 7:
627                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
628                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                     backupMV.y, 1);
629                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
630                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
631                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
632                                                                                     backupMV.y - iDiamondSize, 5);
633                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
634                                                                                     backupMV.y - iDiamondSize, 7);
635                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
636                                                                                     backupMV.y + iDiamondSize, 8);
637                                          break;                                          break;
638    
639                                  case 8:                                  case 8:
640                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
641                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
642                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
643                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
644                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
645                                                                                     backupMV.y + iDiamondSize, 6);
646                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
647                                                                                     backupMV.y - iDiamondSize, 7);
648                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
649                                                                                     backupMV.y + iDiamondSize, 8);
650                                          break;                                          break;
651                          default:                          default:
652                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y,
653                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                                                                   1);
654                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
655                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
656                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
657                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
658                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
659                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
660                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);  
661                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
662                                                                                     backupMV.y - iDiamondSize, 5);
663                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
664                                                                                     backupMV.y + iDiamondSize, 6);
665                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
666                                                                                     backupMV.y - iDiamondSize, 7);
667                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
668                                                                                     backupMV.y + iDiamondSize, 8);
669                                          break;                                          break;
670                          }                          }
671                  }          } else {
672          else                  currMV->x = start_x;
673                  {                  currMV->y = start_y;
                         currMV->x = startx;  
                         currMV->y = starty;  
674                  }                  }
675          return iMinSAD;          return iMinSAD;
676  }  }
677    
678    
679  int32_t Full16_MainSearch(  int32_t
680                                          const uint8_t * const pRef,  Full16_MainSearch(const uint8_t * const pRef,
681                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
682                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
683                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
684                                          const uint8_t * const cur,                                          const uint8_t * const cur,
685                                          const int x, const int y,                                    const int x,
686                                          int32_t startx, int32_t starty,                                    const int y,
687                                          int32_t iMinSAD,                                     const int start_x,
688                                       const int start_y,
689                                       int iMinSAD,
690                                          VECTOR * const currMV,                                          VECTOR * const currMV,
691                                          const VECTOR * const pmv,                                     const int center_x,
692                                          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
693                                          const int32_t min_dy, const int32_t max_dy,                                    const int32_t min_dx,
694                                      const int32_t max_dx,
695                                      const int32_t min_dy,
696                                      const int32_t max_dy,
697                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
698                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
699                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 772  Line 703 
703          int32_t iSAD;          int32_t iSAD;
704          int32_t dx,dy;          int32_t dx,dy;
705          VECTOR backupMV;          VECTOR backupMV;
706          backupMV.x = startx;  
707          backupMV.y = starty;          backupMV.x = start_x;
708            backupMV.y = start_y;
709    
710          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
711                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
# Line 782  Line 714 
714          return iMinSAD;          return iMinSAD;
715  }  }
716    
717  int32_t Full8_MainSearch(  int32_t
718                                          const uint8_t * const pRef,  AdvDiamond16_MainSearch(const uint8_t * const pRef,
719                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
720                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
721                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
722                                          const uint8_t * const cur,                                          const uint8_t * const cur,
723                                          const int x, const int y,                                                  const int x,
724                                          int32_t startx, int32_t starty,                                                  const int y,
725                                          int32_t iMinSAD,                                             int start_x,
726                                               int start_y,
727                                               int iMinSAD,
728                                          VECTOR * const currMV,                                          VECTOR * const currMV,
729                                          const VECTOR * const pmv,                                             const int center_x,
730                                          const int32_t min_dx, const int32_t max_dx,                                             const int center_y,
731                                          const int32_t min_dy, const int32_t max_dy,                                                  const int32_t min_dx,
732                                                    const int32_t max_dx,
733                                                    const int32_t min_dy,
734                                                    const int32_t max_dy,
735                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
736                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
737                                          const int32_t iFcode,                                          const int32_t iFcode,
738                                          const int32_t iQuant,                                          const int32_t iQuant,
739                                          int iFound)                                                  int iDirection)
740  {  {
741    
742          int32_t iSAD;          int32_t iSAD;
         int32_t dx,dy;  
         VECTOR backupMV;  
         backupMV.x = startx;  
         backupMV.y = starty;  
743    
744          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);  
745    
746          return iMinSAD;          if (iDirection) {
747  }                  CHECK_MV16_CANDIDATE(start_x - iDiamondSize, start_y);
748                    CHECK_MV16_CANDIDATE(start_x + iDiamondSize, start_y);
749                    CHECK_MV16_CANDIDATE(start_x, start_y - iDiamondSize);
750                    CHECK_MV16_CANDIDATE(start_x, start_y + iDiamondSize);
751            } else {
752                    int bDirection = 1 + 2 + 4 + 8;
753    
754                    do {
755                            iDirection = 0;
756                            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)
757                                    CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
758    
759                            if (bDirection & 2)
760                                    CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
761    
762  int32_t Halfpel16_Refine(                          if (bDirection & 4)
763          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) */  
764    
765          int32_t iSAD;                          if (bDirection & 8)
766          VECTOR backupMV = *currMV;                                  CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
767    
768          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);  
769    
770          return iMinSAD;                          if (iDirection)         //checking if anything found
771                            {
772                                    bDirection = iDirection;
773                                    iDirection = 0;
774                                    start_x = currMV->x;
775                                    start_y = currMV->y;
776                                    if (bDirection & 3)     //our candidate is left or right
777                                    {
778                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
779                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
780                                    } else                  // what remains here is up or down
781                                    {
782                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
783                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
784  }  }
785    
786  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)                                  if (iDirection) {
787                                            bDirection += iDirection;
788                                            start_x = currMV->x;
789  int32_t PMVfastSearch16(                                          start_y = currMV->y;
790                                          const uint8_t * const pRef,                                  }
791                                          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)  
792  {  {
793      const uint32_t iWcount = pParam->mb_width;                                  switch (bDirection) {
794          const int32_t iWidth = pParam->width;                                  case 2:
795          const int32_t iHeight = pParam->height;                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
796          const int32_t iEdgedWidth = pParam->edged_width;                                                                                           start_y - iDiamondSize, 2 + 4);
797                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
798                                                                                             start_y + iDiamondSize, 2 + 8);
799                                            break;
800                                    case 1:
801    
802                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
803                                                                                             start_y - iDiamondSize, 1 + 4);
804                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
805                                                                                             start_y + iDiamondSize, 1 + 8);
806                                            break;
807                                    case 2 + 4:
808                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
809                                                                                             start_y - iDiamondSize, 1 + 4);
810                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
811                                                                                             start_y - iDiamondSize, 2 + 4);
812                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
813                                                                                             start_y + iDiamondSize, 2 + 8);
814                                            break;
815                                    case 4:
816                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
817                                                                                             start_y - iDiamondSize, 2 + 4);
818                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
819                                                                                             start_y - iDiamondSize, 1 + 4);
820                                            break;
821                                    case 8:
822                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
823                                                                                             start_y + iDiamondSize, 2 + 8);
824                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
825                                                                                             start_y + iDiamondSize, 1 + 8);
826                                            break;
827                                    case 1 + 4:
828                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
829                                                                                             start_y + iDiamondSize, 1 + 8);
830                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
831                                                                                             start_y - iDiamondSize, 1 + 4);
832                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
833                                                                                             start_y - iDiamondSize, 2 + 4);
834                                            break;
835                                    case 2 + 8:
836                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
837                                                                                             start_y - iDiamondSize, 1 + 4);
838                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
839                                                                                             start_y + iDiamondSize, 1 + 8);
840                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
841                                                                                             start_y + iDiamondSize, 2 + 8);
842                                            break;
843                                    case 1 + 8:
844                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
845                                                                                             start_y - iDiamondSize, 2 + 4);
846                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
847                                                                                             start_y + iDiamondSize, 2 + 8);
848                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
849                                                                                             start_y + iDiamondSize, 1 + 8);
850                                            break;
851                                    default:                //1+2+4+8 == we didn't find anything at all
852                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
853                                                                                             start_y - iDiamondSize, 1 + 4);
854                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
855                                                                                             start_y + iDiamondSize, 1 + 8);
856                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
857                                                                                             start_y - iDiamondSize, 2 + 4);
858                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
859                                                                                             start_y + iDiamondSize, 2 + 8);
860                                            break;
861                                    }
862                                    if (!iDirection)
863                                            break;          //ok, the end. really
864                                    else {
865                                            bDirection = iDirection;
866                                            start_x = currMV->x;
867                                            start_y = currMV->y;
868                                    }
869                            }
870                    }
871                    while (1);                              //forever
872            }
873            return iMinSAD;
874    }
875    
876    
877    #define CHECK_MV16_F_INTERPOL(X,Y,BX,BY) { \
878      if ( ((X) <= max_dx) && ((X) >= min_dx) \
879        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
880      { \
881        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
882        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
883        if (iSAD < iMinSAD) \
884        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
885    }
886    
887    #define CHECK_MV16_F_INTERPOL_DIR(X,Y,BX,BY,D) { \
888      if ( ((X) <= max_dx) && ((X) >= min_dx) \
889        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
890      { \
891        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
892        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
893        if (iSAD < iMinSAD) \
894        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
895    }
896    
897    #define CHECK_MV16_F_INTERPOL_FOUND(X,Y,BX,BY,D) { \
898      if ( ((X) <= max_dx) && ((X) >= min_dx) \
899        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
900      { \
901        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
902        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
903        if (iSAD < iMinSAD) \
904        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
905    }
906    
907    
908    #define CHECK_MV16_B_INTERPOL(FX,FY,X,Y) { \
909      if ( ((X) <= max_dx) && ((X) >= min_dx) \
910        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
911      { \
912        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
913        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
914        if (iSAD < iMinSAD) \
915        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
916    }
917    
918    
919    #define CHECK_MV16_B_INTERPOL_DIR(FX,FY,X,Y,D) { \
920      if ( ((X) <= max_dx) && ((X) >= min_dx) \
921        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
922      { \
923        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
924        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
925        if (iSAD < iMinSAD) \
926        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
927    }
928    
929    
930    #define CHECK_MV16_B_INTERPOL_FOUND(FX,FY,X,Y,D) { \
931      if ( ((X) <= max_dx) && ((X) >= min_dx) \
932        && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
933      { \
934        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
935        iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
936        if (iSAD < iMinSAD) \
937        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
938    }
939    
940    
941    #if (0==1)
942    int32_t
943    Diamond16_InterpolMainSearch(
944                                            const uint8_t * const f_pRef,
945                                             const uint8_t * const f_pRefH,
946                                             const uint8_t * const f_pRefV,
947                                             const uint8_t * const f_pRefHV,
948                                             const uint8_t * const cur,
949    
950                                            const uint8_t * const b_pRef,
951                                             const uint8_t * const b_pRefH,
952                                             const uint8_t * const b_pRefV,
953                                             const uint8_t * const b_pRefHV,
954    
955                                             const int x,
956                                             const int y,
957    
958                                       const int f_start_x,
959                                       const int f_start_y,
960                                       const int b_start_x,
961                                       const int b_start_y,
962    
963                                       int iMinSAD,
964                                       VECTOR * const f_currMV,
965                                       VECTOR * const b_currMV,
966    
967                                       const int f_center_x,
968                                       const int f_center_y,
969                                       const int b_center_x,
970                                       const int b_center_y,
971    
972                                             const int32_t min_dx,
973                                             const int32_t max_dx,
974                                             const int32_t min_dy,
975                                             const int32_t max_dy,
976                                             const int32_t iEdgedWidth,
977                                             const int32_t iDiamondSize,
978    
979                                             const int32_t f_iFcode,
980                                             const int32_t b_iFcode,
981    
982                                             const int32_t iQuant,
983                                             int iFound)
984    {
985    /* Do a diamond search around given starting point, return SAD of best */
986    
987            int32_t f_iDirection = 0;
988            int32_t b_iDirection = 0;
989            int32_t iSAD;
990    
991            VECTOR f_backupMV;
992            VECTOR b_backupMV;
993    
994            f_backupMV.x = start_x;
995            f_backupMV.y = start_y;
996            b_backupMV.x = start_x;
997            b_backupMV.y = start_y;
998    
999    /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1000    
1001            CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1002            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1003            CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1004            CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1005    
1006            if (iDirection)
1007                    while (!iFound) {
1008                            iFound = 1;
1009                            backupMV = *currMV;
1010    
1011                            if (iDirection != 2)
1012                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1013                                                                                       backupMV.y, 1);
1014                            if (iDirection != 1)
1015                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1016                                                                                       backupMV.y, 2);
1017                            if (iDirection != 4)
1018                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
1019                                                                                       backupMV.y - iDiamondSize, 3);
1020                            if (iDirection != 3)
1021                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
1022                                                                                       backupMV.y + iDiamondSize, 4);
1023            } else {
1024                    currMV->x = start_x;
1025                    currMV->y = start_y;
1026            }
1027            return iMinSAD;
1028    }
1029    #endif
1030    
1031    
1032    int32_t
1033    AdvDiamond8_MainSearch(const uint8_t * const pRef,
1034                                               const uint8_t * const pRefH,
1035                                               const uint8_t * const pRefV,
1036                                               const uint8_t * const pRefHV,
1037                                               const uint8_t * const cur,
1038                                               const int x,
1039                                               const int y,
1040                                               int start_x,
1041                                               int start_y,
1042                                               int iMinSAD,
1043                                               VECTOR * const currMV,
1044                                               const int center_x,
1045                                               const int center_y,
1046                                               const int32_t min_dx,
1047                                               const int32_t max_dx,
1048                                               const int32_t min_dy,
1049                                               const int32_t max_dy,
1050                                               const int32_t iEdgedWidth,
1051                                               const int32_t iDiamondSize,
1052                                               const int32_t iFcode,
1053                                               const int32_t iQuant,
1054                                               int iDirection)
1055    {
1056    
1057            int32_t iSAD;
1058    
1059    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
1060    
1061            if (iDirection) {
1062                    CHECK_MV8_CANDIDATE(start_x - iDiamondSize, start_y);
1063                    CHECK_MV8_CANDIDATE(start_x + iDiamondSize, start_y);
1064                    CHECK_MV8_CANDIDATE(start_x, start_y - iDiamondSize);
1065                    CHECK_MV8_CANDIDATE(start_x, start_y + iDiamondSize);
1066            } else {
1067                    int bDirection = 1 + 2 + 4 + 8;
1068    
1069                    do {
1070                            iDirection = 0;
1071                            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)
1072                                    CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1073    
1074                            if (bDirection & 2)
1075                                    CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1076    
1077                            if (bDirection & 4)
1078                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1079    
1080                            if (bDirection & 8)
1081                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1082    
1083                            /* now we're doing diagonal checks near our candidate */
1084    
1085                            if (iDirection)         //checking if anything found
1086                            {
1087                                    bDirection = iDirection;
1088                                    iDirection = 0;
1089                                    start_x = currMV->x;
1090                                    start_y = currMV->y;
1091                                    if (bDirection & 3)     //our candidate is left or right
1092                                    {
1093                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1094                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1095                                    } else                  // what remains here is up or down
1096                                    {
1097                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1098                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1099                                    }
1100    
1101                                    if (iDirection) {
1102                                            bDirection += iDirection;
1103                                            start_x = currMV->x;
1104                                            start_y = currMV->y;
1105                                    }
1106                            } else                          //about to quit, eh? not so fast....
1107                            {
1108                                    switch (bDirection) {
1109                                    case 2:
1110                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1111                                                                                            start_y - iDiamondSize, 2 + 4);
1112                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1113                                                                                            start_y + iDiamondSize, 2 + 8);
1114                                            break;
1115                                    case 1:
1116                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1117                                                                                            start_y - iDiamondSize, 1 + 4);
1118                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1119                                                                                            start_y + iDiamondSize, 1 + 8);
1120                                            break;
1121                                    case 2 + 4:
1122                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1123                                                                                            start_y - iDiamondSize, 1 + 4);
1124                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1125                                                                                            start_y - iDiamondSize, 2 + 4);
1126                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1127                                                                                            start_y + iDiamondSize, 2 + 8);
1128                                            break;
1129                                    case 4:
1130                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1131                                                                                            start_y - iDiamondSize, 2 + 4);
1132                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1133                                                                                            start_y - iDiamondSize, 1 + 4);
1134                                            break;
1135                                    case 8:
1136                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1137                                                                                            start_y + iDiamondSize, 2 + 8);
1138                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1139                                                                                            start_y + iDiamondSize, 1 + 8);
1140                                            break;
1141                                    case 1 + 4:
1142                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1143                                                                                            start_y + iDiamondSize, 1 + 8);
1144                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1145                                                                                            start_y - iDiamondSize, 1 + 4);
1146                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1147                                                                                            start_y - iDiamondSize, 2 + 4);
1148                                            break;
1149                                    case 2 + 8:
1150                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1151                                                                                            start_y - iDiamondSize, 1 + 4);
1152                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1153                                                                                            start_y + iDiamondSize, 1 + 8);
1154                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1155                                                                                            start_y + iDiamondSize, 2 + 8);
1156                                            break;
1157                                    case 1 + 8:
1158                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1159                                                                                            start_y - iDiamondSize, 2 + 4);
1160                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1161                                                                                            start_y + iDiamondSize, 2 + 8);
1162                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1163                                                                                            start_y + iDiamondSize, 1 + 8);
1164                                            break;
1165                                    default:                //1+2+4+8 == we didn't find anything at all
1166                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1167                                                                                            start_y - iDiamondSize, 1 + 4);
1168                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1169                                                                                            start_y + iDiamondSize, 1 + 8);
1170                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1171                                                                                            start_y - iDiamondSize, 2 + 4);
1172                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1173                                                                                            start_y + iDiamondSize, 2 + 8);
1174                                            break;
1175                                    }
1176                                    if (!(iDirection))
1177                                            break;          //ok, the end. really
1178                                    else {
1179                                            bDirection = iDirection;
1180                                            start_x = currMV->x;
1181                                            start_y = currMV->y;
1182                                    }
1183                            }
1184                    }
1185                    while (1);                              //forever
1186            }
1187            return iMinSAD;
1188    }
1189    
1190    
1191    int32_t
1192    Full8_MainSearch(const uint8_t * const pRef,
1193                                     const uint8_t * const pRefH,
1194                                     const uint8_t * const pRefV,
1195                                     const uint8_t * const pRefHV,
1196                                     const uint8_t * const cur,
1197                                     const int x,
1198                                     const int y,
1199                               const int start_x,
1200                               const int start_y,
1201                               int iMinSAD,
1202                               VECTOR * const currMV,
1203                               const int center_x,
1204                               const int center_y,
1205                                     const int32_t min_dx,
1206                                     const int32_t max_dx,
1207                                     const int32_t min_dy,
1208                                     const int32_t max_dy,
1209                                     const int32_t iEdgedWidth,
1210                                     const int32_t iDiamondSize,
1211                                     const int32_t iFcode,
1212                                     const int32_t iQuant,
1213                                     int iFound)
1214    {
1215            int32_t iSAD;
1216            int32_t dx, dy;
1217            VECTOR backupMV;
1218    
1219            backupMV.x = start_x;
1220            backupMV.y = start_y;
1221    
1222            for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
1223                    for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
1224                            NOCHECK_MV8_CANDIDATE(dx, dy);
1225    
1226            return iMinSAD;
1227    }
1228    
1229    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1230    
1231    int32_t
1232    Halfpel16_Refine(const uint8_t * const pRef,
1233                                     const uint8_t * const pRefH,
1234                                     const uint8_t * const pRefV,
1235                                     const uint8_t * const pRefHV,
1236                                     const uint8_t * const cur,
1237                                     const int x,
1238                                     const int y,
1239                                     VECTOR * const currMV,
1240                                     int32_t iMinSAD,
1241                               const int center_x,
1242                               const int center_y,
1243                                     const int32_t min_dx,
1244                                     const int32_t max_dx,
1245                                     const int32_t min_dy,
1246                                     const int32_t max_dy,
1247                                     const int32_t iFcode,
1248                                     const int32_t iQuant,
1249                                     const int32_t iEdgedWidth)
1250    {
1251    /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
1252    
1253            int32_t iSAD;
1254            VECTOR backupMV = *currMV;
1255    
1256            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y - 1);
1257            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y - 1);
1258            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y - 1);
1259            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y);
1260            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y);
1261            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y + 1);
1262            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y + 1);
1263            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y + 1);
1264    
1265            return iMinSAD;
1266    }
1267    
1268    #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1269    
1270    
1271    
1272    int32_t
1273    PMVfastSearch16(const uint8_t * const pRef,
1274                                    const uint8_t * const pRefH,
1275                                    const uint8_t * const pRefV,
1276                                    const uint8_t * const pRefHV,
1277                                    const IMAGE * const pCur,
1278                                    const int x,
1279                                    const int y,
1280                                    const int start_x,
1281                                    const int start_y,
1282                                    const int center_x,
1283                                    const int center_y,
1284                                    const uint32_t MotionFlags,
1285                                    const uint32_t iQuant,
1286                                    const uint32_t iFcode,
1287                                    const MBParam * const pParam,
1288                                    const MACROBLOCK * const pMBs,
1289                                    const MACROBLOCK * const prevMBs,
1290                                    VECTOR * const currMV,
1291                                    VECTOR * const currPMV)
1292    {
1293            const uint32_t iWcount = pParam->mb_width;
1294            const int32_t iWidth = pParam->width;
1295            const int32_t iHeight = pParam->height;
1296            const int32_t iEdgedWidth = pParam->edged_width;
1297    
1298          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
1299    
# Line 890  Line 1312 
1312          VECTOR pmv[4];          VECTOR pmv[4];
1313          int32_t psad[4];          int32_t psad[4];
1314    
1315          const MACROBLOCK * const pMB = pMBs + x + y * iWcount;          MainSearch16FuncPtr MainSearchPtr;
1316    
1317          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
1318    
1319          static int32_t threshA,threshB;          int32_t threshA, threshB;
1320          int32_t bPredEq;          int32_t bPredEq;
1321          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1322    
1323  /* Get maximum range */  /* Get maximum range */
1324          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,
1325                    x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
1326    
1327  /* 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 */
1328    
1329          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
1330          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1331          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1332          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1333          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1334          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
   
1335    
1336          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1337            //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1338            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1339    
1340          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1341                  threshA =  512;                  threshA =  512;
1342                  threshB = 1024;                  threshB = 1024;
1343            } else {
         }  
         else  
         {  
1344                  threshA = psad[0];                  threshA = psad[0];
1345                  threshB = threshA+256;                  threshB = threshA+256;
1346                  if (threshA< 512) threshA =  512;                  if (threshA < 512)
1347                  if (threshA>1024) threshA = 1024;                          threshA = 512;
1348                  if (threshB>1792) threshB = 1792;                  if (threshA > 1024)
1349                            threshA = 1024;
1350                    if (threshB > 1792)
1351                            threshB = 1792;
1352          }          }
1353    
1354          iFound=0;          iFound=0;
1355    
 /* 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;  
   
1356  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1357     MinSAD=SAD     MinSAD=SAD
1358     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 957  Line 1360 
1360     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
1361  */  */
1362    
1363            currMV->x = start_x;
1364            currMV->y = start_y;
1365    
1366  // 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! */  
1367                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1368                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
1369          }          }
1370    
1371          if (currMV->x > max_dx)          if (currMV->x > max_dx) {
         {  
1372                  currMV->x=max_dx;                  currMV->x=max_dx;
1373          }          }
1374          if (currMV->x < min_dx)          if (currMV->x < min_dx) {
         {  
1375                  currMV->x=min_dx;                  currMV->x=min_dx;
1376          }          }
1377          if (currMV->y > max_dy)          if (currMV->y > max_dy) {
         {  
1378                  currMV->y=max_dy;                  currMV->y=max_dy;
1379          }          }
1380          if (currMV->y < min_dy)          if (currMV->y < min_dy) {
         {  
1381                  currMV->y=min_dy;                  currMV->y=min_dy;
1382          }          }
1383    
1384          iMinSAD = sad16( cur,          iMinSAD =
1385                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1386                           iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1387          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1388            iMinSAD +=
1389          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
1390          {                                            (uint8_t) iFcode, iQuant);
1391    
1392            if ((iMinSAD < 256) ||
1393                    ((MVequal(*currMV, prevMB->mvs[0])) &&
1394                     ((int32_t) iMinSAD < prevMB->sad16))) {
1395                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
1396                    {
1397                            if (!MVzero(*currMV)) {
1398                                    iMinSAD += MV16_00_BIAS;
1399                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
1400                                    iMinSAD -= MV16_00_BIAS;
1401                            }
1402                    }
1403    
1404                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1405                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
# Line 998  Line 1407 
1407                          goto PMVfast16_Terminate_with_Refine;                          goto PMVfast16_Terminate_with_Refine;
1408          }          }
1409    
1410    
1411    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1412       vector of the median.
1413       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1414    */
1415    
1416            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[0])))
1417                    iFound = 2;
1418    
1419    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1420       Otherwise select large Diamond Search.
1421    */
1422    
1423            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
1424                    iDiamondSize = 1;               // halfpel!
1425            else
1426                    iDiamondSize = 2;               // halfpel!
1427    
1428            if (!(MotionFlags & PMV_HALFPELDIAMOND16))
1429                    iDiamondSize *= 2;
1430    
1431  /*  /*
1432     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.
1433     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1434     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1435     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1436  */  */
1437    
1438  // (0,0) is always possible  // (0,0) is always possible
1439    
1440            if (!MVzero(pmv[0]))
1441          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1442    
1443  // previous frame MV is always possible  // previous frame MV is always possible
1444    
1445            if (!MVzero(prevMB->mvs[0]))
1446                    if (!MVequal(prevMB->mvs[0], pmv[0]))
1447          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y);
1448    
1449  // left neighbour, if allowed  // left neighbour, if allowed
1450          if (x != 0)  
1451          {          if (!MVzero(pmv[1]))
1452                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!MVequal(pmv[1], prevMB->mvs[0]))
1453                  {       pmv[1].x = EVEN(pmv[1].x);                          if (!MVequal(pmv[1], pmv[0])) {
1454                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1455                                            pmv[1].x = EVEN(pmv[1].x);
1456                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1457                  }                  }
1458    
1459                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1460          }          }
   
1461  // top neighbour, if allowed  // top neighbour, if allowed
1462          if (y != 0)          if (!MVzero(pmv[2]))
1463          {                  if (!MVequal(pmv[2], prevMB->mvs[0]))
1464                  if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!MVequal(pmv[2], pmv[0]))
1465                  {       pmv[2].x = EVEN(pmv[2].x);                                  if (!MVequal(pmv[2], pmv[1])) {
1466                                            if (!(MotionFlags & PMV_HALFPEL16)) {
1467                                                    pmv[2].x = EVEN(pmv[2].x);
1468                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
1469                  }                  }
1470                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1471    
1472  // top right neighbour, if allowed  // top right neighbour, if allowed
1473                  if ((uint32_t)x != (iWcount-1))                                          if (!MVzero(pmv[3]))
1474                  {                                                  if (!MVequal(pmv[3], prevMB->mvs[0]))
1475                          if (!(MotionFlags & PMV_HALFPEL16 ))                                                          if (!MVequal(pmv[3], pmv[0]))
1476                          {       pmv[3].x = EVEN(pmv[3].x);                                                                  if (!MVequal(pmv[3], pmv[1]))
1477                                                                            if (!MVequal(pmv[3], pmv[2])) {
1478                                                                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1479                                                                                            pmv[3].x = EVEN(pmv[3].x);
1480                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1481                          }                          }
1482                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                  CHECK_MV16_CANDIDATE(pmv[3].x,
1483                                                                                                                             pmv[3].y);
1484                  }                  }
1485          }          }
1486    
1487            if ((MVzero(*currMV)) &&
1488                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1489                    iMinSAD -= MV16_00_BIAS;
1490    
1491    
1492  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1493     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.
1494  */  */
1495    
1496          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[0]) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ((iMinSAD <= threshA) ||
1497          {                  (MVequal(*currMV, prevMB->mvs[0]) &&
1498                     ((int32_t) iMinSAD < prevMB->sad16))) {
1499                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1500                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
1501                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1065  Line 1513 
1513     Refine by using small diamond and goto step 10.     Refine by using small diamond and goto step 10.
1514  */  */
1515    
1516            if (MotionFlags & PMV_USESQUARES16)
1517                    MainSearchPtr = Square16_MainSearch;
1518            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
1519                    MainSearchPtr = AdvDiamond16_MainSearch;
1520            else
1521                    MainSearchPtr = Diamond16_MainSearch;
1522    
1523          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1524    
1525    
1526  /* 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 */
1527          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1528                                            x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1529                                            currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->x, currMV->y, iMinSAD, &newMV, center_x, center_y,
1530                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dx, max_dx,
1531                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1532                                                      iQuant, iFound);
1533    
1534          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1535                  *currMV = newMV;                  *currMV = newMV;
1536                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1537          }          }
1538    
1539          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
1540  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1541    
1542                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1543                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1544                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1545                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    center_x, center_y, iMinSAD, &newMV, center_x, center_y,
1546                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1547                                                                      iDiamondSize, iFcode, iQuant, iFound);
1548    
1549                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1550                          *currMV = newMV;                          *currMV = newMV;
1551                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1552                  }                  }
1553                  }                  }
1554    
1555                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1556                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1557                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1558                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y,
1559                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy,
1560                                                                      iEdgedWidth, iDiamondSize, iFcode,
1561                                                                      iQuant, iFound);
1562    
1563                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1564                          *currMV = newMV;                          *currMV = newMV;
1565                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1566                  }                  }
# Line 1116  Line 1573 
1573    
1574  PMVfast16_Terminate_with_Refine:  PMVfast16_Terminate_with_Refine:
1575          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1576                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1577                                    x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1578                                    currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1579                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1580    
1581  PMVfast16_Terminate_without_Refine:  PMVfast16_Terminate_without_Refine:
1582          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
1583          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
1584          return iMinSAD;          return iMinSAD;
1585  }  }
1586    
# Line 1132  Line 1589 
1589    
1590    
1591    
1592  int32_t Diamond8_MainSearch(  int32_t
1593          const uint8_t * const pRef,  Diamond8_MainSearch(const uint8_t * const pRef,
1594          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1595          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1596          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1597          const uint8_t * const cur,          const uint8_t * const cur,
1598          const int x, const int y,                                          const int x,
1599          int32_t startx, int32_t starty,                                          const int y,
1600                                            int32_t start_x,
1601                                            int32_t start_y,
1602          int32_t iMinSAD,          int32_t iMinSAD,
1603          VECTOR * const currMV,          VECTOR * const currMV,
1604          const VECTOR * const pmv,                                     const int center_x,
1605          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
1606          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
1607                                            const int32_t max_dx,
1608                                            const int32_t min_dy,
1609                                            const int32_t max_dy,
1610          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
1611          const int32_t iDiamondSize,          const int32_t iDiamondSize,
1612          const int32_t iFcode,          const int32_t iFcode,
# Line 1154  Line 1616 
1616  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
1617    
1618          int32_t iDirection=0;          int32_t iDirection=0;
1619            int32_t iDirectionBackup;
1620          int32_t iSAD;          int32_t iSAD;
1621          VECTOR backupMV;          VECTOR backupMV;
1622          backupMV.x = startx;  
1623          backupMV.y = starty;          backupMV.x = start_x;
1624            backupMV.y = start_y;
1625    
1626  /* 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 */
1627    
# Line 1166  Line 1630 
1630          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
1631          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1632    
1633          if (iDirection)          if (iDirection) {
1634                  while (!iFound)                  while (!iFound) {
                 {  
1635                          iFound = 1;                          iFound = 1;
1636                          backupMV=*currMV;       // since iDirection!=0, this is well defined!                          backupMV=*currMV;       // since iDirection!=0, this is well defined!
1637                            iDirectionBackup = iDirection;
1638    
1639                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
1640                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1641                          if ( iDirection != 1)                                                                                    backupMV.y, 1);
1642                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
1643                          if ( iDirection != 4)                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1644                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                    backupMV.y, 2);
1645                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
1646                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1647                                                                                      backupMV.y - iDiamondSize, 3);
1648                            if (iDirectionBackup != 3)
1649                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1650                                                                                      backupMV.y + iDiamondSize, 4);
1651                  }                  }
1652          else          } else {
1653          {                  currMV->x = start_x;
1654                  currMV->x = startx;                  currMV->y = start_y;
                 currMV->y = starty;  
1655          }          }
1656          return iMinSAD;          return iMinSAD;
1657  }  }
1658    
1659  int32_t Halfpel8_Refine(  int32_t
1660          const uint8_t * const pRef,  Halfpel8_Refine_c(const uint8_t * const pRef,
1661          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1662          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1663          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1664          const uint8_t * const cur,          const uint8_t * const cur,
1665          const int x, const int y,                                  const int x,
1666                                    const int y,
1667          VECTOR * const currMV,          VECTOR * const currMV,
1668          int32_t iMinSAD,          int32_t iMinSAD,
1669          const VECTOR * const pmv,                             const int center_x,
1670          const int32_t min_dx, const int32_t max_dx,                             const int center_y,
1671          const int32_t min_dy, const int32_t max_dy,                                  const int32_t min_dx,
1672                                    const int32_t max_dx,
1673                                    const int32_t min_dy,
1674                                    const int32_t max_dy,
1675          const int32_t iFcode,          const int32_t iFcode,
1676          const int32_t iQuant,          const int32_t iQuant,
1677          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 1225  Line 1696 
1696    
1697  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1698    
1699  int32_t PMVfastSearch8(  int32_t
1700                                          const uint8_t * const pRef,  PMVfastSearch8(const uint8_t * const pRef,
1701                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1702                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1703                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1704                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1705                                          const int x, const int y,                             const int x,
1706                                          const int start_x, const int start_y,                             const int y,
1707                               const int start_x,
1708                               const int start_y,
1709                                    const int center_x,
1710                                    const int center_y,
1711                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1712                                          const uint32_t iQuant,                                          const uint32_t iQuant,
1713                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1260  Line 1735 
1735          int32_t psad[4];          int32_t psad[4];
1736          VECTOR newMV;          VECTOR newMV;
1737          VECTOR backupMV;          VECTOR backupMV;
1738            VECTOR startMV;
1739    
1740          const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1741          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;
1742    
1743          static int32_t threshA,threshB;           int32_t threshA, threshB;
1744          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
1745          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1746    
1747          int32_t iSubBlock = ((y&1)<<1) + (x&1);          int32_t iSubBlock = (y & 1) + (y & 1) + (x & 1);
1748    
1749  /* Get maximum range */          MainSearch8FuncPtr MainSearchPtr;
         get_range(&min_dx, &max_dx, &min_dy, &max_dy,  
                   x, y, 8, iWidth, iHeight, iFcode);  
1750    
1751  /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */          /* Init variables */
1752            startMV.x = start_x;
1753            startMV.y = start_y;
1754    
1755          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          /* Get maximum range */
1756          { min_dx = EVEN(min_dx);          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
1757                              iFcode);
1758    
1759            if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
1760                    min_dx = EVEN(min_dx);
1761          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1762          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1763          max_dy = EVEN(max_dy);                  max_dy = EVEN(max_dy);
1764          }               /* 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;  
         }  
   
         iFound=0;  
   
 /* 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  
 */  
1765    
1766          if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[iSubBlock]) ) )          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
1767                  iFound=2;          //bPredEq = get_pmvdata(pMBs, (x >> 1), (y >> 1), iWcount, iSubBlock, pmv, psad);
1768            bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
1769    
1770  /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.          if ((x == 0) && (y == 0)) {
1771     Otherwise select large Diamond Search.                  threshA = 512 / 4;
1772  */                  threshB = 1024 / 4;
1773    
1774          if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536/4) || (bPredEq) )          } else {
1775                  iDiamondSize=1; // 1 halfpel!                  threshA = psad[0] / 4;  /* good estimate? */
1776          else                  threshB = threshA + 256 / 4;
1777                  iDiamondSize=2; // 2 halfpel = 1 full pixel!                  if (threshA < 512 / 4)
1778                            threshA = 512 / 4;
1779                    if (threshA > 1024 / 4)
1780                            threshA = 1024 / 4;
1781                    if (threshB > 1792 / 4)
1782                            threshB = 1792 / 4;
1783            }
1784    
1785          if (!(MotionFlags & PMV_HALFPELDIAMOND8) )          iFound = 0;
                 iDiamondSize*=2;  
1786    
1787  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1788     MinSAD=SAD     MinSAD=SAD
# Line 1333  Line 1794 
1794    
1795  // Prepare for main loop  // Prepare for main loop
1796    
1797          currMV->x=start_x;              /* start with mv16 */  //  if (MotionFlags & PMV_USESQUARES8)
1798          currMV->y=start_y;  //      MainSearchPtr = Square8_MainSearch;
1799    //  else
1800    
1801            if (MotionFlags & PMV_ADVANCEDDIAMOND8)
1802                    MainSearchPtr = AdvDiamond8_MainSearch;
1803            else
1804                    MainSearchPtr = Diamond8_MainSearch;
1805    
         iMinSAD = sad8( cur,  
                         get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),  
                         iEdgedWidth);  
         iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode) * iQuant;  
1806    
1807          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )          *currMV = startMV;
1808          {  
1809            iMinSAD =
1810                    sad8(cur,
1811                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
1812                                                    iEdgedWidth), iEdgedWidth);
1813            iMinSAD +=
1814                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
1815                                             (uint8_t) iFcode, iQuant);
1816    
1817            if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))
1818                                                                    && ((int32_t) iMinSAD <
1819                                                                            prevMB->sad8[iSubBlock]))) {
1820                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1821                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
1822                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
1823                          goto PMVfast8_Terminate_with_Refine;                          goto PMVfast8_Terminate_with_Refine;
1824          }          }
1825    
1826    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1827       vector of the median.
1828       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1829    */
1830    
1831            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[iSubBlock])))
1832                    iFound = 2;
1833    
1834    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1835       Otherwise select large Diamond Search.
1836    */
1837    
1838            if ((!MVzero(pmv[0])) || (threshB < 1536 / 4) || (bPredEq))
1839                    iDiamondSize = 1;               // 1 halfpel!
1840            else
1841                    iDiamondSize = 2;               // 2 halfpel = 1 full pixel!
1842    
1843            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
1844                    iDiamondSize *= 2;
1845    
1846    
1847  /*  /*
1848     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.
1849     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1850     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1851     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1852  */  */
1853    
1854  // 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);  
1855    
1856  // (0,0) is always possible          if (!MVequal(pmv[0], startMV))
1857                    CHECK_MV8_CANDIDATE(center_x, center_y);
1858    
1859    // (0,0) if needed
1860            if (!MVzero(pmv[0]))
1861                    if (!MVzero(startMV))
1862          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
1863    
1864  // previous frame MV is always possible  // previous frame MV if needed
1865          CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);          if (!MVzero(prevMB->mvs[iSubBlock]))
1866                    if (!MVequal(prevMB->mvs[iSubBlock], startMV))
1867                            if (!MVequal(prevMB->mvs[iSubBlock], pmv[0]))
1868                                    CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,
1869                                                                            prevMB->mvs[iSubBlock].y);
1870    
1871            if ((iMinSAD <= threshA) ||
1872                    (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
1873                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
1874                    if (MotionFlags & PMV_QUICKSTOP16)
1875                            goto PMVfast8_Terminate_without_Refine;
1876                    if (MotionFlags & PMV_EARLYSTOP16)
1877                            goto PMVfast8_Terminate_with_Refine;
1878            }
1879    
1880  // left neighbour, if allowed  // left neighbour, if allowed and needed
1881          if (psad[1] != MV_MAX_ERROR)          if (!MVzero(pmv[1]))
1882          {                  if (!MVequal(pmv[1], startMV))
1883                  if (!(MotionFlags & PMV_HALFPEL8 ))                          if (!MVequal(pmv[1], prevMB->mvs[iSubBlock]))
1884                  {       pmv[1].x = EVEN(pmv[1].x);                                  if (!MVequal(pmv[1], pmv[0])) {
1885                                            if (!(MotionFlags & PMV_HALFPEL8)) {
1886                                                    pmv[1].x = EVEN(pmv[1].x);
1887                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1888                  }                  }
1889                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1890          }          }
1891    // top neighbour, if allowed and needed
1892  // top neighbour, if allowed          if (!MVzero(pmv[2]))
1893          if (psad[2] != MV_MAX_ERROR)                  if (!MVequal(pmv[2], startMV))
1894          {                          if (!MVequal(pmv[2], prevMB->mvs[iSubBlock]))
1895                  if (!(MotionFlags & PMV_HALFPEL8 ))                                  if (!MVequal(pmv[2], pmv[0]))
1896                  {       pmv[2].x = EVEN(pmv[2].x);                                          if (!MVequal(pmv[2], pmv[1])) {
1897                                                    if (!(MotionFlags & PMV_HALFPEL8)) {
1898                                                            pmv[2].x = EVEN(pmv[2].x);
1899                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
1900                  }                  }
1901                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1902    
1903  // top right neighbour, if allowed  // top right neighbour, if allowed and needed
1904                  if (psad[3] != MV_MAX_ERROR)                                                  if (!MVzero(pmv[3]))
1905                  {                                                          if (!MVequal(pmv[3], startMV))
1906                          if (!(MotionFlags & PMV_HALFPEL8 ))                                                                  if (!MVequal(pmv[3], prevMB->mvs[iSubBlock]))
1907                          {       pmv[3].x = EVEN(pmv[3].x);                                                                          if (!MVequal(pmv[3], pmv[0]))
1908                                                                                    if (!MVequal(pmv[3], pmv[1]))
1909                                                                                            if (!MVequal(pmv[3], pmv[2])) {
1910                                                                                                    if (!
1911                                                                                                            (MotionFlags &
1912                                                                                                             PMV_HALFPEL8)) {
1913                                                                                                            pmv[3].x = EVEN(pmv[3].x);
1914                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1915                          }                          }
1916                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                                  CHECK_MV8_CANDIDATE(pmv[3].x,
1917                                                                                                                                            pmv[3].y);
1918                  }                  }
1919          }          }
1920    
1921            if ((MVzero(*currMV)) &&
1922                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1923                    iMinSAD -= MV8_00_BIAS;
1924    
1925    
1926  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1927     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.
1928  */  */
1929    
1930          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
1931          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
1932                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
1933                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1934                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
1935                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1421  Line 1949 
1949          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1950    
1951  /* 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 */
1952          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1953                                           x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
1954                                           currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
1955                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1956                                                      iQuant, iFound);
1957    
1958          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1959                  *currMV = newMV;                  *currMV = newMV;
1960                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1961          }          }
1962    
1963          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
1964  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1965    
1966                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1967                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1968                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1969                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
1970                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1971                                                                      iDiamondSize, iFcode, iQuant, iFound);
1972    
1973                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1974                          *currMV = newMV;                          *currMV = newMV;
1975                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1976                  }                  }
1977                  }                  }
1978    
1979                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1980                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1981                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1982                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
1983                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
1984                                                                      iQuant, iFound);
1985    
1986                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1987                          *currMV = newMV;                          *currMV = newMV;
1988                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1989                  }                  }
# Line 1469  Line 1996 
1996    
1997  PMVfast8_Terminate_with_Refine:  PMVfast8_Terminate_with_Refine:
1998          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
1999                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2000                                                   x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2001                                                   currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2002                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2003    
2004    
2005  PMVfast8_Terminate_without_Refine:  PMVfast8_Terminate_without_Refine:
2006          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2007          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2008    
2009          return iMinSAD;          return iMinSAD;
2010  }  }
2011    
2012  int32_t EPZSSearch16(  int32_t
2013                                          const uint8_t * const pRef,  EPZSSearch16(const uint8_t * const pRef,
2014                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2015                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2016                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2017                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2018                                          const int x, const int y,                           const int x,
2019                             const int y,
2020                            const int start_x,
2021                            const int start_y,
2022                            const int center_x,
2023                            const int center_y,
2024                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2025                                          const uint32_t iQuant,                                          const uint32_t iQuant,
2026                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1519  Line 2051 
2051          int32_t psad[8];          int32_t psad[8];
2052    
2053          static MACROBLOCK * oldMBs = NULL;          static MACROBLOCK * oldMBs = NULL;
2054          const MACROBLOCK * const pMB = pMBs + x + y * iWcount;  
2055    //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
2056          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK * const prevMB = prevMBs + x + y * iWcount;
2057          MACROBLOCK * oldMB = NULL;          MACROBLOCK * oldMB = NULL;
2058    
2059          static int32_t thresh2;           int32_t thresh2;
2060          int32_t bPredEq;          int32_t bPredEq;
2061          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2062    
2063          MainSearch16FuncPtr EPZSMainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
2064    
2065          if (oldMBs == NULL)          if (oldMBs == NULL) {
2066          {       oldMBs = (MACROBLOCK*) calloc(1,iWcount*iHcount*sizeof(MACROBLOCK));                  oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
2067                  fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));  //      fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
2068          }          }
2069          oldMB = oldMBs + x + y * iWcount;          oldMB = oldMBs + x + y * iWcount;
2070    
2071  /* Get maximum range */  /* Get maximum range */
2072          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,
2073                          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 */  
2074    
2075          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
2076          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2077            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2078            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2079            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2080          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2081            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2082          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
2083            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2084    
2085  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2086          MinSAD=SAD          MinSAD=SAD
# Line 1559  Line 2091 
2091    
2092  // Prepare for main loop  // Prepare for main loop
2093    
2094          *currMV=pmv[0];         /* current best := median prediction */          currMV->x = start_x;
2095          if (!(MotionFlags & PMV_HALFPEL16))          currMV->y = start_y;
2096          {  
2097            if (!(MotionFlags & PMV_HALFPEL16)) {
2098                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2099                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2100          }          }
# Line 1577  Line 2110 
2110    
2111  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2112    
2113          iMinSAD = sad16( cur,          iMinSAD =
2114                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
2115                  iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2116          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2117            iMinSAD +=
2118                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2119                                              (uint8_t) iFcode, iQuant);
2120    
2121  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2122          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) )          if ((iMinSAD < 256) ||
2123                  {                  ((MVequal(*currMV, prevMB->mvs[0])) &&
2124                     ((int32_t) iMinSAD < prevMB->sad16))) {
2125                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2126                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2127                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1594  Line 2131 
2131  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2132    
2133  // previous frame MV  // previous frame MV
2134          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
2135    
2136  // set threshhold based on Min of Prediction and SAD of collocated block  // set threshhold based on Min of Prediction and SAD of collocated block
2137  // 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
2138    
2139          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
2140                  thresh2 =  512;                  thresh2 =  512;
2141          }          } else {
         else  
         {  
2142  /* 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] */
2143    
2144                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
# Line 1616  Line 2150 
2150    
2151    
2152  // left neighbour, if allowed  // left neighbour, if allowed
2153          if (x != 0)          if (x != 0) {
2154          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2155                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2156                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2157                  }                  }
2158                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
2159          }          }
   
2160  // top neighbour, if allowed  // top neighbour, if allowed
2161          if (y != 0)          if (y != 0) {
2162          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2163                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2164                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2165                  }                  }
2166                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
2167    
2168  // top right neighbour, if allowed  // top right neighbour, if allowed
2169                  if ((uint32_t)x != (iWcount-1))                  if ((uint32_t) x != (iWcount - 1)) {
2170                  {                          if (!(MotionFlags & PMV_HALFPEL16)) {
2171                          if (!(MotionFlags & PMV_HALFPEL16 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2172                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2173                          }                          }
2174                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
# Line 1650  Line 2180 
2180  */  */
2181    
2182          if ( (iMinSAD <= thresh2)          if ( (iMinSAD <= thresh2)
2183                  || ( MVequal(*currMV,pMB->mvs[0]) && ((uint32_t)iMinSAD <= prevMB->sad16) ) )                  || (MVequal(*currMV, prevMB->mvs[0]) &&
2184                  {                          ((int32_t) iMinSAD <= prevMB->sad16))) {
2185                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2186                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2187                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1660  Line 2190 
2190    
2191  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
2192    
2193          backupMV = pMB->mvs[0];                 // last MV          backupMV = prevMB->mvs[0];      // collocated MV
2194          backupMV.x += (pMB->mvs[0].x - oldMB->mvs[0].x );       // acceleration X          backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x);     // acceleration X
2195          backupMV.y += (pMB->mvs[0].y - oldMB->mvs[0].y );       // acceleration Y          backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y);     // acceleration Y
2196    
2197          CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);          CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);
2198    
2199  // left neighbour  // left neighbour
2200          if (x != 0)          if (x != 0)
2201                  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);
2202    
2203    // top neighbour
2204            if (y != 0)
2205                    CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,
2206                                                             (prevMB - iWcount)->mvs[0].y);
2207    
2208    // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
2209    
2210            if ((uint32_t) x != iWcount - 1)
2211                    CHECK_MV16_CANDIDATE((prevMB + 1)->mvs[0].x, (prevMB + 1)->mvs[0].y);
2212    
2213    // bottom neighbour, dito
2214            if ((uint32_t) y != iHcount - 1)
2215                    CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,
2216                                                             (prevMB + iWcount)->mvs[0].y);
2217    
2218    /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
2219            if (iMinSAD <= thresh2) {
2220                    if (MotionFlags & PMV_QUICKSTOP16)
2221                            goto EPZS16_Terminate_without_Refine;
2222                    if (MotionFlags & PMV_EARLYSTOP16)
2223                            goto EPZS16_Terminate_with_Refine;
2224            }
2225    
2226    /************ (if Diamond Search)  **************/
2227    
2228            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2229    
2230            if (MotionFlags & PMV_USESQUARES16)
2231                    MainSearchPtr = Square16_MainSearch;
2232            else
2233             if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2234                    MainSearchPtr = AdvDiamond16_MainSearch;
2235            else
2236                    MainSearchPtr = Diamond16_MainSearch;
2237    
2238    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2239    
2240            iSAD =
2241                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2242                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2243                                                      min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2244    
2245            if (iSAD < iMinSAD) {
2246                    *currMV = newMV;
2247                    iMinSAD = iSAD;
2248            }
2249    
2250    
2251            if (MotionFlags & PMV_EXTSEARCH16) {
2252    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2253    
2254                    if (!(MVequal(pmv[0], backupMV))) {
2255                            iSAD =
2256                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2257                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2258                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2259                                                                      2, iFcode, iQuant, 0);
2260                    }
2261    
2262                    if (iSAD < iMinSAD) {
2263                            *currMV = newMV;
2264                            iMinSAD = iSAD;
2265                    }
2266    
2267                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2268                            iSAD =
2269                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2270                                                                      iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2271                                                                      max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2272    
2273                            if (iSAD < iMinSAD) {
2274                                    *currMV = newMV;
2275                                    iMinSAD = iSAD;
2276                            }
2277                    }
2278            }
2279    
2280    /***************        Choose best MV found     **************/
2281    
2282      EPZS16_Terminate_with_Refine:
2283            if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
2284                    iMinSAD =
2285                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2286                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2287                                                             iFcode, iQuant, iEdgedWidth);
2288    
2289      EPZS16_Terminate_without_Refine:
2290    
2291            *oldMB = *prevMB;
2292    
2293            currPMV->x = currMV->x - center_x;
2294            currPMV->y = currMV->y - center_y;
2295            return iMinSAD;
2296    }
2297    
2298    
2299    int32_t
2300    EPZSSearch8(const uint8_t * const pRef,
2301                            const uint8_t * const pRefH,
2302                            const uint8_t * const pRefV,
2303                            const uint8_t * const pRefHV,
2304                            const IMAGE * const pCur,
2305                            const int x,
2306                            const int y,
2307                            const int start_x,
2308                            const int start_y,
2309                            const int center_x,
2310                            const int center_y,
2311                            const uint32_t MotionFlags,
2312                            const uint32_t iQuant,
2313                            const uint32_t iFcode,
2314                            const MBParam * const pParam,
2315                            const MACROBLOCK * const pMBs,
2316                            const MACROBLOCK * const prevMBs,
2317                            VECTOR * const currMV,
2318                            VECTOR * const currPMV)
2319    {
2320    /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
2321    
2322            const uint32_t iWcount = pParam->mb_width;
2323            const int32_t iWidth = pParam->width;
2324            const int32_t iHeight = pParam->height;
2325            const int32_t iEdgedWidth = pParam->edged_width;
2326    
2327            const uint8_t *cur = pCur->y + x * 8 + y * 8 * iEdgedWidth;
2328    
2329            int32_t iDiamondSize = 1;
2330    
2331            int32_t min_dx;
2332            int32_t max_dx;
2333            int32_t min_dy;
2334            int32_t max_dy;
2335    
2336            VECTOR newMV;
2337            VECTOR backupMV;
2338    
2339            VECTOR pmv[4];
2340            int32_t psad[8];
2341    
2342            const int32_t iSubBlock = ((y & 1) << 1) + (x & 1);
2343    
2344    //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2345            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
2346    
2347            int32_t bPredEq;
2348            int32_t iMinSAD, iSAD = 9999;
2349    
2350            MainSearch8FuncPtr MainSearchPtr;
2351    
2352    /* Get maximum range */
2353            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2354                              iFcode);
2355    
2356    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2357    
2358            if (!(MotionFlags & PMV_HALFPEL8)) {
2359                    min_dx = EVEN(min_dx);
2360                    max_dx = EVEN(max_dx);
2361                    min_dy = EVEN(min_dy);
2362                    max_dy = EVEN(max_dy);
2363            }
2364            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2365            //bPredEq = get_pmvdata(pMBs, x >> 1, y >> 1, iWcount, iSubBlock, pmv[0].x, pmv[0].y, psad);
2366            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2367    
2368    
2369    /* Step 4: Calculate SAD around the Median prediction.
2370            MinSAD=SAD
2371            If Motion Vector equal to Previous frame motion vector
2372                    and MinSAD<PrevFrmSAD goto Step 10.
2373            If SAD<=256 goto Step 10.
2374    */
2375    
2376    // Prepare for main loop
2377    
2378    
2379            if (!(MotionFlags & PMV_HALFPEL8)) {
2380                    currMV->x = EVEN(currMV->x);
2381                    currMV->y = EVEN(currMV->y);
2382            }
2383    
2384            if (currMV->x > max_dx)
2385                    currMV->x = max_dx;
2386            if (currMV->x < min_dx)
2387                    currMV->x = min_dx;
2388            if (currMV->y > max_dy)
2389                    currMV->y = max_dy;
2390            if (currMV->y < min_dy)
2391                    currMV->y = min_dy;
2392    
2393    /***************** This is predictor SET A: only median prediction ******************/
2394    
2395    
2396            iMinSAD =
2397                    sad8(cur,
2398                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2399                                                    iEdgedWidth), iEdgedWidth);
2400            iMinSAD +=
2401                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2402                                             (uint8_t) iFcode, iQuant);
2403    
2404    
2405    // thresh1 is fixed to 256
2406            if (iMinSAD < 256 / 4) {
2407                    if (MotionFlags & PMV_QUICKSTOP8)
2408                            goto EPZS8_Terminate_without_Refine;
2409                    if (MotionFlags & PMV_EARLYSTOP8)
2410                            goto EPZS8_Terminate_with_Refine;
2411            }
2412    
2413    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2414    
2415    
2416    // MV=(0,0) is often a good choice
2417            CHECK_MV8_ZERO;
2418    
2419    // previous frame MV
2420            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x, prevMB->mvs[iSubBlock].y);
2421    
2422    // left neighbour, if allowed
2423            if (psad[1] != MV_MAX_ERROR) {
2424                    if (!(MotionFlags & PMV_HALFPEL8)) {
2425                            pmv[1].x = EVEN(pmv[1].x);
2426                            pmv[1].y = EVEN(pmv[1].y);
2427                    }
2428                    CHECK_MV8_CANDIDATE(pmv[1].x, pmv[1].y);
2429            }
2430    // top neighbour, if allowed
2431            if (psad[2] != MV_MAX_ERROR) {
2432                    if (!(MotionFlags & PMV_HALFPEL8)) {
2433                            pmv[2].x = EVEN(pmv[2].x);
2434                            pmv[2].y = EVEN(pmv[2].y);
2435                    }
2436                    CHECK_MV8_CANDIDATE(pmv[2].x, pmv[2].y);
2437    
2438    // top right neighbour, if allowed
2439                    if (psad[3] != MV_MAX_ERROR) {
2440                            if (!(MotionFlags & PMV_HALFPEL8)) {
2441                                    pmv[3].x = EVEN(pmv[3].x);
2442                                    pmv[3].y = EVEN(pmv[3].y);
2443                            }
2444                            CHECK_MV8_CANDIDATE(pmv[3].x, pmv[3].y);
2445                    }
2446            }
2447    
2448  // 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);  
2449    
2450  // 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)
2451                    iMinSAD -= MV8_00_BIAS;
2452    
2453          if ((uint32_t)x != iWcount-1)  */
                 CHECK_MV16_CANDIDATE((pMB+1)->mvs[0].x,oldMB->mvs[0].y);  
2454    
2455  // bottom neighbour, dito  /* Terminate if MinSAD <= T_2
2456          if ((uint32_t)y != iHcount-1)     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
2457                  CHECK_MV16_CANDIDATE((pMB+iWcount)->mvs[0].x,oldMB->mvs[0].y);  */
2458    
2459  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */          if (iMinSAD < 512 / 4) {        /* T_2 == 512/4 hardcoded */
2460          if (iMinSAD <= thresh2)                  if (MotionFlags & PMV_QUICKSTOP8)
2461                  {                          goto EPZS8_Terminate_without_Refine;
2462                          if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_EARLYSTOP8)
2463                                  goto EPZS16_Terminate_without_Refine;                          goto EPZS8_Terminate_with_Refine;
                         if (MotionFlags & PMV_EARLYSTOP16)  
                                 goto EPZS16_Terminate_with_Refine;  
2464                  }                  }
2465    
2466  /************ (if Diamond Search)  **************/  /************ (Diamond Search)  **************/
2467    
2468          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2469    
2470  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */          if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2471                    iDiamondSize *= 2;
2472    
2473          if (MotionFlags & PMV_USESQUARES16)  /* default: use best prediction as starting point for one call of EPZS_MainSearch */
2474                  EPZSMainSearchPtr = Square16_MainSearch;  
2475    // there is no EPZS^2 for inter4v at the moment
2476    
2477    //  if (MotionFlags & PMV_USESQUARES8)
2478    //      MainSearchPtr = Square8_MainSearch;
2479    //  else
2480    
2481            if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2482                    MainSearchPtr = AdvDiamond8_MainSearch;
2483          else          else
2484                  EPZSMainSearchPtr = Diamond16_MainSearch;                  MainSearchPtr = Diamond8_MainSearch;
2485    
2486          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2487                          x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2488                          currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2489                          2, iFcode, iQuant, 0);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2490                                                      iQuant, 0);
2491    
2492          if (iSAD < iMinSAD)  
2493          {          if (iSAD < iMinSAD) {
2494                  *currMV = newMV;                  *currMV = newMV;
2495                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2496          }          }
2497    
2498            if (MotionFlags & PMV_EXTSEARCH8) {
         if (MotionFlags & PMV_EXTSEARCH16)  
         {  
2499  /* 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) */
2500    
2501                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2502                  {                          iSAD =
2503                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2504                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2505                                  pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2506                                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, 0);
                 }  
2507    
2508                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2509                          *currMV = newMV;                          *currMV = newMV;
2510                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2511                  }                  }
2512                    }
2513    
2514                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2515                  {                          iSAD =
2516                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2517                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2518                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2519                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, /*iDiamondSize*/ 2, iFcode, iQuant, 0);                                                                    iQuant, 0);
2520    
2521                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2522                                  *currMV = newMV;                                  *currMV = newMV;
2523                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2524                          }                          }
# Line 1750  Line 2527 
2527    
2528  /***************        Choose best MV found     **************/  /***************        Choose best MV found     **************/
2529    
2530  EPZS16_Terminate_with_Refine:    EPZS8_Terminate_with_Refine:
2531          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step
2532                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2533                                  x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2534                                  currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2535                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
   
 EPZS16_Terminate_without_Refine:  
2536    
2537          *oldMB = *pMB;    EPZS8_Terminate_without_Refine:
2538    
2539          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2540          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2541          return iMinSAD;          return iMinSAD;
2542  }  }
2543    
2544    
2545  int32_t EPZSSearch8(  
2546                                          const uint8_t * const pRef,  int32_t
2547    PMVfastIntSearch16(const uint8_t * const pRef,
2548                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2549                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2550                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2551                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2552                                          const int x, const int y,                                  const int x,
2553                                          const int start_x, const int start_y,                                  const int y,
2554                            const int start_x,
2555                            const int start_y,
2556                            const int center_x,
2557                            const int center_y,
2558                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2559                                          const uint32_t iQuant,                                          const uint32_t iQuant,
2560                                          const uint32_t iFcode,                                          const uint32_t iFcode,
# Line 1789  Line 2569 
2569          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
2570          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
2571    
2572          const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;          const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
2573            const VECTOR zeroMV = { 0, 0 };
2574    
2575          int32_t iDiamondSize=1;          int32_t iDiamondSize;
2576    
2577          int32_t min_dx;          int32_t min_dx;
2578          int32_t max_dx;          int32_t max_dx;
2579          int32_t min_dy;          int32_t min_dy;
2580          int32_t max_dy;          int32_t max_dy;
2581    
2582            int32_t iFound;
2583    
2584          VECTOR newMV;          VECTOR newMV;
2585          VECTOR backupMV;          VECTOR backupMV;                        /* just for PMVFAST */
2586    
2587          VECTOR pmv[4];          VECTOR pmv[4];
2588          int32_t psad[8];          int32_t psad[4];
2589    
2590          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);          MainSearch16FuncPtr MainSearchPtr;
2591    
2592          const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2593          const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount;          MACROBLOCK *const pMB = pMBs + x + y * iWcount;
2594    
2595            int32_t threshA, threshB;
2596          int32_t bPredEq;          int32_t bPredEq;
2597          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD, iSAD;
2598    
         MainSearch8FuncPtr EPZSMainSearchPtr;  
2599    
2600  /* Get maximum range */  /* Get maximum range */
2601          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,
2602                          x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2603    
2604  /* 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 */
2605    
2606          if (!(MotionFlags & PMV_HALFPEL8 ))          if ((x == 0) && (y == 0)) {
2607          { min_dx = EVEN(min_dx);                  threshA = 512;
2608            max_dx = EVEN(max_dx);                  threshB = 1024;
2609            min_dy = EVEN(min_dy);  
2610            max_dy = EVEN(max_dy);                  bPredEq = 0;
2611          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */                  psad[0] = psad[1] = psad[2] = psad[3] = 0;
2612                    *currMV = pmv[0] = pmv[1] = pmv[2] = pmv[3] = zeroMV;
2613    
2614            } else {
2615                    threshA = psad[0];
2616                    threshB = threshA + 256;
2617                    if (threshA < 512)
2618                            threshA = 512;
2619                    if (threshA > 1024)
2620                            threshA = 1024;
2621                    if (threshB > 1792)
2622                            threshB = 1792;
2623    
2624          bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);                  bPredEq = get_ipmvdata(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2625                    *currMV = pmv[0];                       /* current best := prediction */
2626            }
2627    
2628            iFound = 0;
2629    
2630  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2631          MinSAD=SAD          MinSAD=SAD
# Line 1837  Line 2634 
2634          If SAD<=256 goto Step 10.          If SAD<=256 goto Step 10.
2635  */  */
2636    
2637  // Prepare for main loop          if (currMV->x > max_dx) {
2638                    currMV->x = EVEN(max_dx);
2639            }
2640            if (currMV->x < min_dx) {
2641                    currMV->x = EVEN(min_dx);
2642            }
2643            if (currMV->y > max_dy) {
2644                    currMV->y = EVEN(max_dy);
2645            }
2646            if (currMV->y < min_dy) {
2647                    currMV->y = EVEN(min_dy);
2648            }
2649    
2650            iMinSAD =
2651                    sad16(cur,
2652                              get_iref_mv(pRef, x, y, 16, currMV,
2653                                                     iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2654            iMinSAD +=
2655                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2656                                              (uint8_t) iFcode, iQuant);
2657    
2658            if ((iMinSAD < 256) ||
2659                    ((MVequal(*currMV, prevMB->i_mvs[0])) &&
2660                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2661                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
2662                    {
2663                            if (!MVzero(*currMV)) {
2664                                    iMinSAD += MV16_00_BIAS;
2665                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
2666                                    iMinSAD -= MV16_00_BIAS;
2667                            }
2668                    }
2669    
2670          if (!(MotionFlags & PMV_HALFPEL8))                  if (MotionFlags & PMV_EARLYSTOP16)
2671          {                          goto PMVfastInt16_Terminate_with_Refine;
                 currMV->x = EVEN(currMV->x);  
                 currMV->y = EVEN(currMV->y);  
2672          }          }
2673    
         if (currMV->x > max_dx)  
                 currMV->x=max_dx;  
         if (currMV->x < min_dx)  
                 currMV->x=min_dx;  
         if (currMV->y > max_dy)  
                 currMV->y=max_dy;  
         if (currMV->y < min_dy)  
                 currMV->y=min_dy;  
2674    
2675  /***************** This is predictor SET A: only median prediction ******************/  /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2676       vector of the median.
2677       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2678    */
2679    
2680            if ((bPredEq) && (MVequal(pmv[0], prevMB->i_mvs[0])))
2681                    iFound = 2;
2682    
2683          iMinSAD = sad8( cur,  /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2684                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),     Otherwise select large Diamond Search.
2685                  iEdgedWidth);  */
         iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;  
2686    
2687            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
2688                    iDiamondSize = 2;               // halfpel units!
2689            else
2690                    iDiamondSize = 4;               // halfpel units!
2691    
2692  // thresh1 is fixed to 256  /*
2693          if (iMinSAD < 256/4 )     Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
2694                  {     Also calculate (0,0) but do not subtract offset.
2695                          if (MotionFlags & PMV_QUICKSTOP8)     Let MinSAD be the smallest SAD up to this point.
2696                                  goto EPZS8_Terminate_without_Refine;     If MV is (0,0) subtract offset.
2697                          if (MotionFlags & PMV_EARLYSTOP8)  */
                                 goto EPZS8_Terminate_with_Refine;  
                 }  
2698    
2699  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  // (0,0) is often a good choice
2700    
2701  // previous frame MV          if (!MVzero(pmv[0]))
2702          CHECK_MV8_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);                  CHECK_MV16_ZERO;
2703    
2704  // MV=(0,0) is often a good choice  // previous frame MV is always possible
2705    
2706          CHECK_MV8_ZERO;          if (!MVzero(prevMB->i_mvs[0]))
2707                    if (!MVequal(prevMB->i_mvs[0], pmv[0]))
2708                            CHECK_MV16_CANDIDATE(prevMB->i_mvs[0].x, prevMB->i_mvs[0].y);
2709    
2710  /* Terminate if MinSAD <= T_2  // left neighbour, if allowed
2711     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]  
2712            if (!MVzero(pmv[1]))
2713                    if (!MVequal(pmv[1], prevMB->i_mvs[0]))
2714                            if (!MVequal(pmv[1], pmv[0]))
2715                                    CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
2716    
2717    // top neighbour, if allowed
2718            if (!MVzero(pmv[2]))
2719                    if (!MVequal(pmv[2], prevMB->i_mvs[0]))
2720                            if (!MVequal(pmv[2], pmv[0]))
2721                                    if (!MVequal(pmv[2], pmv[1]))
2722                                            CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
2723    
2724    // top right neighbour, if allowed
2725                                            if (!MVzero(pmv[3]))
2726                                                    if (!MVequal(pmv[3], prevMB->i_mvs[0]))
2727                                                            if (!MVequal(pmv[3], pmv[0]))
2728                                                                    if (!MVequal(pmv[3], pmv[1]))
2729                                                                            if (!MVequal(pmv[3], pmv[2]))
2730                                                                                    CHECK_MV16_CANDIDATE(pmv[3].x,
2731                                                                                                                             pmv[3].y);
2732    
2733            if ((MVzero(*currMV)) &&
2734                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2735                    iMinSAD -= MV16_00_BIAS;
2736    
2737    
2738    /* Step 6: If MinSAD <= thresa goto Step 10.
2739       If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
2740  */  */
2741    
2742          if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */          if ((iMinSAD <= threshA) ||
2743                  {                  (MVequal(*currMV, prevMB->i_mvs[0]) &&
2744                          if (MotionFlags & PMV_QUICKSTOP8)                   ((int32_t) iMinSAD < prevMB->i_sad16))) {
                                 goto EPZS8_Terminate_without_Refine;  
                         if (MotionFlags & PMV_EARLYSTOP8)  
                                 goto EPZS8_Terminate_with_Refine;  
                 }  
2745    
2746  /************ (if Diamond Search)  **************/                  if (MotionFlags & PMV_EARLYSTOP16)
2747                            goto PMVfastInt16_Terminate_with_Refine;
2748            }
2749    
         backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */  
2750    
2751          if (!(MotionFlags & PMV_HALFPELDIAMOND8))  /************ (Diamond Search)  **************/
2752                  iDiamondSize *= 2;  /*
2753       Step 7: Perform Diamond search, with either the small or large diamond.
2754       If Found=2 only examine one Diamond pattern, and afterwards goto step 10
2755       Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
2756       If center then goto step 10.
2757       Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
2758       Refine by using small diamond and goto step 10.
2759    */
2760    
2761  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */          if (MotionFlags & PMV_USESQUARES16)
2762                    MainSearchPtr = Square16_MainSearch;
2763            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2764                    MainSearchPtr = AdvDiamond16_MainSearch;
2765            else
2766                    MainSearchPtr = Diamond16_MainSearch;
2767    
2768  //      if (MotionFlags & PMV_USESQUARES8)          backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
 //              EPZSMainSearchPtr = Square8_MainSearch;  
 //      else  
                 EPZSMainSearchPtr = Diamond8_MainSearch;  
2769    
         iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,  
                 x, y,  
                 currMV->x, currMV->y, iMinSAD, &newMV,  
                 pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,  
                 iDiamondSize, iFcode, iQuant, 00);  
2770    
2771    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2772            iSAD =
2773                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2774                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2775                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2776                                                      iQuant, iFound);
2777    
2778          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2779                  *currMV = newMV;                  *currMV = newMV;
2780                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2781          }          }
2782    
2783          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH16) {
2784          {  /* extended: search (up to) two more times: orignal prediction and (0,0) */
 /* extended mode: search (up to) two more times: orignal prediction and (0,0) */  
2785    
2786                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2787                  {                          iSAD =
2788                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2789                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2790                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2791                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, iFound);
2792    
2793                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2794                                  *currMV = newMV;                                  *currMV = newMV;
2795                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2796                          }                          }
2797                  }                  }
2798    
2799                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2800                  {                          iSAD =
2801                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2802                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2803                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2804                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iQuant, iFound);
2805    
2806                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2807                                  *currMV = newMV;                                  *currMV = newMV;
2808                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2809                          }                          }
2810                  }                  }
2811          }          }
2812    
2813  /***************        Choose best MV found     **************/  /*
2814       Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.
2815    */
2816    
2817  EPZS8_Terminate_with_Refine:  PMVfastInt16_Terminate_with_Refine:
         if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step  
                 iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,  
                                 x, y,  
                                 currMV, iMinSAD,  
                                 pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);  
2818    
2819  EPZS8_Terminate_without_Refine:          pMB->i_mvs[0] = pMB->i_mvs[1] = pMB->i_mvs[2] = pMB->i_mvs[3] = pMB->i_mv16 = *currMV;
2820            pMB->i_sad8[0] = pMB->i_sad8[1] = pMB->i_sad8[2] = pMB->i_sad8[3] = pMB->i_sad16 = iMinSAD;
2821    
2822          currPMV->x = currMV->x - pmv[0].x;          if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
2823          currPMV->y = currMV->y - pmv[0].y;                  iMinSAD =
2824                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2825                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2826                                                             iFcode, iQuant, iEdgedWidth);
2827    
2828            pmv[0] = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          // get _REAL_ prediction (halfpel possible)
2829    
2830    PMVfastInt16_Terminate_without_Refine:
2831            currPMV->x = currMV->x - center_x;
2832            currPMV->y = currMV->y - center_y;
2833          return iMinSAD;          return iMinSAD;
2834  }  }
2835    
2836    
2837    
   
   
2838  /* ***********************************************************  /* ***********************************************************
2839          bvop motion estimation          bvop motion estimation
2840  // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)  // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)
2841  ***************************************************************/  ***************************************************************/
2842    
 /*  
 void MotionEstimationBVOP(  
                         MBParam * const pParam,  
                         FRAMEINFO * const frame,  
2843    
2844    #define DIRECT_PENALTY 0
2845    #define DIRECT_UPPERLIMIT 256   // never use direct mode if SAD is larger than this
2846    
2847    void
2848    MotionEstimationBVOP(MBParam * const pParam,
2849                                             FRAMEINFO * const frame,
2850                                             const int32_t time_bp,
2851                                             const int32_t time_pp,
2852                          // forward (past) reference                          // forward (past) reference
2853                          const MACROBLOCK * const f_mbs,                          const MACROBLOCK * const f_mbs,
2854                      const IMAGE * const f_ref,                      const IMAGE * const f_ref,
# Line 1997  Line 2862 
2862                      const IMAGE * const b_refV,                      const IMAGE * const b_refV,
2863                          const IMAGE * const b_refHV)                          const IMAGE * const b_refHV)
2864  {  {
2865      const uint32_t mb_width = pParam->mb_width;          const int mb_width = pParam->mb_width;
2866      const uint32_t mb_height = pParam->mb_height;          const int mb_height = pParam->mb_height;
2867          const int32_t edged_width = pParam->edged_width;          const int edged_width = pParam->edged_width;
2868    
2869          int32_t i,j;          int i, j, k;
2870    
2871          int32_t f_sad16;          static const VECTOR zeroMV={0,0};
2872          int32_t b_sad16;  
2873          int32_t i_sad16;          int f_sad16;    /* forward (as usual) search */