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

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

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

revision 3, Fri Mar 8 02:46:11 2002 UTC revision 300, Tue Jul 16 12:02:27 2002 UTC
# Line 1  Line 1 
1  /**************************************************************************  /**************************************************************************
2   *   *
3     *      XVID MPEG-4 VIDEO CODEC
4     *      motion estimation
5     *
6     *      This program is an implementation of a part of one or more MPEG-4
7     *      Video tools as specified in ISO/IEC 14496-2 standard.  Those intending
8     *      to use this software module in hardware or software products are
9     *      advised that its use may infringe existing patents or copyrights, and
10     *      any such use would be at such party's own risk.  The original
11     *      developer of this software module and his/her company, and subsequent
12     *      editors and their companies, will have no liability for use of this
13     *      software or modifications or derivatives thereof.
14     *
15     *      This program is free software; you can redistribute it and/or modify
16     *      it under the terms of the GNU General Public License as published by
17     *      the Free Software Foundation; either version 2 of the License, or
18     *      (at your option) any later version.
19     *
20     *      This program is distributed in the hope that it will be useful,
21     *      but WITHOUT ANY WARRANTY; without even the implied warranty of
22     *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23     *      GNU General Public License for more details.
24     *
25     *      You should have received a copy of the GNU General Public License
26     *      along with this program; if not, write to the Free Software
27     *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28     *
29     *************************************************************************/
30    
31    /**************************************************************************
32     *
33   *  Modifications:   *  Modifications:
34   *   *
35     *      01.05.2002      updated MotionEstimationBVOP
36     *      25.04.2002 partial prevMB conversion
37     *  22.04.2002 remove some compile warning by chenm001 <chenm001@163.com>
38     *  14.04.2002 added MotionEstimationBVOP()
39     *  02.04.2002 add EPZS(^2) as ME algorithm, use PMV_USESQUARES to choose between
40     *             EPZS and EPZS^2
41   *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop   *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop
42   *             PMVFast_Refine to support multiple searches with different start points   *             PMVFast_Refine to support multiple searches with different start points
43   *      07.01.2002 uv-block-based interpolation   *      07.01.2002 uv-block-based interpolation
# Line 31  Line 67 
67    
68  #include <assert.h>  #include <assert.h>
69  #include <stdio.h>  #include <stdio.h>
70    #include <stdlib.h>
71    
72  #include "../encoder.h"  #include "../encoder.h"
73  #include "../utils/mbfunctions.h"  #include "../utils/mbfunctions.h"
74  #include "../prediction/mbprediction.h"  #include "../prediction/mbprediction.h"
75  #include "../global.h"  #include "../global.h"
76  #include "../utils/timer.h"  #include "../utils/timer.h"
77    #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)  
   
   
 #define MIN(X, Y) ((X)<(Y)?(X):(Y))  
 #define MAX(X, Y) ((X)>(Y)?(X):(Y))  
 #define ABS(X) (((X)>0)?(X):-(X))  
 #define SIGN(X) (((X)>0)?1:-1)  
   
   
 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, int start_y,  
                                         const uint32_t iQuality,  
                                         MBParam * const pParam,  
                                         MACROBLOCK * const pMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
 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 iQuality,  
                                         MBParam * const pParam,  
                                         MACROBLOCK * const pMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
   
   
 /* diamond search stuff  
    keep the the sequence in circular order (so optimization works)  
 */  
   
 typedef struct  
 {  
         int32_t dx;  
         int32_t dy;  
 }  
 DPOINT;  
80    
81    
82  static const DPOINT diamond_small[4] =  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          {0, 1}, {1, 0}, {0, -1}, {-1, 0}                  (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    
 static const DPOINT diamond_large[8] =  
 {  
         {0, 2}, {1, 1}, {2, 0}, {1, -1}, {0, -2}, {-1, -1}, {-2, 0}, {-1, 1}  
 };  
100    
101    
102  // mv.length table  // mv.length table
# Line 133  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 141  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 159  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          return NEIGH_TEND_16X16 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));                            const int32_t dy,
141  }                            const uint32_t iFcode,
142                              const uint32_t iQuant)
143  static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode)  {
144            return NEIGH_TEND_16X16 * lambda_vec16[iQuant] * (mv_bits(dx, iFcode) +
145  {                                                                                                            mv_bits(dy, iFcode));
146      return NEIGH_TEND_8X8 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));  }
147  }  
148    static __inline uint32_t
149    calc_delta_8(const int32_t dx,
150                             const int32_t dy,
151                             const uint32_t iFcode,
152  /* calculate the min/max range (in halfpixels)                           const uint32_t iQuant)
153          relative to the _MACROBLOCK_ position  {
154  */          return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) +
155                                                                                                       mv_bits(dy, iFcode));
156  static void __inline get_range(  }
157                          int32_t * const min_dx, int32_t * const max_dx,  
158                          int32_t * const min_dy, int32_t * const max_dy,  bool
159                          const uint32_t x, const uint32_t y,  MotionEstimation(MBParam * const pParam,
160                          const uint32_t block_sz,                                        // block dimension, 8 or 16                                   FRAMEINFO * const current,
161                          const uint32_t width, const uint32_t height,                                   FRAMEINFO * const reference,
                         const uint32_t fcode)  
 {  
         const int search_range = 32 << (fcode - 1);  
     const int high = search_range - 1;  
     const int low = -search_range;  
   
         // convert full-pixel measurements to half pixel  
         const int hp_width = 2 * width;  
         const int hp_height = 2 * height;  
         const int hp_edge = 2 * block_sz;  
         const int hp_x = 2 * (x) * block_sz;            // we need _right end_ of block, not x-coordinate  
         const int hp_y = 2 * (y) * block_sz;            // same for _bottom end_  
   
     *max_dx = MIN(high, hp_width - hp_x);  
     *max_dy = MIN(high, hp_height - hp_y);  
     *min_dx = MAX(low,  -(hp_edge + hp_x));  
     *min_dy = MAX(low,  -(hp_edge + hp_y));  
 }  
   
   
 /* getref: calculate reference image pointer  
 the decision to use interpolation h/v/hv or the normal image is  
 based on dx & dy.  
 */  
   
 static __inline const uint8_t * get_ref(  
                                 const uint8_t * const refn,  
                                 const uint8_t * const refh,  
                                 const uint8_t * const refv,  
                                 const uint8_t * const refhv,  
                                 const uint32_t x, const uint32_t y,  
                                 const uint32_t block,                                   // block dimension, 8 or 16  
                                 const int32_t dx, const int32_t dy,  
                                 const uint32_t stride)  
 {  
         switch ( ((dx&1)<<1) + (dy&1) )         // ((dx%2)?2:0)+((dy%2)?1:0)  
     {  
         case 0 : return refn + (x*block+dx/2) + (y*block+dy/2)*stride;  
     case 1 : return refv + (x*block+dx/2) + (y*block+(dy-1)/2)*stride;  
         case 2 : return refh + (x*block+(dx-1)/2) + (y*block+dy/2)*stride;  
         default :  
         case 3 : return refhv + (x*block+(dx-1)/2) + (y*block+(dy-1)/2)*stride;  
         }  
 }  
   
   
 /* This is somehow a copy of get_ref, but with MV instead of X,Y */  
   
 static __inline const uint8_t * get_ref_mv(  
                                 const uint8_t * const refn,  
                                 const uint8_t * const refh,  
                                 const uint8_t * const refv,  
                                 const uint8_t * const refhv,  
                                 const uint32_t x, const uint32_t y,  
                                 const uint32_t block,                   // block dimension, 8 or 16  
                                 const VECTOR* mv,       // measured in half-pel!  
                                 const uint32_t stride)  
 {  
         switch ( (((mv->x)&1)<<1) + ((mv->y)&1) )  
     {  
         case 0 : return refn + (x*block+(mv->x)/2) + (y*block+(mv->y)/2)*stride;  
         case 1 : return refv + (x*block+(mv->x)/2) + (y*block+((mv->y)-1)/2)*stride;  
         case 2 : return refh + (x*block+((mv->x)-1)/2) + (y*block+(mv->y)/2)*stride;  
         default :  
         case 3 : return refhv + (x*block+((mv->x)-1)/2) + (y*block+((mv->y)-1)/2)*stride;  
         }  
 }  
   
 #ifndef SEARCH16  
 #define SEARCH16        PMVfastSearch16  
 #endif  
   
 #ifndef SEARCH8  
 #define SEARCH8         PMVfastSearch8  
 #endif  
   
 bool MotionEstimation(  
                         MACROBLOCK * const pMBs,  
                         MBParam * const pParam,  
                     const IMAGE * const pRef,  
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,
                     IMAGE * const pCurrent,  
165                          const uint32_t iLimit)                          const uint32_t iLimit)
   
166  {  {
167      const uint32_t iWcount = pParam->mb_width;      const uint32_t iWcount = pParam->mb_width;
168      const uint32_t iHcount = pParam->mb_height;      const uint32_t iHcount = pParam->mb_height;
169            MACROBLOCK *const pMBs = current->mbs;
170            MACROBLOCK *const prevMBs = reference->mbs;
171            const IMAGE *const pCurrent = &current->image;
172            const IMAGE *const pRef = &reference->image;
173    
174          uint32_t i, j, iIntra = 0;          const VECTOR zeroMV = { 0, 0 };
175    
176      VECTOR mv16;          int32_t x, y;
177      VECTOR pmv16;          int32_t iIntra = 0;
178            VECTOR pmv;
179    
180      int32_t sad8 = 0;          if (sadInit)
181      int32_t sad16;                  (*sadInit) ();
     int32_t deviation;  
182    
183          // note: i==horizontal, j==vertical          for (y = 0; y < iHcount; y++)   {
184      for (i = 0; i < iHcount; i++)                  for (x = 0; x < iWcount; x ++)  {
                 for (j = 0; j < iWcount; j++)  
                 {  
                         MACROBLOCK *pMB = &pMBs[j + i * iWcount];  
185    
186                          sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                          MACROBLOCK *const pMB = &pMBs[x + y * iWcount];
                                           j, i, pParam->motion_flags,  
                                           pParam, pMBs, &mv16, &pmv16);  
                         pMB->sad16=sad16;  
187    
188                            pMB->sad16 =
189                                    SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,
190                                                     y, current->motion_flags, current->quant,
191                                                     current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,
192                                                     &pMB->pmvs[0]);
193    
194                  /* decide: MODE_INTER or MODE_INTRA                          if (0 < (pMB->sad16 - MV16_INTER_BIAS)) {
195                          if (dev_intra < sad_inter - 2 * nb) use_intra                                  int32_t deviation;
                 */  
196    
197                  deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width);                                  deviation =
198                                            dev16(pCurrent->y + x * 16 + y * 16 * pParam->edged_width,
199                                                      pParam->edged_width);
200    
201                  if (deviation < (sad16 - INTER_BIAS))                                  if (deviation < (pMB->sad16 - MV16_INTER_BIAS)) {
                 {  
202                          pMB->mode = MODE_INTRA;                          pMB->mode = MODE_INTRA;
203                          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] =
204                          pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;                                                  pMB->mvs[3] = zeroMV;
205                                            pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
206                                                    pMB->sad8[3] = 0;
207    
208                          iIntra++;                          iIntra++;
209                          if(iIntra >= iLimit)                          if(iIntra >= iLimit)
# Line 312  Line 211 
211    
212                          continue;                          continue;
213                  }                  }
   
                 if (pParam->global_flags & XVID_INTER4V)  
                 {  
                         pMB->sad8[0] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                         2 * j, 2 * i, mv16.x, mv16.y, pParam->motion_flags,  
                                         pParam, pMBs, &pMB->mvs[0], &pMB->pmvs[0]);  
   
                         pMB->sad8[1] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                         2 * j + 1, 2 * i, mv16.x, mv16.y, pParam->motion_flags,  
                                         pParam, pMBs, &pMB->mvs[1], &pMB->pmvs[1]);  
   
                         pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                         2 * j, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,  
                                         pParam, pMBs, &pMB->mvs[2], &pMB->pmvs[2]);  
   
                         pMB->sad8[3] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,  
                                         2 * j + 1, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,  
                                         pParam, pMBs, &pMB->mvs[3], &pMB->pmvs[3]);  
   
                         sad8 = pMB->sad8[0] + pMB->sad8[1] + pMB->sad8[2] + pMB->sad8[3];  
