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

Legend:
Removed from v.78  
changed lines
  Added in v.267

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