214                  }                  }
215    
216                            pmv = pMB->pmvs[0];
217                            if (current->global_flags & XVID_INTER4V)
218                                    if ((!(current->global_flags & XVID_LUMIMASKING) ||
219                                             pMB->dquant == NO_CHANGE)) {
220                                            int32_t sad8 = IMV16X16 * current->quant;
221    
222                                            if (sad8 < pMB->sad16)
223    
224                                                    sad8 += pMB->sad8[0] =
225                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
226                                                                            pCurrent, 2 * x, 2 * y, pMB->mv16.x,
227                                                                            pMB->mv16.y, current->motion_flags,
228                                                                            current->quant, current->fcode, pParam,
229                                                                            pMBs, prevMBs, &pMB->mvs[0],
230                                                                            &pMB->pmvs[0]);
231    
232                                            if (sad8 < pMB->sad16)
233                                                    sad8 += pMB->sad8[1] =
234                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
235                                                                            pCurrent, 2 * x + 1, 2 * y, pMB->mv16.x,
236                                                                            pMB->mv16.y, current->motion_flags,
237                                                                            current->quant, current->fcode, pParam,
238                                                                            pMBs, prevMBs, &pMB->mvs[1],
239                                                                            &pMB->pmvs[1]);
240    
241                                            if (sad8 < pMB->sad16)
242                                                    sad8 += pMB->sad8[2] =
243                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
244                                                                            pCurrent, 2 * x, 2 * y + 1, pMB->mv16.x,
245                                                                            pMB->mv16.y, current->motion_flags,
246                                                                            current->quant, current->fcode, pParam,
247                                                                            pMBs, prevMBs, &pMB->mvs[2],
248                                                                            &pMB->pmvs[2]);
249    
250                                            if (sad8 < pMB->sad16)
251                                                    sad8 += pMB->sad8[3] =
252                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
253                                                                            pCurrent, 2 * x + 1, 2 * y + 1,
254                                                                            pMB->mv16.x, pMB->mv16.y,
255                                                                            current->motion_flags, current->quant,
256                                                                            current->fcode, pParam, pMBs, prevMBs,
257                                                                            &pMB->mvs[3], &pMB->pmvs[3]);
258    
259                  /* decide: MODE_INTER or MODE_INTER4V                  /* decide: MODE_INTER or MODE_INTER4V
260                          mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v                                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
261                  */                  */
262    
263                  if (pMB->dquant == NO_CHANGE) {                                          if (sad8 < pMB->sad16) {
                         if (((pParam->global_flags & XVID_INTER4V)==0) ||  
                                 (sad16 < (sad8 + (int32_t)(IMV16X16 * pParam->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  
264                                  pMB->mode = MODE_INTER4V;                                  pMB->mode = MODE_INTER4V;
265                                                    pMB->sad8[0] *= 4;
266                                                    pMB->sad8[1] *= 4;
267                                                    pMB->sad8[2] *= 4;
268                                                    pMB->sad8[3] *= 4;
269                                                    continue;
270                  }                  }
271                  else  
272                  {                                  }
273                          sad8 = sad16;  
274                          pMB->mode = MODE_INTER;                          pMB->mode = MODE_INTER;
275                          pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;                          pMB->pmvs[0] = pmv;     /* pMB->pmvs[1] = pMB->pmvs[2] = pMB->pmvs[3]  are not needed for INTER */
276                          pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->mv16;
277                          pMB->pmvs[0].x = pmv16.x;                          pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =
278                          pMB->pmvs[0].y = pmv16.y;                                  pMB->sad16;
279                  }                  }
280          }          }
281    
282          return 0;          return 0;
283  }  }
284    
 #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )  
   
 #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )  
   
   
285  #define CHECK_MV16_ZERO {\  #define CHECK_MV16_ZERO {\
286    if ( (0 <= max_dx) && (0 >= min_dx) \    if ( (0 <= max_dx) && (0 >= min_dx) \
287      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
288    { \    { \
289      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); \
290      iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\
     if (iSAD <= iQuant * 96)    \  
         iSAD -= MV16_00_BIAS; \  
291      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
292      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
293  }  }
294    
295    #define NOCHECK_MV16_CANDIDATE(X,Y) { \
296        iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
297        iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
298        if (iSAD < iMinSAD) \
299        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
300    }
301    
302  #define CHECK_MV16_CANDIDATE(X,Y) { \  #define CHECK_MV16_CANDIDATE(X,Y) { \
303    if ( ((X) <= max_dx) && ((X) >= min_dx) \    if ( ((X) <= max_dx) && ((X) >= min_dx) \
304      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
305    { \    { \
306      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); \
307      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
308      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
309      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
310  }  }
# Line 400  Line 314 
314      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
315    { \    { \
316      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); \
317      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
318      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
319      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
320  }  }
# Line 410  Line 324 
324      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
325    { \    { \
326      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); \
327      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode, iQuant);\
328      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
329      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
330  }  }
# Line 418  Line 332 
332    
333  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
334    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); \
335    iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\    iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode, iQuant);\
336    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
337    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
338  }  }
339    
340    #define NOCHECK_MV8_CANDIDATE(X,Y) \
341      { \
342        iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
343        iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
344        if (iSAD < iMinSAD) \
345        {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
346    }
347    
348  #define CHECK_MV8_CANDIDATE(X,Y) { \  #define CHECK_MV8_CANDIDATE(X,Y) { \
349    if ( ((X) <= max_dx) && ((X) >= min_dx) \    if ( ((X) <= max_dx) && ((X) >= min_dx) \
350      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
351    { \    { \
352      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); \
353      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
354      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
355      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
356  }  }
# Line 439  Line 360 
360      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
361    { \    { \
362      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); \
363      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
364      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
365      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
366  }  }
# Line 449  Line 370 
370      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
371    { \    { \
372      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); \
373      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode, iQuant);\
374      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
375      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
376  }  }
# Line 464  Line 385 
385                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
386                                          const int x, const int y,                                          const int x, const int y,
387                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
388                                            const uint32_t iQuant,
389                                            const uint32_t iFcode,
390                                          MBParam * const pParam,                                          MBParam * const pParam,
391                                          MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
392                                            const MACROBLOCK * const prevMBs,
393                                          VECTOR * const currMV,                                          VECTOR * const currMV,
394                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
395  {  {
396          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
         const int32_t iQuant = pParam->quant;  
397          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
398          int32_t iSAD;          int32_t iSAD;
399          int32_t pred_x,pred_y;          VECTOR pred;
400    
401    
402          get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);          pred = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
403    
404          iSAD = sad16( cur,          iSAD = sad16( cur,
405                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),                  get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),
# Line 485  Line 409 
409    
410          currMV->x = 0;          currMV->x = 0;
411          currMV->y = 0;          currMV->y = 0;
412          currPMV->x = -pred_x;          currPMV->x = -pred.x;
413          currPMV->y = -pred_y;          currPMV->y = -pred.y;
414    
415          return iSAD;          return iSAD;
416    
417  }  }
418  */  */
419    
420  int32_t PMVfastSearch16_MainSearch(  int32_t
421                                          const uint8_t * const pRef,  Diamond16_MainSearch(const uint8_t * const pRef,
422                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
423                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
424                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
425                                          const uint8_t * const cur,                                          const uint8_t * const cur,
426                                          const int x, const int y,                                           const int x,
427                                          int32_t startx, int32_t starty,                                           const int y,
428                                             int32_t startx,
429                                             int32_t starty,
430                                          int32_t iMinSAD,                                          int32_t iMinSAD,
431                                          VECTOR * const currMV,                                          VECTOR * const currMV,
432                                          const VECTOR * const pmv,                                          const VECTOR * const pmv,
433                                          const int32_t min_dx, const int32_t max_dx,                                           const int32_t min_dx,
434                                          const int32_t min_dy, const int32_t max_dy,                                           const int32_t max_dx,
435                                             const int32_t min_dy,
436                                             const int32_t max_dy,
437                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
438                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
439                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 517  Line 445 
445          int32_t iDirection=0;          int32_t iDirection=0;
446          int32_t iSAD;          int32_t iSAD;
447          VECTOR backupMV;          VECTOR backupMV;
448    
449          backupMV.x = startx;          backupMV.x = startx;
450          backupMV.y = starty;          backupMV.y = starty;
451    
# Line 528  Line 457 
457          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
458    
459          if (iDirection)          if (iDirection)
460                  while (!iFound)                  while (!iFound) {
                 {  
461                          iFound = 1;                          iFound = 1;
462                          backupMV=*currMV;                          backupMV=*currMV;
463    
464                          if ( iDirection != 2)                          if ( iDirection != 2)
465                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
466                                                                                       backupMV.y, 1);
467                          if ( iDirection != 1)                          if ( iDirection != 1)
468                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
469                                                                                       backupMV.y, 2);
470                          if ( iDirection != 4)                          if ( iDirection != 4)
471                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
472                                                                                       backupMV.y - iDiamondSize, 3);
473                          if ( iDirection != 3)                          if ( iDirection != 3)
474                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
475                  }                                                                                     backupMV.y + iDiamondSize, 4);
476          else          } else {
                 {  
477                          currMV->x = startx;                          currMV->x = startx;
478                          currMV->y = starty;                          currMV->y = starty;
479                  }                  }
480          return iMinSAD;          return iMinSAD;
481  }  }
482    
483  int32_t PMVfastSearch16_Refine(  int32_t
484                                          const uint8_t * const pRef,  Square16_MainSearch(const uint8_t * const pRef,
485                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
486                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
487                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
488                                          const uint8_t * const cur,                                          const uint8_t * const cur,
489                                          const int x, const int y,                                          const int x,
490                                          VECTOR * const currMV,                                          const int y,
491                                            int32_t startx,
492                                            int32_t starty,
493                                          int32_t iMinSAD,                                          int32_t iMinSAD,
494                                            VECTOR * const currMV,
495                                          const VECTOR * const pmv,                                          const VECTOR * const pmv,
496                                          const int32_t min_dx, const int32_t max_dx,                                          const int32_t min_dx,
497                                          const int32_t min_dy, const int32_t max_dy,                                          const int32_t max_dx,
498                                            const int32_t min_dy,
499                                            const int32_t max_dy,
500                                            const int32_t iEdgedWidth,
501                                            const int32_t iDiamondSize,
502                                          const int32_t iFcode,                                          const int32_t iFcode,
503                                          const int32_t iQuant,                                          const int32_t iQuant,
504                                          const int32_t iEdgedWidth)                                          int iFound)
505  {  {
506  /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  /* Do a square search around given starting point, return SAD of best */
507    
508            int32_t iDirection = 0;
509          int32_t iSAD;          int32_t iSAD;
510          VECTOR backupMV = *currMV;          VECTOR backupMV;
511    
512          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y-1);          backupMV.x = startx;
513          CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y-1);          backupMV.y = starty;
514          CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y-1);  
515          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y);  /* It's one search with full square pattern, and new parts for all following diamonds */
516          CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y);  
517          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y+1);  /*   new direction are extra, so 1-4 is normal diamond
518          CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y+1);        537
519          CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y+1);        1*2
520          648
521    */
522    
523            CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
524            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
525            CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
526            CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
527    
528            CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
529                                                             backupMV.y - iDiamondSize, 5);
530            CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
531                                                             backupMV.y + iDiamondSize, 6);
532            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
533                                                             backupMV.y - iDiamondSize, 7);
534            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
535                                                             backupMV.y + iDiamondSize, 8);
536    
537    
538            if (iDirection)
539                    while (!iFound) {
540                            iFound = 1;
541                            backupMV = *currMV;
542    
543                            switch (iDirection) {
544                            case 1:
545                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
546                                                                                       backupMV.y, 1);
547                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
548                                                                                     backupMV.y - iDiamondSize, 5);
549                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
550                                                                                     backupMV.y - iDiamondSize, 7);
551                                    break;
552                            case 2:
553                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
554                                                                                     2);
555                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
556                                                                                     backupMV.y + iDiamondSize, 6);
557                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
558                                                                                     backupMV.y + iDiamondSize, 8);
559                                    break;
560    
561                            case 3:
562                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
563                                                                                     4);
564                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
565                                                                                     backupMV.y - iDiamondSize, 7);
566                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
567                                                                                     backupMV.y + iDiamondSize, 8);
568                                    break;
569    
570                            case 4:
571                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
572                                                                                     3);
573                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
574                                                                                     backupMV.y - iDiamondSize, 5);
575                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
576                                                                                     backupMV.y + iDiamondSize, 6);
577                                    break;
578    
579                            case 5:
580                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y,
581                                                                                     1);
582                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
583                                                                                     3);
584                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
585                                                                                     backupMV.y - iDiamondSize, 5);
586                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
587                                                                                     backupMV.y + iDiamondSize, 6);
588                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
589                                                                                     backupMV.y - iDiamondSize, 7);
590                                    break;
591    
592                            case 6:
593                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
594                                                                                     2);
595                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
596                                                                                     3);
597    
598                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
599                                                                                     backupMV.y - iDiamondSize, 5);
600                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
601                                                                                     backupMV.y + iDiamondSize, 6);
602                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
603                                                                                     backupMV.y + iDiamondSize, 8);
604    
605                                    break;
606    
607                            case 7:
608                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
609                                                                                       backupMV.y, 1);
610                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
611                                                                                     4);
612                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
613                                                                                     backupMV.y - iDiamondSize, 5);
614                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
615                                                                                     backupMV.y - iDiamondSize, 7);
616                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
617                                                                                     backupMV.y + iDiamondSize, 8);
618                                    break;
619    
620                            case 8:
621                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
622                                                                                     2);
623                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
624                                                                                     4);
625                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
626                                                                                     backupMV.y + iDiamondSize, 6);
627                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
628                                                                                     backupMV.y - iDiamondSize, 7);
629                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
630                                                                                     backupMV.y + iDiamondSize, 8);
631                                    break;
632                            default:
633                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y,
634                                                                                     1);
635                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y,
636                                                                                     2);
637                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize,
638                                                                                     3);
639                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize,
640                                                                                     4);
641    
642                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
643                                                                                     backupMV.y - iDiamondSize, 5);
644                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
645                                                                                     backupMV.y + iDiamondSize, 6);
646                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
647                                                                                     backupMV.y - iDiamondSize, 7);
648                                    CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
649                                                                                     backupMV.y + iDiamondSize, 8);
650                                    break;
651                            }
652            } else {
653                    currMV->x = startx;
654                    currMV->y = starty;
655            }
656          return iMinSAD;          return iMinSAD;
657  }  }
658    
 #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  
659    
660  int32_t PMVfastSearch16(  int32_t
661                                          const uint8_t * const pRef,  Full16_MainSearch(const uint8_t * const pRef,
662                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
663                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
664                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
665                                          const IMAGE * const pCur,                                    const uint8_t * const cur,
666                                          const int x, const int y,                                    const int x,
667                                          const uint32_t MotionFlags,                                    const int y,
668                                          MBParam * const pParam,                                    int32_t startx,
669                                          MACROBLOCK * const pMBs,                                    int32_t starty,
670                                      int32_t iMinSAD,
671                                          VECTOR * const currMV,                                          VECTOR * const currMV,
672                                          VECTOR * const currPMV)                                    const VECTOR * const pmv,
673                                      const int32_t min_dx,
674                                      const int32_t max_dx,
675                                      const int32_t min_dy,
676                                      const int32_t max_dy,
677                                      const int32_t iEdgedWidth,
678                                      const int32_t iDiamondSize,
679                                      const int32_t iFcode,
680                                      const int32_t iQuant,
681                                      int iFound)
682  {  {
683          const uint32_t iWcount = pParam->mb_width;          int32_t iSAD;
684          const int32_t iFcode = pParam->fixed_code;          int32_t dx, dy;
685          const int32_t iQuant = pParam->quant;          VECTOR backupMV;
         const int32_t iWidth = pParam->width;  
         const int32_t iHeight = pParam->height;  
         const int32_t iEdgedWidth = pParam->edged_width;  
   
         const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;  
   
         int32_t iDiamondSize;  
   
         int32_t min_dx;  
         int32_t max_dx;  
         int32_t min_dy;  
         int32_t max_dy;  
   
         int32_t iFound;  
686    
687          VECTOR newMV;          backupMV.x = startx;
688          VECTOR backupMV;        /* just for PMVFAST */          backupMV.y = starty;
689    
690          VECTOR pmv[4];          for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
691          int32_t psad[4];                  for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
692                            NOCHECK_MV16_CANDIDATE(dx, dy);
693    
694          MACROBLOCK * const pMB = pMBs + x + y * iWcount;          return iMinSAD;
695    }
696    
697          static int32_t threshA,threshB;  int32_t
698          int32_t bPredEq;  AdvDiamond16_MainSearch(const uint8_t * const pRef,
699          int32_t iMinSAD,iSAD;                                                  const uint8_t * const pRefH,
700                                                    const uint8_t * const pRefV,
701                                                    const uint8_t * const pRefHV,
702                                                    const uint8_t * const cur,
703                                                    const int x,
704                                                    const int y,
705                                                    int32_t startx,
706                                                    int32_t starty,
707                                                    int32_t iMinSAD,
708                                                    VECTOR * const currMV,
709                                                    const VECTOR * const pmv,
710                                                    const int32_t min_dx,
711                                                    const int32_t max_dx,
712                                                    const int32_t min_dy,
713                                                    const int32_t max_dy,
714                                                    const int32_t iEdgedWidth,
715                                                    const int32_t iDiamondSize,
716                                                    const int32_t iFcode,
717                                                    const int32_t iQuant,
718                                                    int iDirection)
719    {
720    
721  /* Get maximum range */          int32_t iSAD;
         get_range(&min_dx, &max_dx, &min_dy, &max_dy,  
                         x, y, 16, iWidth, iHeight, iFcode);  
722    
723  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
724    
725          if (!(MotionFlags & PMV_HALFPEL16 ))          if (iDirection) {
726          { min_dx = EVEN(min_dx);                  CHECK_MV16_CANDIDATE(startx - iDiamondSize, starty);
727            max_dx = EVEN(max_dx);                  CHECK_MV16_CANDIDATE(startx + iDiamondSize, starty);
728            min_dy = EVEN(min_dy);                  CHECK_MV16_CANDIDATE(startx, starty - iDiamondSize);
729            max_dy = EVEN(max_dy);                  CHECK_MV16_CANDIDATE(startx, starty + iDiamondSize);
730          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          } else {
731                    int bDirection = 1 + 2 + 4 + 8;
732    
733                    do {
734                            iDirection = 0;
735                            if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
736                                    CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);
737    
738                            if (bDirection & 2)
739                                    CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);
740    
741                            if (bDirection & 4)
742                                    CHECK_MV16_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);
743    
744                            if (bDirection & 8)
745                                    CHECK_MV16_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);
746    
747                            /* now we're doing diagonal checks near our candidate */
748    
749                            if (iDirection)         //checking if anything found
750                            {
751                                    bDirection = iDirection;
752                                    iDirection = 0;
753                                    startx = currMV->x;
754                                    starty = currMV->y;
755                                    if (bDirection & 3)     //our candidate is left or right
756                                    {
757                                            CHECK_MV16_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);
758                                            CHECK_MV16_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);
759                                    } else                  // what remains here is up or down
760                                    {
761                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);
762                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);
763                                    }
764    
765                                    if (iDirection) {
766                                            bDirection += iDirection;
767                                            startx = currMV->x;
768                                            starty = currMV->y;
769                                    }
770                            } else                          //about to quit, eh? not so fast....
771                            {
772                                    switch (bDirection) {
773                                    case 2:
774                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
775                                                                                             starty - iDiamondSize, 2 + 4);
776                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
777                                                                                             starty + iDiamondSize, 2 + 8);
778                                            break;
779                                    case 1:
780                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
781                                                                                             starty - iDiamondSize, 1 + 4);
782                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
783                                                                                             starty + iDiamondSize, 1 + 8);
784                                            break;
785                                    case 2 + 4:
786                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
787                                                                                             starty - iDiamondSize, 1 + 4);
788                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
789                                                                                             starty - iDiamondSize, 2 + 4);
790                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
791                                                                                             starty + iDiamondSize, 2 + 8);
792                                            break;
793                                    case 4:
794                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
795                                                                                             starty - iDiamondSize, 2 + 4);
796                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
797                                                                                             starty - iDiamondSize, 1 + 4);
798                                            break;
799                                    case 8:
800                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
801                                                                                             starty + iDiamondSize, 2 + 8);
802                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
803                                                                                             starty + iDiamondSize, 1 + 8);
804                                            break;
805                                    case 1 + 4:
806                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
807                                                                                             starty + iDiamondSize, 1 + 8);
808                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
809                                                                                             starty - iDiamondSize, 1 + 4);
810                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
811                                                                                             starty - iDiamondSize, 2 + 4);
812                                            break;
813                                    case 2 + 8:
814                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
815                                                                                             starty - iDiamondSize, 1 + 4);
816                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
817                                                                                             starty + iDiamondSize, 1 + 8);
818                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
819                                                                                             starty + iDiamondSize, 2 + 8);
820                                            break;
821                                    case 1 + 8:
822                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
823                                                                                             starty - iDiamondSize, 2 + 4);
824                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
825                                                                                             starty + iDiamondSize, 2 + 8);
826                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
827                                                                                             starty + iDiamondSize, 1 + 8);
828                                            break;
829                                    default:                //1+2+4+8 == we didn't find anything at all
830                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
831                                                                                             starty - iDiamondSize, 1 + 4);
832                                            CHECK_MV16_CANDIDATE_DIR(startx - iDiamondSize,
833                                                                                             starty + iDiamondSize, 1 + 8);
834                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
835                                                                                             starty - iDiamondSize, 2 + 4);
836                                            CHECK_MV16_CANDIDATE_DIR(startx + iDiamondSize,
837                                                                                             starty + iDiamondSize, 2 + 8);
838                                            break;
839                                    }
840                                    if (!iDirection)
841                                            break;          //ok, the end. really
842                                    else {
843                                            bDirection = iDirection;
844                                            startx = currMV->x;
845                                            starty = currMV->y;
846                                    }
847                            }
848                    }
849                    while (1);                              //forever
850            }
851            return iMinSAD;
852    }
853    
854    int32_t
855    AdvDiamond8_MainSearch(const uint8_t * const pRef,
856                                               const uint8_t * const pRefH,
857                                               const uint8_t * const pRefV,
858                                               const uint8_t * const pRefHV,
859                                               const uint8_t * const cur,
860                                               const int x,
861                                               const int y,
862                                               int32_t startx,
863                                               int32_t starty,
864                                               int32_t iMinSAD,
865                                               VECTOR * const currMV,
866                                               const VECTOR * const pmv,
867                                               const int32_t min_dx,
868                                               const int32_t max_dx,
869                                               const int32_t min_dy,
870                                               const int32_t max_dy,
871                                               const int32_t iEdgedWidth,
872                                               const int32_t iDiamondSize,
873                                               const int32_t iFcode,
874                                               const int32_t iQuant,
875                                               int iDirection)
876    {
877    
878          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          int32_t iSAD;
879    
880          if ((x==0) && (y==0) )  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
         {  
                 threshA =  512;  
                 threshB = 1024;  
881    
882            if (iDirection) {
883                    CHECK_MV8_CANDIDATE(startx - iDiamondSize, starty);
884                    CHECK_MV8_CANDIDATE(startx + iDiamondSize, starty);
885                    CHECK_MV8_CANDIDATE(startx, starty - iDiamondSize);
886                    CHECK_MV8_CANDIDATE(startx, starty + iDiamondSize);
887            } else {
888                    int bDirection = 1 + 2 + 4 + 8;
889    
890                    do {
891                            iDirection = 0;
892                            if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)
893                                    CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);
894    
895                            if (bDirection & 2)
896                                    CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);
897    
898                            if (bDirection & 4)
899                                    CHECK_MV8_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);
900    
901                            if (bDirection & 8)
902                                    CHECK_MV8_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);
903    
904                            /* now we're doing diagonal checks near our candidate */
905    
906                            if (iDirection)         //checking if anything found
907                            {
908                                    bDirection = iDirection;
909                                    iDirection = 0;
910                                    startx = currMV->x;
911                                    starty = currMV->y;
912                                    if (bDirection & 3)     //our candidate is left or right
913                                    {
914                                            CHECK_MV8_CANDIDATE_DIR(startx, starty + iDiamondSize, 8);
915                                            CHECK_MV8_CANDIDATE_DIR(startx, starty - iDiamondSize, 4);
916                                    } else                  // what remains here is up or down
917                                    {
918                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize, starty, 2);
919                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize, starty, 1);
920                                    }
921    
922                                    if (iDirection) {
923                                            bDirection += iDirection;
924                                            startx = currMV->x;
925                                            starty = currMV->y;
926                                    }
927                            } else                          //about to quit, eh? not so fast....
928                            {
929                                    switch (bDirection) {
930                                    case 2:
931                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
932                                                                                            starty - iDiamondSize, 2 + 4);
933                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
934                                                                                            starty + iDiamondSize, 2 + 8);
935                                            break;
936                                    case 1:
937                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
938                                                                                            starty - iDiamondSize, 1 + 4);
939                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
940                                                                                            starty + iDiamondSize, 1 + 8);
941                                            break;
942                                    case 2 + 4:
943                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
944                                                                                            starty - iDiamondSize, 1 + 4);
945                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
946                                                                                            starty - iDiamondSize, 2 + 4);
947                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
948                                                                                            starty + iDiamondSize, 2 + 8);
949                                            break;
950                                    case 4:
951                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
952                                                                                            starty - iDiamondSize, 2 + 4);
953                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
954                                                                                            starty - iDiamondSize, 1 + 4);
955                                            break;
956                                    case 8:
957                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
958                                                                                            starty + iDiamondSize, 2 + 8);
959                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
960                                                                                            starty + iDiamondSize, 1 + 8);
961                                            break;
962                                    case 1 + 4:
963                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
964                                                                                            starty + iDiamondSize, 1 + 8);
965                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
966                                                                                            starty - iDiamondSize, 1 + 4);
967                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
968                                                                                            starty - iDiamondSize, 2 + 4);
969                                            break;
970                                    case 2 + 8:
971                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
972                                                                                            starty - iDiamondSize, 1 + 4);
973                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
974                                                                                            starty + iDiamondSize, 1 + 8);
975                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
976                                                                                            starty + iDiamondSize, 2 + 8);
977                                            break;
978                                    case 1 + 8:
979                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
980                                                                                            starty - iDiamondSize, 2 + 4);
981                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
982                                                                                            starty + iDiamondSize, 2 + 8);
983                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
984                                                                                            starty + iDiamondSize, 1 + 8);
985                                            break;
986                                    default:                //1+2+4+8 == we didn't find anything at all
987                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
988                                                                                            starty - iDiamondSize, 1 + 4);
989                                            CHECK_MV8_CANDIDATE_DIR(startx - iDiamondSize,
990                                                                                            starty + iDiamondSize, 1 + 8);
991                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
992                                                                                            starty - iDiamondSize, 2 + 4);
993                                            CHECK_MV8_CANDIDATE_DIR(startx + iDiamondSize,
994                                                                                            starty + iDiamondSize, 2 + 8);
995                                            break;
996                                    }
997                                    if (!(iDirection))
998                                            break;          //ok, the end. really
999                                    else {
1000                                            bDirection = iDirection;
1001                                            startx = currMV->x;
1002                                            starty = currMV->y;
1003          }          }
1004          else                          }
1005          {                  }
1006                  threshA = psad[0];                  while (1);                              //forever
1007                  threshB = threshA+256;          }
1008                  if (threshA< 512) threshA =  512;          return iMinSAD;
                 if (threshA>1024) threshA = 1024;  
                 if (threshB>1792) threshB = 1792;  
1009          }          }
1010    
         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  
 */  
   
         if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[0]) ) )  
                 iFound=2;  
1011    
1012  /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  int32_t
1013          Otherwise select large Diamond Search.  Full8_MainSearch(const uint8_t * const pRef,
1014  */                                   const uint8_t * const pRefH,
1015                                     const uint8_t * const pRefV,
1016                                     const uint8_t * const pRefHV,
1017                                     const uint8_t * const cur,
1018                                     const int x,
1019                                     const int y,
1020                                     int32_t startx,
1021                                     int32_t starty,
1022                                     int32_t iMinSAD,
1023                                     VECTOR * const currMV,
1024                                     const VECTOR * const pmv,
1025                                     const int32_t min_dx,
1026                                     const int32_t max_dx,
1027                                     const int32_t min_dy,
1028                                     const int32_t max_dy,
1029                                     const int32_t iEdgedWidth,
1030                                     const int32_t iDiamondSize,
1031                                     const int32_t iFcode,
1032                                     const int32_t iQuant,
1033                                     int iFound)
1034    {
1035            int32_t iSAD;
1036            int32_t dx, dy;
1037            VECTOR backupMV;
1038    
1039          if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536) || (bPredEq) )          backupMV.x = startx;
1040                  iDiamondSize=1; // halfpel!          backupMV.y = starty;
         else  
                 iDiamondSize=2; // halfpel!  
1041    
1042          if (!(MotionFlags & PMV_HALFPELDIAMOND16) )          for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
1043                  iDiamondSize*=2;                  for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
1044                            NOCHECK_MV8_CANDIDATE(dx, dy);
1045    
1046            return iMinSAD;
1047    }
1048    
1049    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1050    
1051    int32_t
1052    Halfpel16_Refine(const uint8_t * const pRef,
1053                                     const uint8_t * const pRefH,
1054                                     const uint8_t * const pRefV,
1055                                     const uint8_t * const pRefHV,
1056                                     const uint8_t * const cur,
1057                                     const int x,
1058                                     const int y,
1059                                     VECTOR * const currMV,
1060                                     int32_t iMinSAD,
1061                                     const VECTOR * const pmv,
1062                                     const int32_t min_dx,
1063                                     const int32_t max_dx,
1064                                     const int32_t min_dy,
1065                                     const int32_t max_dy,
1066                                     const int32_t iFcode,
1067                                     const int32_t iQuant,
1068                                     const int32_t iEdgedWidth)
1069    {
1070    /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
1071    
1072            int32_t iSAD;
1073            VECTOR backupMV = *currMV;
1074    
1075            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y - 1);
1076            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y - 1);
1077            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y - 1);
1078            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y);
1079            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y);
1080            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y + 1);
1081            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y + 1);
1082            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y + 1);
1083    
1084            return iMinSAD;
1085    }
1086    
1087    #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1088    
1089    
1090    int32_t
1091    PMVfastSearch16(const uint8_t * const pRef,
1092                                    const uint8_t * const pRefH,
1093                                    const uint8_t * const pRefV,
1094                                    const uint8_t * const pRefHV,
1095                                    const IMAGE * const pCur,
1096                                    const int x,
1097                                    const int y,
1098                                    const uint32_t MotionFlags,
1099                                    const uint32_t iQuant,
1100                                    const uint32_t iFcode,
1101                                    const MBParam * const pParam,
1102                                    const MACROBLOCK * const pMBs,
1103                                    const MACROBLOCK * const prevMBs,
1104                                    VECTOR * const currMV,
1105                                    VECTOR * const currPMV)
1106    {
1107            const uint32_t iWcount = pParam->mb_width;
1108            const int32_t iWidth = pParam->width;
1109            const int32_t iHeight = pParam->height;
1110            const int32_t iEdgedWidth = pParam->edged_width;
1111    
1112            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
1113    
1114            int32_t iDiamondSize;
1115    
1116            int32_t min_dx;
1117            int32_t max_dx;
1118            int32_t min_dy;
1119            int32_t max_dy;
1120    
1121            int32_t iFound;
1122    
1123            VECTOR newMV;
1124            VECTOR backupMV;                        /* just for PMVFAST */
1125    
1126            VECTOR pmv[4];
1127            int32_t psad[4];
1128    
1129            MainSearch16FuncPtr MainSearchPtr;
1130    
1131            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
1132    
1133            int32_t threshA, threshB;
1134            int32_t bPredEq;
1135            int32_t iMinSAD, iSAD;
1136    
1137    /* Get maximum range */
1138            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
1139                              iFcode);
1140    
1141    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1142    
1143            if (!(MotionFlags & PMV_HALFPEL16)) {
1144                    min_dx = EVEN(min_dx);
1145                    max_dx = EVEN(max_dx);
1146                    min_dy = EVEN(min_dy);
1147                    max_dy = EVEN(max_dy);
1148            }
1149    
1150            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1151            //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1152            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1153    
1154    /*      fprintf(stderr,"pmv: %d %d / %d --- %d %d   %d %d   %d %d - %d %d %d\n",
1155                    pmv[0].x,pmv[0].y,psad[0],
1156                    pmv[1].x,pmv[1].y,pmv[2].x,pmv[2].y,pmv[3].x,pmv[3].y,
1157                    psad[1],psad[2],psad[3]);
1158    */
1159            if ((x == 0) && (y == 0)) {
1160                    threshA = 512;
1161                    threshB = 1024;
1162            } else {
1163                    threshA = psad[0];
1164                    threshB = threshA + 256;
1165                    if (threshA < 512)
1166                            threshA = 512;
1167                    if (threshA > 1024)
1168                            threshA = 1024;
1169                    if (threshB > 1792)
1170                            threshB = 1792;
1171            }
1172    
1173            iFound = 0;
1174    
1175  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1176          MinSAD=SAD          MinSAD=SAD
# Line 688  Line 1179 
1179          If SAD<=256 goto Step 10.          If SAD<=256 goto Step 10.
1180  */  */
1181    
   
 // Prepare for main loop  
   
1182          *currMV=pmv[0];         /* current best := prediction */          *currMV=pmv[0];         /* current best := prediction */
1183          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {   /* This should NOT be necessary! */
         {       /* This should NOT be necessary! */  
1184                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1185                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
1186          }          }
1187    
1188          if (currMV->x > max_dx)          if (currMV->x > max_dx) {
                 {  
1189                          currMV->x=max_dx;                          currMV->x=max_dx;
1190                  }                  }
1191          if (currMV->x < min_dx)          if (currMV->x < min_dx) {
                 {  
1192                          currMV->x=min_dx;                          currMV->x=min_dx;
1193                  }                  }
1194          if (currMV->y > max_dy)          if (currMV->y > max_dy) {
                 {  
1195                          currMV->y=max_dy;                          currMV->y=max_dy;
1196                  }                  }
1197          if (currMV->y < min_dy)          if (currMV->y < min_dy) {
                 {  
1198                          currMV->y=min_dy;                          currMV->y=min_dy;
1199                  }                  }
1200    
1201          iMinSAD = sad16( cur,          iMinSAD =
1202                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1203                  iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1204          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1205            iMinSAD +=
1206          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )                  calc_delta_16(currMV->x - pmv[0].x, currMV->y - pmv[0].y,
1207                  {                                            (uint8_t) iFcode, iQuant);
1208    
1209            if ((iMinSAD < 256) ||
1210                    ((MVequal(*currMV, prevMB->mvs[0])) &&
1211                     ((int32_t) iMinSAD < prevMB->sad16))) {
1212                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
1213                    {
1214                            if (!MVzero(*currMV)) {
1215                                    iMinSAD += MV16_00_BIAS;
1216                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
1217                                    iMinSAD -= MV16_00_BIAS;
1218                            }
1219                    }
1220    
1221                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
1222                                  goto step10b;                          goto PMVfast16_Terminate_without_Refine;
1223                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
1224                                  goto step10;                          goto PMVfast16_Terminate_with_Refine;
1225                  }                  }
1226    
1227    
1228    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1229       vector of the median.
1230       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1231    */
1232    
1233            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[0])))
1234                    iFound = 2;
1235    
1236    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1237       Otherwise select large Diamond Search.
1238    */
1239    
1240            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
1241                    iDiamondSize = 1;               // halfpel!
1242            else
1243                    iDiamondSize = 2;               // halfpel!
1244    
1245            if (!(MotionFlags & PMV_HALFPELDIAMOND16))
1246                    iDiamondSize *= 2;
1247    
1248  /*  /*
1249  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.
1250          Also calculate (0,0) but do not subtract offset.          Also calculate (0,0) but do not subtract offset.
1251          Let MinSAD be the smallest SAD up to this point.          Let MinSAD be the smallest SAD up to this point.
1252          If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1253  */  */
1254    
1255  // (0,0) is always possible  // (0,0) is always possible
1256    
1257            if (!MVzero(pmv[0]))
1258          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1259    
1260  // previous frame MV is always possible  // previous frame MV is always possible
1261          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);  
1262            if (!MVzero(prevMB->mvs[0]))
1263                    if (!MVequal(prevMB->mvs[0], pmv[0]))
1264                            CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
1265    
1266  // left neighbour, if allowed  // left neighbour, if allowed
1267          if (x != 0)  
1268          {          if (!MVzero(pmv[1]))
1269                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!MVequal(pmv[1], prevMB->mvs[0]))
1270                  {       pmv[1].x = EVEN(pmv[1].x);                          if (!MVequal(pmv[1], pmv[0])) {
1271                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1272                                            pmv[1].x = EVEN(pmv[1].x);
1273                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
1274                  }                  }
1275    
1276                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1277          }          }
   
1278  // top neighbour, if allowed  // top neighbour, if allowed
1279          if (y != 0)          if (!MVzero(pmv[2]))
1280          {                  if (!MVequal(pmv[2], prevMB->mvs[0]))
1281                  if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!MVequal(pmv[2], pmv[0]))
1282                  {       pmv[2].x = EVEN(pmv[2].x);                                  if (!MVequal(pmv[2], pmv[1])) {
1283                                            if (!(MotionFlags & PMV_HALFPEL16)) {
1284                                                    pmv[2].x = EVEN(pmv[2].x);
1285                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
1286                  }                  }
1287                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1288    
1289  // top right neighbour, if allowed  // top right neighbour, if allowed
1290                  if (x != (iWcount-1))                                          if (!MVzero(pmv[3]))
1291                  {                                                  if (!MVequal(pmv[3], prevMB->mvs[0]))
1292                          if (!(MotionFlags & PMV_HALFPEL16 ))                                                          if (!MVequal(pmv[3], pmv[0]))
1293                          {       pmv[3].x = EVEN(pmv[3].x);                                                                  if (!MVequal(pmv[3], pmv[1]))
1294                                                                            if (!MVequal(pmv[3], pmv[2])) {
1295                                                                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1296                                                                                            pmv[3].x = EVEN(pmv[3].x);
1297                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
1298                          }                          }
1299                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                  CHECK_MV16_CANDIDATE(pmv[3].x,
1300                                                                                                                             pmv[3].y);
1301                  }                  }
1302          }          }
1303    
1304            if ((MVzero(*currMV)) &&
1305                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1306                    iMinSAD -= MV16_00_BIAS;
1307    
1308    
1309  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1310     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
1311  */  */
1312    
1313          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )          if ((iMinSAD <= threshA) ||
1314                  {                  (MVequal(*currMV, prevMB->mvs[0]) &&
1315                     ((int32_t) iMinSAD < prevMB->sad16))) {
1316                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
1317                                  goto step10b;                          goto PMVfast16_Terminate_without_Refine;
1318                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
1319                                  goto step10;                          goto PMVfast16_Terminate_with_Refine;
1320                  }                  }
1321    
1322    
# Line 796  Line 1330 
1330          Refine by using small diamond and goto step 10.          Refine by using small diamond and goto step 10.
1331  */  */
1332    
1333            if (MotionFlags & PMV_USESQUARES16)
1334                    MainSearchPtr = Square16_MainSearch;
1335            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
1336                    MainSearchPtr = AdvDiamond16_MainSearch;
1337            else
1338                    MainSearchPtr = Diamond16_MainSearch;
1339    
1340          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1341    
1342    
1343    //      fprintf(stderr,"Entering Diamond %d %d (%d):\n",x,y,iMinSAD);
1344    
1345  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1346          iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1347                  x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
1348                  currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,
1349                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1350                                                      iQuant, iFound);
1351    
1352          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1353                  *currMV = newMV;                  *currMV = newMV;
1354                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1355          }          }
1356    
1357          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
1358  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1359    
1360                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1361                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1362                                  x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1363                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,
1364                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1365                                                                      iDiamondSize, iFcode, iQuant, iFound);
1366    
1367                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
1368                                  *currMV = newMV;                                  *currMV = newMV;
1369                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
1370                          }                          }
1371                  }                  }
1372    
1373                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1374                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1375                                  x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1376                          0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,
1377                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
1378                                                                      iQuant, iFound);
1379    
1380                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
1381                                  *currMV = newMV;                                  *currMV = newMV;
1382                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
1383                          }                          }
# Line 845  Line 1388 
1388          Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.          Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.
1389  */  */
1390    
1391  step10:    PMVfast16_Terminate_with_Refine:
1392          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1393                  iMinSAD = PMVfastSearch16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1394                                  x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1395                                  currMV, iMinSAD,                                                           iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,
1396                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1397    
1398  step10b:  /*fprintf(stderr,"Chosen for %d %d: %d %d - %d %d\n",x,y,currMV->x,currMV->y,pmv[0].x,pmv[0].y);
1399    */
1400      PMVfast16_Terminate_without_Refine:
1401          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1402          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
1403          return iMinSAD;          return iMinSAD;
# Line 863  Line 1408 
1408    
1409    
1410    
1411  int32_t PMVfastSearch8_MainSearch(  int32_t
1412                                          const uint8_t * const pRef,  Diamond8_MainSearch(const uint8_t * const pRef,
1413                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1414                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1415                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1416                                          const uint8_t * const cur,                                          const uint8_t * const cur,
1417                                          const int x, const int y,                                          const int x,
1418                                          int32_t startx, int32_t starty,                                          const int y,
1419                                            int32_t startx,
1420                                            int32_t starty,
1421                                          int32_t iMinSAD,                                          int32_t iMinSAD,
1422                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1423                                          const VECTOR * const pmv,                                          const VECTOR * const pmv,
1424                                          const int32_t min_dx, const int32_t max_dx,                                          const int32_t min_dx,
1425                                          const int32_t min_dy, const int32_t max_dy,                                          const int32_t max_dx,
1426                                            const int32_t min_dy,
1427                                            const int32_t max_dy,
1428                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
1429                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
1430                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 887  Line 1436 
1436          int32_t iDirection=0;          int32_t iDirection=0;
1437          int32_t iSAD;          int32_t iSAD;
1438          VECTOR backupMV;          VECTOR backupMV;
1439    
1440          backupMV.x = startx;          backupMV.x = startx;
1441          backupMV.y = starty;          backupMV.y = starty;
1442    
# Line 898  Line 1448 
1448          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1449    
1450          if (iDirection)          if (iDirection)
1451                  while (!iFound)                  while (!iFound) {
                 {  
1452                          iFound = 1;                          iFound = 1;
1453                          backupMV=*currMV;       // since iDirection!=0, this is well defined!                          backupMV=*currMV;       // since iDirection!=0, this is well defined!
1454    
1455                          if ( iDirection != 2)                          if ( iDirection != 2)
1456                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1457                                                                                      backupMV.y, 1);
1458                          if ( iDirection != 1)                          if ( iDirection != 1)
1459                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1460                                                                                      backupMV.y, 2);
1461                          if ( iDirection != 4)                          if ( iDirection != 4)
1462                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1463                                                                                      backupMV.y - iDiamondSize, 3);
1464                          if ( iDirection != 3)                          if ( iDirection != 3)
1465                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1466                  }                                                                                    backupMV.y + iDiamondSize, 4);
1467          else          } else {
                 {  
1468                          currMV->x = startx;                          currMV->x = startx;
1469                          currMV->y = starty;                          currMV->y = starty;
1470                  }                  }
1471          return iMinSAD;          return iMinSAD;
1472  }  }
1473    
1474  int32_t PMVfastSearch8_Refine(  int32_t
1475                                          const uint8_t * const pRef,  Halfpel8_Refine_c(const uint8_t * const pRef,
1476                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1477                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1478                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1479                                          const uint8_t * const cur,                                          const uint8_t * const cur,
1480                                          const int x, const int y,                                  const int x,
1481                                    const int y,
1482                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1483                                          int32_t iMinSAD,                                          int32_t iMinSAD,
1484                                          const VECTOR * const pmv,                                          const VECTOR * const pmv,
1485                                          const int32_t min_dx, const int32_t max_dx,                                  const int32_t min_dx,
1486                                          const int32_t min_dy, const int32_t max_dy,                                  const int32_t max_dx,
1487                                    const int32_t min_dy,
1488                                    const int32_t max_dy,
1489                                          const int32_t iFcode,                                          const int32_t iFcode,
1490                                          const int32_t iQuant,                                          const int32_t iQuant,
1491                                          const int32_t iEdgedWidth)                                          const int32_t iEdgedWidth)
# Line 956  Line 1510 
1510    
1511  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1512    
1513  int32_t PMVfastSearch8(  int32_t
1514                                          const uint8_t * const pRef,  PMVfastSearch8(const uint8_t * const pRef,
1515                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1516                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1517                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1518                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1519                                          const int x, const int y,                             const int x,
1520                                          const int start_x, int start_y,                             const int y,
1521                               const int start_x,
1522                               const int start_y,
1523                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1524                                          MBParam * const pParam,                             const uint32_t iQuant,
1525                                          MACROBLOCK * const pMBs,                             const uint32_t iFcode,
1526                               const MBParam * const pParam,
1527                               const MACROBLOCK * const pMBs,
1528                               const MACROBLOCK * const prevMBs,
1529                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1530                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
1531  {  {
1532          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
   
         const int32_t iFcode = pParam->fixed_code;  
         const int32_t iQuant = pParam->quant;  
1533          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1534          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
1535          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 991  Line 1547 
1547          int32_t psad[4];          int32_t psad[4];
1548          VECTOR newMV;          VECTOR newMV;
1549          VECTOR backupMV;          VECTOR backupMV;
1550            VECTOR startMV;
1551    
1552          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1553            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
1554    
1555          static int32_t threshA,threshB;           int32_t threshA, threshB;
1556          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
1557          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1558    
1559          int32_t iSubBlock = ((y&1)<<1) + (x&1);          int32_t iSubBlock = (y & 1) + (y & 1) + (x & 1);
1560    
1561  /* Get maximum range */          MainSearch8FuncPtr MainSearchPtr;
     get_range(&min_dx, &max_dx, &min_dy, &max_dy,  
                         x, y, 8, iWidth, iHeight, iFcode);  
1562    
1563  /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */          /* Init variables */
1564            startMV.x = start_x;
1565            startMV.y = start_y;
1566    
1567          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          /* Get maximum range */
1568          { min_dx = EVEN(min_dx);          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
1569                              iFcode);
1570    
1571            if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
1572                    min_dx = EVEN(min_dx);
1573            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
1574            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
1575            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
1576          }               /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          }
   
1577    
1578          bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
1579            //bPredEq = get_pmvdata(pMBs, (x >> 1), (y >> 1), iWcount, iSubBlock, pmv, psad);
1580            bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
1581    
1582          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1583                  threshA =  512/4;                  threshA =  512/4;
1584                  threshB = 1024/4;                  threshB = 1024/4;
1585    
1586          }          } else {
         else  
         {  
1587                  threshA = psad[0]/4;                    /* good estimate */                  threshA = psad[0]/4;                    /* good estimate */
1588                  threshB = threshA+256/4;                  threshB = threshA+256/4;
1589                  if (threshA< 512/4) threshA =  512/4;                  if (threshA < 512 / 4)
1590                  if (threshA>1024/4) threshA = 1024/4;                          threshA = 512 / 4;
1591                  if (threshB>1792/4) threshB = 1792/4;                  if (threshA > 1024 / 4)
1592                            threshA = 1024 / 4;
1593                    if (threshB > 1792 / 4)
1594                            threshB = 1792 / 4;
1595          }          }
1596    
1597          iFound=0;          iFound=0;
1598    
1599  /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  /* Step 4: Calculate SAD around the Median prediction.
1600       MinSAD=SAD
1601       If Motion Vector equal to Previous frame motion vector
1602       and MinSAD<PrevFrmSAD goto Step 10.
1603       If SAD<=256 goto Step 10.
1604    */
1605    
1606    
1607    // Prepare for main loop
1608    
1609    //  if (MotionFlags & PMV_USESQUARES8)
1610    //      MainSearchPtr = Square8_MainSearch;
1611    //  else
1612    
1613            if (MotionFlags & PMV_ADVANCEDDIAMOND8)
1614                    MainSearchPtr = AdvDiamond8_MainSearch;
1615            else
1616                    MainSearchPtr = Diamond8_MainSearch;
1617    
1618    
1619            *currMV = startMV;
1620    
1621            iMinSAD =
1622                    sad8(cur,
1623                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
1624                                                    iEdgedWidth), iEdgedWidth);
1625            iMinSAD +=
1626                    calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y,
1627                                             (uint8_t) iFcode, iQuant);
1628    
1629            if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))
1630                                                                    && ((int32_t) iMinSAD <
1631                                                                            prevMB->sad8[iSubBlock]))) {
1632                    if (MotionFlags & PMV_QUICKSTOP16)
1633                            goto PMVfast8_Terminate_without_Refine;
1634                    if (MotionFlags & PMV_EARLYSTOP16)
1635                            goto PMVfast8_Terminate_with_Refine;
1636            }
1637    
1638    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1639          vector of the median.          vector of the median.
1640          If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2          If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1641  */  */
1642    
1643          if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[iSubBlock]) ) )          if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[iSubBlock])))
1644                  iFound=2;                  iFound=2;
1645    
1646  /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1647          Otherwise select large Diamond Search.          Otherwise select large Diamond Search.
1648  */  */
1649    
1650          if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536/4) || (bPredEq) )          if ((!MVzero(pmv[0])) || (threshB < 1536 / 4) || (bPredEq))
1651                  iDiamondSize=1; // 1 halfpel!                  iDiamondSize=1; // 1 halfpel!
1652          else          else
1653                  iDiamondSize=2; // 2 halfpel = 1 full pixel!                  iDiamondSize=2; // 2 halfpel = 1 full pixel!
# Line 1053  Line 1655 
1655          if (!(MotionFlags & PMV_HALFPELDIAMOND8) )          if (!(MotionFlags & PMV_HALFPELDIAMOND8) )
1656                  iDiamondSize*=2;                  iDiamondSize*=2;
1657    
 /* Step 4: Calculate SAD around the Median prediction.  
         MinSAD=SAD  
         If Motion Vector equal to Previous frame motion vector  
                 and MinSAD<PrevFrmSAD goto Step 10.  
         If SAD<=256 goto Step 10.  
 */  
   
   
 // Prepare for main loop  
   
         currMV->x=start_x;              /* start with mv16 */  
         currMV->y=start_y;  
   
         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;  
   
         if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && (iMinSAD < pMB->sad8[iSubBlock]) ) )  
                 {  
                         if (MotionFlags & PMV_QUICKSTOP8)  
                                 goto step10_8b;  
                         if (MotionFlags & PMV_EARLYSTOP8)  
                                 goto step10_8;  
                 }  
1658    
1659  /*  /*
1660  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.
1661          Also calculate (0,0) but do not subtract offset.          Also calculate (0,0) but do not subtract offset.
1662          Let MinSAD be the smallest SAD up to this point.          Let MinSAD be the smallest SAD up to this point.
1663          If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1664  */  */
1665    
1666  // the prediction might be even better than mv16  // the median prediction might be even better than mv16
1667    
1668            if (!MVequal(pmv[0], startMV))
1669          CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);          CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);
1670    
1671  // (0,0) is always possible  // (0,0) if needed
1672            if (!MVzero(pmv[0]))
1673                    if (!MVzero(startMV))
1674          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
1675    
1676  // previous frame MV is always possible  // previous frame MV if needed
1677          CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);          if (!MVzero(prevMB->mvs[iSubBlock]))
1678                    if (!MVequal(prevMB->mvs[iSubBlock], startMV))
1679                            if (!MVequal(prevMB->mvs[iSubBlock], pmv[0]))
1680                                    CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,
1681                                                                            prevMB->mvs[iSubBlock].y);
1682    
1683            if ((iMinSAD <= threshA) ||
1684                    (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
1685                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
1686                    if (MotionFlags & PMV_QUICKSTOP16)
1687                            goto PMVfast8_Terminate_without_Refine;
1688                    if (MotionFlags & PMV_EARLYSTOP16)
1689                            goto PMVfast8_Terminate_with_Refine;
1690            }
1691    
1692  // left neighbour, if allowed  // left neighbour, if allowed and needed
1693          if (psad[1] != MV_MAX_ERROR)          if (!MVzero(pmv[1]))
1694          {                  if (!MVequal(pmv[1], startMV))
1695                  if (!(MotionFlags & PMV_HALFPEL8 ))                          if (!MVequal(pmv[1], prevMB->mvs[iSubBlock]))
1696                  {       pmv[1].x = EVEN(pmv[1].x);                                  if (!MVequal(pmv[1], pmv[0])) {
1697                                            if (!(MotionFlags & PMV_HALFPEL8)) {
1698                                                    pmv[1].x = EVEN(pmv[1].x);
1699                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
1700                  }                  }
1701                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1702          }          }
1703    // top neighbour, if allowed and needed
1704  // top neighbour, if allowed          if (!MVzero(pmv[2]))
1705          if (psad[2] != MV_MAX_ERROR)                  if (!MVequal(pmv[2], startMV))
1706          {                          if (!MVequal(pmv[2], prevMB->mvs[iSubBlock]))
1707                  if (!(MotionFlags & PMV_HALFPEL8 ))                                  if (!MVequal(pmv[2], pmv[0]))
1708                  {       pmv[2].x = EVEN(pmv[2].x);                                          if (!MVequal(pmv[2], pmv[1])) {
1709                                                    if (!(MotionFlags & PMV_HALFPEL8)) {
1710                                                            pmv[2].x = EVEN(pmv[2].x);
1711                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
1712                  }                  }
1713                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1714    
1715  // top right neighbour, if allowed  // top right neighbour, if allowed and needed
1716                  if (psad[3] != MV_MAX_ERROR)                                                  if (!MVzero(pmv[3]))
1717                  {                                                          if (!MVequal(pmv[3], startMV))
1718                  if (!(MotionFlags & PMV_HALFPEL8 ))                                                                  if (!MVequal(pmv[3], prevMB->mvs[iSubBlock]))
1719                  {       pmv[3].x = EVEN(pmv[3].x);                                                                          if (!MVequal(pmv[3], pmv[0]))
1720                                                                                    if (!MVequal(pmv[3], pmv[1]))
1721                                                                                            if (!MVequal(pmv[3], pmv[2])) {
1722                                                                                                    if (!
1723                                                                                                            (MotionFlags &
1724                                                                                                             PMV_HALFPEL8)) {
1725                                                                                                            pmv[3].x = EVEN(pmv[3].x);
1726                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1727                  }                  }
1728                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                                  CHECK_MV8_CANDIDATE(pmv[3].x,
1729                                                                                                                                            pmv[3].y);
1730                  }                  }
1731          }          }
1732    
1733            if ((MVzero(*currMV)) &&
1734                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1735                    iMinSAD -= MV8_00_BIAS;
1736    
1737    
1738  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1739     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
1740  */  */
1741    
1742          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
1743                  {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
1744                          if (MotionFlags & PMV_QUICKSTOP8)                   ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
1745                                  goto step10_8b;                  if (MotionFlags & PMV_QUICKSTOP16)
1746                          if (MotionFlags & PMV_EARLYSTOP8)                          goto PMVfast8_Terminate_without_Refine;
1747                                  goto step10_8;                  if (MotionFlags & PMV_EARLYSTOP16)
1748                            goto PMVfast8_Terminate_with_Refine;
1749                  }                  }
1750    
1751  /************ (Diamond Search)  **************/  /************ (Diamond Search)  **************/
# Line 1150  Line 1761 
1761          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1762    
1763  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1764          iSAD = PMVfastSearch8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1765                  x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
1766                  currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,
1767                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1768                                                      iQuant, iFound);
1769    
1770          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1771                  *currMV = newMV;                  *currMV = newMV;
1772                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1773          }          }
1774    
1775          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
1776  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1777    
1778                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1779                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1780                                  x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1781                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,
1782                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1783                                                                      iDiamondSize, iFcode, iQuant, iFound);
1784    
1785                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
1786                                  *currMV = newMV;                                  *currMV = newMV;
1787                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
1788                          }                          }
1789                  }                  }
1790    
1791                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1792                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1793                                  x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1794                          0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,
1795                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
1796                                                                      iQuant, iFound);
1797    
1798                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
1799                                  *currMV = newMV;                                  *currMV = newMV;
1800                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
1801                          }                          }
# Line 1196  Line 1806 
1806           By performing an optional local half-pixel search, we can refine this result even further.           By performing an optional local half-pixel search, we can refine this result even further.
1807  */  */
1808    
1809  step10_8:    PMVfast8_Terminate_with_Refine:
1810          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
1811                  iMinSAD = PMVfastSearch8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1812                                  x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1813                                  currMV, iMinSAD,                                                          iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,
1814                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
1815    
 step10_8b:  
1816    
1817      PMVfast8_Terminate_without_Refine:
1818          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - pmv[0].x;
1819          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - pmv[0].y;
1820    
1821          return iMinSAD;          return iMinSAD;
1822  }  }
1823    
1824    int32_t
1825    EPZSSearch16(const uint8_t * const pRef,
1826                             const uint8_t * const pRefH,
1827                             const uint8_t * const pRefV,
1828                             const uint8_t * const pRefHV,
1829                             const IMAGE * const pCur,
1830                             const int x,
1831                             const int y,
1832                             const uint32_t MotionFlags,
1833                             const uint32_t iQuant,
1834                             const uint32_t iFcode,
1835                             const MBParam * const pParam,
1836                             const MACROBLOCK * const pMBs,
1837                             const MACROBLOCK * const prevMBs,
1838                             VECTOR * const currMV,
1839                             VECTOR * const currPMV)
1840    {
1841            const uint32_t iWcount = pParam->mb_width;
1842            const uint32_t iHcount = pParam->mb_height;
1843    
1844            const int32_t iWidth = pParam->width;
1845            const int32_t iHeight = pParam->height;
1846            const int32_t iEdgedWidth = pParam->edged_width;
1847    
1848            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
1849    
1850            int32_t min_dx;
1851            int32_t max_dx;
1852            int32_t min_dy;
1853            int32_t max_dy;
1854    
1855            VECTOR newMV;
1856            VECTOR backupMV;
1857    
1858            VECTOR pmv[4];
1859            int32_t psad[8];
1860    
1861            static MACROBLOCK *oldMBs = NULL;
1862    
1863    //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
1864            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
1865            MACROBLOCK *oldMB = NULL;
1866    
1867             int32_t thresh2;
1868            int32_t bPredEq;
1869            int32_t iMinSAD, iSAD = 9999;
1870    
1871            MainSearch16FuncPtr MainSearchPtr;
1872    
1873            if (oldMBs == NULL) {
1874                    oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
1875    //      fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
1876            }
1877            oldMB = oldMBs + x + y * iWcount;
1878    
1879    /* Get maximum range */
1880            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
1881                              iFcode);
1882    
1883            if (!(MotionFlags & PMV_HALFPEL16)) {
1884                    min_dx = EVEN(min_dx);
1885                    max_dx = EVEN(max_dx);
1886                    min_dy = EVEN(min_dy);
1887                    max_dy = EVEN(max_dy);
1888            }
1889            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1890            //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
1891            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1892    
1893    /* Step 4: Calculate SAD around the Median prediction.
1894            MinSAD=SAD
1895            If Motion Vector equal to Previous frame motion vector
1896                    and MinSAD<PrevFrmSAD goto Step 10.
1897            If SAD<=256 goto Step 10.
1898    */
1899    
1900    // Prepare for main loop
1901    
1902            *currMV = pmv[0];                       /* current best := median prediction */
1903            if (!(MotionFlags & PMV_HALFPEL16)) {
1904                    currMV->x = EVEN(currMV->x);
1905                    currMV->y = EVEN(currMV->y);
1906            }
1907    
1908            if (currMV->x > max_dx)
1909                    currMV->x = max_dx;
1910            if (currMV->x < min_dx)
1911                    currMV->x = min_dx;
1912            if (currMV->y > max_dy)
1913                    currMV->y = max_dy;
1914            if (currMV->y < min_dy)
1915                    currMV->y = min_dy;
1916    
1917    /***************** This is predictor SET A: only median prediction ******************/
1918    
1919            iMinSAD =
1920                    sad16(cur,
1921                              get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1922                                                     iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1923            iMinSAD +=
1924                    calc_delta_16(currMV->x - pmv[0].x, currMV->y - pmv[0].y,
1925                                              (uint8_t) iFcode, iQuant);
1926    
1927    // thresh1 is fixed to 256
1928            if ((iMinSAD < 256) ||
1929                    ((MVequal(*currMV, prevMB->mvs[0])) &&
1930                     ((int32_t) iMinSAD < prevMB->sad16))) {
1931                    if (MotionFlags & PMV_QUICKSTOP16)
1932                            goto EPZS16_Terminate_without_Refine;
1933                    if (MotionFlags & PMV_EARLYSTOP16)
1934                            goto EPZS16_Terminate_with_Refine;
1935            }
1936    
1937    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
1938    
1939    // previous frame MV
1940            CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
1941    
1942    // set threshhold based on Min of Prediction and SAD of collocated block
1943    // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
1944    
1945            if ((x == 0) && (y == 0)) {
1946                    thresh2 = 512;
1947            } else {
1948    /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */
1949    
1950                    thresh2 = MIN(psad[0], iSAD) * 6 / 5 + 128;
1951            }
1952    
1953    // MV=(0,0) is often a good choice
1954    
1955            CHECK_MV16_ZERO;
1956    
1957    
1958    // left neighbour, if allowed
1959            if (x != 0) {
1960                    if (!(MotionFlags & PMV_HALFPEL16)) {
1961                            pmv[1].x = EVEN(pmv[1].x);
1962                            pmv[1].y = EVEN(pmv[1].y);
1963                    }
1964                    CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
1965            }
1966    // top neighbour, if allowed
1967            if (y != 0) {
1968                    if (!(MotionFlags & PMV_HALFPEL16)) {
1969                            pmv[2].x = EVEN(pmv[2].x);
1970                            pmv[2].y = EVEN(pmv[2].y);
1971                    }
1972                    CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
1973    
1974    // top right neighbour, if allowed
1975                    if ((uint32_t) x != (iWcount - 1)) {
1976                            if (!(MotionFlags & PMV_HALFPEL16)) {
1977                                    pmv[3].x = EVEN(pmv[3].x);
1978                                    pmv[3].y = EVEN(pmv[3].y);
1979                            }
1980                            CHECK_MV16_CANDIDATE(pmv[3].x, pmv[3].y);
1981                    }
1982            }
1983    
1984    /* Terminate if MinSAD <= T_2
1985       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
1986    */
1987    
1988            if ((iMinSAD <= thresh2)
1989                    || (MVequal(*currMV, prevMB->mvs[0]) &&
1990                            ((int32_t) iMinSAD <= prevMB->sad16))) {
1991                    if (MotionFlags & PMV_QUICKSTOP16)
1992                            goto EPZS16_Terminate_without_Refine;
1993                    if (MotionFlags & PMV_EARLYSTOP16)
1994                            goto EPZS16_Terminate_with_Refine;
1995            }
1996    
1997    /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
1998    
1999            backupMV = prevMB->mvs[0];      // collocated MV
2000            backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x);     // acceleration X
2001            backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y);     // acceleration Y
2002    
2003            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y);
2004    
2005    // left neighbour
2006            if (x != 0)
2007                    CHECK_MV16_CANDIDATE((prevMB - 1)->mvs[0].x, (prevMB - 1)->mvs[0].y);
2008    
2009    // top neighbour
2010            if (y != 0)
2011                    CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,
2012                                                             (prevMB - iWcount)->mvs[0].y);
2013    
2014    // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
2015    
2016            if ((uint32_t) x != iWcount - 1)
2017                    CHECK_MV16_CANDIDATE((prevMB + 1)->mvs[0].x, (prevMB + 1)->mvs[0].y);
2018    
2019    // bottom neighbour, dito
2020            if ((uint32_t) y != iHcount - 1)
2021                    CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,
2022                                                             (prevMB + iWcount)->mvs[0].y);
2023    
2024    /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
2025            if (iMinSAD <= thresh2) {
2026                    if (MotionFlags & PMV_QUICKSTOP16)
2027                            goto EPZS16_Terminate_without_Refine;
2028                    if (MotionFlags & PMV_EARLYSTOP16)
2029                            goto EPZS16_Terminate_with_Refine;
2030            }
2031    
2032    /************ (if Diamond Search)  **************/
2033    
2034            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2035    
2036            if (MotionFlags & PMV_USESQUARES16)
2037                    MainSearchPtr = Square16_MainSearch;
2038            else
2039             if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2040                    MainSearchPtr = AdvDiamond16_MainSearch;
2041            else
2042                    MainSearchPtr = Diamond16_MainSearch;
2043    
2044    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2045    
2046            iSAD =
2047                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2048                                                      currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,
2049                                                      min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2050    
2051            if (iSAD < iMinSAD) {
2052                    *currMV = newMV;
2053                    iMinSAD = iSAD;
2054            }
2055    
2056    
2057            if (MotionFlags & PMV_EXTSEARCH16) {
2058    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2059    
2060                    if (!(MVequal(pmv[0], backupMV))) {
2061                            iSAD =
2062                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2063                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,
2064                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2065                                                                      2, iFcode, iQuant, 0);
2066                    }
2067    
2068                    if (iSAD < iMinSAD) {
2069                            *currMV = newMV;
2070                            iMinSAD = iSAD;
2071                    }
2072    
2073                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2074                            iSAD =
2075                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2076                                                                      iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,
2077                                                                      max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2078    
2079                            if (iSAD < iMinSAD) {
2080                                    *currMV = newMV;
2081                                    iMinSAD = iSAD;
2082                            }
2083                    }
2084            }
2085    
2086    /***************        Choose best MV found     **************/
2087    
2088      EPZS16_Terminate_with_Refine:
2089            if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
2090                    iMinSAD =
2091                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2092                                                             iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,
2093                                                             iFcode, iQuant, iEdgedWidth);
2094    
2095      EPZS16_Terminate_without_Refine:
2096    
2097            *oldMB = *prevMB;
2098    
2099            currPMV->x = currMV->x - pmv[0].x;
2100            currPMV->y = currMV->y - pmv[0].y;
2101            return iMinSAD;
2102    }
2103    
2104    
2105    int32_t
2106    EPZSSearch8(const uint8_t * const pRef,
2107                            const uint8_t * const pRefH,
2108                            const uint8_t * const pRefV,
2109                            const uint8_t * const pRefHV,
2110                            const IMAGE * const pCur,
2111                            const int x,
2112                            const int y,
2113                            const int start_x,
2114                            const int start_y,
2115                            const uint32_t MotionFlags,
2116                            const uint32_t iQuant,
2117                            const uint32_t iFcode,
2118                            const MBParam * const pParam,
2119                            const MACROBLOCK * const pMBs,
2120                            const MACROBLOCK * const prevMBs,
2121                            VECTOR * const currMV,
2122                            VECTOR * const currPMV)
2123    {
2124    /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
2125    
2126            const uint32_t iWcount = pParam->mb_width;
2127            const int32_t iWidth = pParam->width;
2128            const int32_t iHeight = pParam->height;
2129            const int32_t iEdgedWidth = pParam->edged_width;
2130    
2131            const uint8_t *cur = pCur->y + x * 8 + y * 8 * iEdgedWidth;
2132    
2133            int32_t iDiamondSize = 1;
2134    
2135            int32_t min_dx;
2136            int32_t max_dx;
2137            int32_t min_dy;
2138            int32_t max_dy;
2139    
2140            VECTOR newMV;
2141            VECTOR backupMV;
2142    
2143            VECTOR pmv[4];
2144            int32_t psad[8];
2145    
2146            const int32_t iSubBlock = ((y & 1) << 1) + (x & 1);
2147    
2148    //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2149            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
2150    
2151            int32_t bPredEq;
2152            int32_t iMinSAD, iSAD = 9999;
2153    
2154            MainSearch8FuncPtr MainSearchPtr;
2155    
2156    /* Get maximum range */
2157            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2158                              iFcode);
2159    
2160    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2161    
2162            if (!(MotionFlags & PMV_HALFPEL8)) {
2163                    min_dx = EVEN(min_dx);
2164                    max_dx = EVEN(max_dx);
2165                    min_dy = EVEN(min_dy);
2166                    max_dy = EVEN(max_dy);
2167            }
2168            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2169            //bPredEq = get_pmvdata(pMBs, x >> 1, y >> 1, iWcount, iSubBlock, pmv, psad);
2170            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2171    
2172    
2173    /* Step 4: Calculate SAD around the Median prediction.
2174            MinSAD=SAD
2175            If Motion Vector equal to Previous frame motion vector
2176                    and MinSAD<PrevFrmSAD goto Step 10.
2177            If SAD<=256 goto Step 10.
2178    */
2179    
2180    // Prepare for main loop
2181    
2182    
2183            if (!(MotionFlags & PMV_HALFPEL8)) {
2184                    currMV->x = EVEN(currMV->x);
2185                    currMV->y = EVEN(currMV->y);
2186            }
2187    
2188            if (currMV->x > max_dx)
2189                    currMV->x = max_dx;
2190            if (currMV->x < min_dx)
2191                    currMV->x = min_dx;
2192            if (currMV->y > max_dy)
2193                    currMV->y = max_dy;
2194            if (currMV->y < min_dy)
2195                    currMV->y = min_dy;
2196    
2197    /***************** This is predictor SET A: only median prediction ******************/
2198    
2199    
2200            iMinSAD =
2201                    sad8(cur,
2202                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2203                                                    iEdgedWidth), iEdgedWidth);
2204            iMinSAD +=
2205                    calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y,
2206                                             (uint8_t) iFcode, iQuant);
2207    
2208    
2209    // thresh1 is fixed to 256
2210            if (iMinSAD < 256 / 4) {
2211                    if (MotionFlags & PMV_QUICKSTOP8)
2212                            goto EPZS8_Terminate_without_Refine;
2213                    if (MotionFlags & PMV_EARLYSTOP8)
2214                            goto EPZS8_Terminate_with_Refine;
2215            }
2216    
2217    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2218    
2219    
2220    // MV=(0,0) is often a good choice
2221            CHECK_MV8_ZERO;
2222    
2223    // previous frame MV
2224            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x, prevMB->mvs[iSubBlock].y);
2225    
2226    // left neighbour, if allowed
2227            if (psad[1] != MV_MAX_ERROR) {
2228                    if (!(MotionFlags & PMV_HALFPEL8)) {
2229                            pmv[1].x = EVEN(pmv[1].x);
2230                            pmv[1].y = EVEN(pmv[1].y);
2231                    }
2232                    CHECK_MV8_CANDIDATE(pmv[1].x, pmv[1].y);
2233            }
2234    // top neighbour, if allowed
2235            if (psad[2] != MV_MAX_ERROR) {
2236                    if (!(MotionFlags & PMV_HALFPEL8)) {
2237                            pmv[2].x = EVEN(pmv[2].x);
2238                            pmv[2].y = EVEN(pmv[2].y);
2239                    }
2240                    CHECK_MV8_CANDIDATE(pmv[2].x, pmv[2].y);
2241    
2242    // top right neighbour, if allowed
2243                    if (psad[3] != MV_MAX_ERROR) {
2244                            if (!(MotionFlags & PMV_HALFPEL8)) {
2245                                    pmv[3].x = EVEN(pmv[3].x);
2246                                    pmv[3].y = EVEN(pmv[3].y);
2247                            }
2248                            CHECK_MV8_CANDIDATE(pmv[3].x, pmv[3].y);
2249                    }
2250            }
2251    
2252    /*  // this bias is zero anyway, at the moment!
2253    
2254            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
2255                    iMinSAD -= MV8_00_BIAS;
2256    
2257    */
2258    
2259    /* Terminate if MinSAD <= T_2
2260       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
2261    */
2262    
2263            if (iMinSAD < 512 / 4) {        /* T_2 == 512/4 hardcoded */
2264                    if (MotionFlags & PMV_QUICKSTOP8)
2265                            goto EPZS8_Terminate_without_Refine;
2266                    if (MotionFlags & PMV_EARLYSTOP8)
2267                            goto EPZS8_Terminate_with_Refine;
2268            }
2269    
2270    /************ (Diamond Search)  **************/
2271    
2272            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2273    
2274            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2275                    iDiamondSize *= 2;
2276    
2277    /* default: use best prediction as starting point for one call of EPZS_MainSearch */
2278    
2279    // there is no EPZS^2 for inter4v at the moment
2280    
2281    //  if (MotionFlags & PMV_USESQUARES8)
2282    //      MainSearchPtr = Square8_MainSearch;
2283    //  else
2284    
2285            if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2286                    MainSearchPtr = AdvDiamond8_MainSearch;
2287            else
2288                    MainSearchPtr = Diamond8_MainSearch;
2289    
2290            iSAD =
2291                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2292                                                      currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,
2293                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2294                                                      iQuant, 0);
2295    
2296    
2297            if (iSAD < iMinSAD) {
2298                    *currMV = newMV;
2299                    iMinSAD = iSAD;
2300            }
2301    
2302            if (MotionFlags & PMV_EXTSEARCH8) {
2303    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2304    
2305                    if (!(MVequal(pmv[0], backupMV))) {
2306                            iSAD =
2307                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2308                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,
2309                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2310                                                                      iDiamondSize, iFcode, iQuant, 0);
2311    
2312                            if (iSAD < iMinSAD) {
2313                                    *currMV = newMV;
2314                                    iMinSAD = iSAD;
2315                            }
2316                    }
2317    
2318                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2319                            iSAD =
2320                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2321                                                                      iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,
2322                                                                      max_dy, iEdgedWidth, iDiamondSize, iFcode,
2323                                                                      iQuant, 0);
2324    
2325                            if (iSAD < iMinSAD) {
2326                                    *currMV = newMV;
2327                                    iMinSAD = iSAD;
2328                            }
2329                    }
2330            }
2331    
2332    /***************        Choose best MV found     **************/
2333    
2334      EPZS8_Terminate_with_Refine:
2335            if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step
2336                    iMinSAD =
2337                            Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2338                                                            iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,
2339                                                            iFcode, iQuant, iEdgedWidth);
2340    
2341      EPZS8_Terminate_without_Refine:
2342    
2343            currPMV->x = currMV->x - pmv[0].x;
2344            currPMV->y = currMV->y - pmv[0].y;
2345            return iMinSAD;
2346    }
2347    
2348    
2349    
2350    int32_t
2351    PMVfastIntSearch16(const uint8_t * const pRef,
2352                                    const uint8_t * const pRefH,
2353                                    const uint8_t * const pRefV,
2354                                    const uint8_t * const pRefHV,
2355                                    const IMAGE * const pCur,
2356                                    const int x,
2357                                    const int y,
2358                                    const uint32_t MotionFlags,
2359                                    const uint32_t iQuant,
2360                                    const uint32_t iFcode,
2361                                    const MBParam * const pParam,
2362                                    const MACROBLOCK * const pMBs,
2363                                    const MACROBLOCK * const prevMBs,
2364                                    VECTOR * const currMV,
2365                                    VECTOR * const currPMV)
2366    {
2367            const uint32_t iWcount = pParam->mb_width;
2368            const int32_t iWidth = pParam->width;
2369            const int32_t iHeight = pParam->height;
2370            const int32_t iEdgedWidth = pParam->edged_width;
2371    
2372            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
2373            const VECTOR zeroMV = { 0, 0 };
2374    
2375            int32_t iDiamondSize;
2376    
2377            int32_t min_dx;
2378            int32_t max_dx;
2379            int32_t min_dy;
2380            int32_t max_dy;
2381    
2382            int32_t iFound;
2383    
2384            VECTOR newMV;
2385            VECTOR backupMV;                        /* just for PMVFAST */
2386    
2387            VECTOR pmv[4];
2388            int32_t psad[4];
2389    
2390            MainSearch16FuncPtr MainSearchPtr;
2391    
2392            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2393            MACROBLOCK *const pMB = pMBs + x + y * iWcount;
2394    
2395            int32_t threshA, threshB;
2396            int32_t bPredEq;
2397            int32_t iMinSAD, iSAD;
2398    
2399    /* Get maximum range */
2400            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2401                              iFcode);
2402    
2403    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2404    
2405            if ((x == 0) && (y == 0)) {
2406                    threshA = 512;
2407                    threshB = 1024;
2408    
2409                    bPredEq = 0;
2410                    psad[0] = psad[1] = psad[2] = psad[3] = 0;
2411                    *currMV = pmv[0] = pmv[1] = pmv[2] = pmv[3] = zeroMV;
2412    
2413            } else {
2414                    threshA = psad[0];
2415                    threshB = threshA + 256;
2416                    if (threshA < 512)
2417                            threshA = 512;
2418                    if (threshA > 1024)
2419                            threshA = 1024;
2420                    if (threshB > 1792)
2421                            threshB = 1792;
2422    
2423                    bPredEq = get_ipmvdata(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2424                    *currMV = pmv[0];                       /* current best := prediction */
2425            }
2426    
2427            iFound = 0;
2428    
2429    /* Step 4: Calculate SAD around the Median prediction.
2430       MinSAD=SAD
2431       If Motion Vector equal to Previous frame motion vector
2432       and MinSAD<PrevFrmSAD goto Step 10.
2433       If SAD<=256 goto Step 10.
2434    */
2435    
2436            if (currMV->x > max_dx) {
2437                    currMV->x = EVEN(max_dx);
2438            }
2439            if (currMV->x < min_dx) {
2440                    currMV->x = EVEN(min_dx);
2441            }
2442            if (currMV->y > max_dy) {
2443                    currMV->y = EVEN(max_dy);
2444            }
2445            if (currMV->y < min_dy) {
2446                    currMV->y = EVEN(min_dy);
2447            }
2448    
2449            iMinSAD =
2450                    sad16(cur,
2451                              get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2452                                                     iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2453            iMinSAD +=
2454                    calc_delta_16(currMV->x - pmv[0].x, currMV->y - pmv[0].y,
2455                                              (uint8_t) iFcode, iQuant);
2456    
2457            if ((iMinSAD < 256) ||
2458                    ((MVequal(*currMV, prevMB->i_mvs[0])) &&
2459                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2460                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
2461                    {
2462                            if (!MVzero(*currMV)) {
2463                                    iMinSAD += MV16_00_BIAS;
2464                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
2465                                    iMinSAD -= MV16_00_BIAS;
2466                            }
2467                    }
2468    
2469                    if (MotionFlags & PMV_EARLYSTOP16)
2470                            goto PMVfastInt16_Terminate_with_Refine;
2471            }
2472    
2473    
2474    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2475       vector of the median.
2476       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2477    */
2478    
2479            if ((bPredEq) && (MVequal(pmv[0], prevMB->i_mvs[0])))
2480                    iFound = 2;
2481    
2482    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2483       Otherwise select large Diamond Search.
2484    */
2485    
2486            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
2487                    iDiamondSize = 2;               // halfpel units!
2488            else
2489                    iDiamondSize = 4;               // halfpel units!
2490    
2491    /*
2492       Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
2493       Also calculate (0,0) but do not subtract offset.
2494       Let MinSAD be the smallest SAD up to this point.
2495       If MV is (0,0) subtract offset.
2496    */
2497    
2498    // (0,0) is often a good choice
2499    
2500            if (!MVzero(pmv[0]))
2501                    CHECK_MV16_ZERO;
2502    
2503    // previous frame MV is always possible
2504    
2505            if (!MVzero(prevMB->i_mvs[0]))
2506                    if (!MVequal(prevMB->i_mvs[0], pmv[0]))
2507                            CHECK_MV16_CANDIDATE(prevMB->i_mvs[0].x, prevMB->i_mvs[0].y);
2508    
2509    // left neighbour, if allowed
2510    
2511            if (!MVzero(pmv[1]))
2512                    if (!MVequal(pmv[1], prevMB->i_mvs[0]))
2513                            if (!MVequal(pmv[1], pmv[0]))
2514                                    CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
2515    
2516    // top neighbour, if allowed
2517            if (!MVzero(pmv[2]))
2518                    if (!MVequal(pmv[2], prevMB->i_mvs[0]))
2519                            if (!MVequal(pmv[2], pmv[0]))
2520                                    if (!MVequal(pmv[2], pmv[1]))
2521                                            CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
2522    
2523    // top right neighbour, if allowed
2524                                            if (!MVzero(pmv[3]))
2525                                                    if (!MVequal(pmv[3], prevMB->i_mvs[0]))
2526                                                            if (!MVequal(pmv[3], pmv[0]))
2527                                                                    if (!MVequal(pmv[3], pmv[1]))
2528                                                                            if (!MVequal(pmv[3], pmv[2]))
2529                                                                                    CHECK_MV16_CANDIDATE(pmv[3].x,
2530                                                                                                                             pmv[3].y);
2531    
2532            if ((MVzero(*currMV)) &&
2533                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2534                    iMinSAD -= MV16_00_BIAS;
2535    
2536    
2537    /* Step 6: If MinSAD <= thresa goto Step 10.
2538       If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
2539    */
2540    
2541            if ((iMinSAD <= threshA) ||
2542                    (MVequal(*currMV, prevMB->i_mvs[0]) &&
2543                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2544    
2545                    if (MotionFlags & PMV_EARLYSTOP16)
2546                            goto PMVfastInt16_Terminate_with_Refine;
2547            }
2548    
2549    
2550    /************ (Diamond Search)  **************/
2551    /*
2552       Step 7: Perform Diamond search, with either the small or large diamond.
2553       If Found=2 only examine one Diamond pattern, and afterwards goto step 10
2554       Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
2555       If center then goto step 10.
2556       Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
2557       Refine by using small diamond and goto step 10.
2558    */
2559    
2560            if (MotionFlags & PMV_USESQUARES16)
2561                    MainSearchPtr = Square16_MainSearch;
2562            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2563                    MainSearchPtr = AdvDiamond16_MainSearch;
2564            else
2565                    MainSearchPtr = Diamond16_MainSearch;
2566    
2567            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2568    
2569    
2570    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2571            iSAD =
2572                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2573                                                      currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx,
2574                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2575                                                      iQuant, iFound);
2576    
2577            if (iSAD < iMinSAD) {
2578                    *currMV = newMV;
2579                    iMinSAD = iSAD;
2580            }
2581    
2582            if (MotionFlags & PMV_EXTSEARCH16) {
2583    /* extended: search (up to) two more times: orignal prediction and (0,0) */
2584    
2585                    if (!(MVequal(pmv[0], backupMV))) {
2586                            iSAD =
2587                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2588                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, pmv,
2589                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2590                                                                      iDiamondSize, iFcode, iQuant, iFound);
2591    
2592                            if (iSAD < iMinSAD) {
2593                                    *currMV = newMV;
2594                                    iMinSAD = iSAD;
2595                            }
2596                    }
2597    
2598                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2599                            iSAD =
2600                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2601                                                                      iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy,
2602                                                                      max_dy, iEdgedWidth, iDiamondSize, iFcode,
2603                                                                      iQuant, iFound);
2604    
2605                            if (iSAD < iMinSAD) {
2606                                    *currMV = newMV;
2607                                    iMinSAD = iSAD;
2608                            }
2609                    }
2610            }
2611    
2612    /*
2613       Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.
2614    */
2615    
2616    PMVfastInt16_Terminate_with_Refine:
2617    
2618            pMB->i_mvs[0] = pMB->i_mvs[1] = pMB->i_mvs[2] = pMB->i_mvs[3] = pMB->i_mv16 = *currMV;
2619            pMB->i_sad8[0] = pMB->i_sad8[1] = pMB->i_sad8[2] = pMB->i_sad8[3] = pMB->i_sad16 = iMinSAD;
2620    
2621            if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
2622                    iMinSAD =
2623                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2624                                                             iMinSAD, pmv, min_dx, max_dx, min_dy, max_dy,
2625                                                             iFcode, iQuant, iEdgedWidth);
2626    
2627            pmv[0] = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          // get _REAL_ prediction (halfpel possible)
2628    
2629    PMVfastInt16_Terminate_without_Refine:
2630            currPMV->x = currMV->x - pmv[0].x;
2631            currPMV->y = currMV->y - pmv[0].y;
2632            return iMinSAD;
2633    }
2634    
2635    
2636    
2637    /* ***********************************************************
2638            bvop motion estimation
2639    // TODO: need to incorporate prediction here (eg. sad += calc_delta_16)
2640    ***************************************************************/
2641    
2642    
2643    void
2644    MotionEstimationBVOP(MBParam * const pParam,
2645                                             FRAMEINFO * const frame,
2646                                             // forward (past) reference
2647                                             const MACROBLOCK * const f_mbs,
2648                                             const IMAGE * const f_ref,
2649                                             const IMAGE * const f_refH,
2650                                             const IMAGE * const f_refV,
2651                                             const IMAGE * const f_refHV,
2652                                             // backward (future) reference
2653                                             const MACROBLOCK * const b_mbs,
2654                                             const IMAGE * const b_ref,
2655                                             const IMAGE * const b_refH,
2656                                             const IMAGE * const b_refV,
2657                                             const IMAGE * const b_refHV)
2658    {
2659            const uint32_t mb_width = pParam->mb_width;
2660            const uint32_t mb_height = pParam->mb_height;
2661            const int32_t edged_width = pParam->edged_width;
2662    
2663            uint32_t i, j;
2664    
2665            int32_t f_sad16;
2666            int32_t b_sad16;
2667            int32_t i_sad16;
2668            int32_t d_sad16;
2669            int32_t best_sad;
2670    
2671            VECTOR pmv_dontcare;
2672    
2673            // note: i==horizontal, j==vertical
2674            for (j = 0; j < mb_height; j++) {
2675                    for (i = 0; i < mb_width; i++) {
2676                            MACROBLOCK *mb = &frame->mbs[i + j * mb_width];
2677                            const MACROBLOCK *f_mb = &f_mbs[i + j * mb_width];
2678                            const MACROBLOCK *b_mb = &b_mbs[i + j * mb_width];
2679    
2680                            if (b_mb->mode == MODE_INTER && b_mb->cbp == 0 &&
2681                                    b_mb->mvs[0].x == 0 && b_mb->mvs[0].y == 0) {
2682                                    mb->mode = MODE_NOT_CODED;
2683                                    mb->mvs[0].x = 0;
2684                                    mb->mvs[0].y = 0;
2685                                    mb->b_mvs[0].x = 0;
2686                                    mb->b_mvs[0].y = 0;
2687                                    continue;
2688                            }
2689                    /* force F_SAD16
2690                            f_sad16 = 100;
2691                            b_sad16 = 65535;
2692    
2693                            mb->mode = MODE_FORWARD;
2694                            mb->mvs[0].x = 1;
2695                            mb->mvs[0].y = 1;
2696                            mb->b_mvs[0].x = 1;
2697                            mb->b_mvs[0].y = 1;
2698                            continue;
2699                     ^^ force F_SAD16 */
2700    
2701    
2702                            // forward search
2703                            f_sad16 =
2704                                    SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2705                                                     &frame->image, i, j, frame->motion_flags,
2706                                                     frame->quant, frame->fcode, pParam,
2707                                                     f_mbs,  f_mbs, /* todo */
2708                                                     &mb->mvs[0], &pmv_dontcare);   // ignore pmv
2709    
2710                            // backward search
2711                            b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,
2712                                                    &frame->image, i, j, frame->motion_flags,
2713                                                    frame->quant, frame->bcode, pParam,
2714                                                    b_mbs, b_mbs,   /* todo */
2715                                                    &mb->b_mvs[0], &pmv_dontcare);  // ignore pmv
2716    
2717                            // interpolate search (simple, but effective)
2718                            i_sad16 = 65535;
2719    
2720                            /*
2721                            x/y range somewhat buggy
2722                            i_sad16 =
2723                                    sad16bi_c(frame->image.y + i * 16 + j * 16 * edged_width,
2724                                                      get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,
2725                                                                      i, j, 16, mb->mvs[0].x, mb->mvs[0].y,
2726                                                                      edged_width), get_ref(b_ref->y, b_refH->y,
2727                                                                                                                    b_refV->y, b_refHV->y,
2728                                                                                                                    i, j, 16,
2729                                                                                                                    mb->b_mvs[0].x,
2730                                                                                                                    mb->b_mvs[0].x,
2731                                                                                                                    edged_width),
2732                                                      edged_width);
2733                            */
2734    
2735                            // TODO: direct search
2736                            // predictor + range of [-32,32]
2737                            d_sad16 = 65535;
2738    
2739    
2740                            if (f_sad16 < b_sad16) {
2741                                    best_sad = f_sad16;
2742                                    mb->mode = MODE_FORWARD;
2743                            } else {
2744                                    best_sad = b_sad16;
2745                                    mb->mode = MODE_BACKWARD;
2746                            }
2747    
2748                            if (i_sad16 < best_sad) {
2749                                    best_sad = i_sad16;
2750                                    mb->mode = MODE_INTERPOLATE;
2751                            }
2752    
2753                            if (d_sad16 < best_sad) {
2754                                    best_sad = d_sad16;
2755                                    mb->mode = MODE_DIRECT;
2756                            }
2757    
2758                    }
2759            }
2760    }

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

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