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

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

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

revision 115, Thu Apr 11 10:18:40 2002 UTC revision 444, Sat Sep 7 13:41:13 2002 UTC
# Line 1  Line 1 
1  /**************************************************************************  /*****************************************************************************
2   *   *
3   *  Modifications:   *  XVID MPEG-4 VIDEO CODEC
4     *  - Motion Estimation module -
5   *   *
6   *  02.04.2002 add EPZS(^2) as ME algorithm, use PMV_USESQUARES to choose between   *  Copyright(C) 2002 Christoph Lampert <gruel@web.de>
7   *             EPZS and EPZS^2   *  Copyright(C) 2002 Michael Militzer <michael@xvid.org>
8   *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop   *  Copyright(C) 2002 Edouard Gomez <ed.gomez@wanadoo.fr>
  *             PMVFast_Refine to support multiple searches with different start points  
  *  07.01.2002 uv-block-based interpolation  
  *  06.01.2002 INTER/INTRA-decision is now done before any SEARCH8 (speedup)  
  *             changed INTER_BIAS to 150 (as suggested by suxen_drol)  
  *             removed halfpel refinement step in PMVfastSearch8 + quality=5  
  *             added new quality mode = 6 which performs halfpel refinement  
  *             filesize difference between quality 5 and 6 is smaller than 1%  
  *             (Isibaar)  
  *  31.12.2001 PMVfastSearch16 and PMVfastSearch8 (gruel)  
  *  30.12.2001 get_range/MotionSearchX simplified; blue/green bug fix  
  *  22.12.2001 commented best_point==99 check  
  *  19.12.2001 modified get_range (purple bug fix)  
  *  15.12.2001 moved pmv displacement from mbprediction  
  *  02.12.2001 motion estimation/compensation split (Isibaar)  
  *  16.11.2001 rewrote/tweaked search algorithms; pross@cs.rmit.edu.au  
  *  10.11.2001 support for sad16/sad8 functions  
  *  28.08.2001 reactivated MODE_INTER4V for EXT_MODE  
  *  24.08.2001 removed MODE_INTER4V_Q, disabled MODE_INTER4V for EXT_MODE  
  *  22.08.2001 added MODE_INTER4V_Q  
  *  20.08.2001 added pragma to get rid of internal compiler error with VC6  
  *             idea by Cyril. Thanks.  
9   *   *
10   *  Michael Militzer <isibaar@videocoding.de>   *  This program is an implementation of a part of one or more MPEG-4
11     *  Video tools as specified in ISO/IEC 14496-2 standard.  Those intending
12     *  to use this software module in hardware or software products are
13     *  advised that its use may infringe existing patents or copyrights, and
14     *  any such use would be at such party's own risk.  The original
15     *  developer of this software module and his/her company, and subsequent
16     *  editors and their companies, will have no liability for use of this
17     *  software or modifications or derivatives thereof.
18   *   *
19   **************************************************************************/   *  This program is free software; you can redistribute it and/or modify
20     *  it under the terms of the GNU General Public License as published by
21     *  the Free Software Foundation; either version 2 of the License, or
22     *  (at your option) any later version.
23     *
24     *  This program is distributed in the hope that it will be useful,
25     *  but WITHOUT ANY WARRANTY; without even the implied warranty of
26     *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27     *  GNU General Public License for more details.
28     *
29     *  You should have received a copy of the GNU General Public License
30     *  along with this program; if not, write to the Free Software
31     *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
32     *
33     *************************************************************************/
34    
35  #include <assert.h>  #include <assert.h>
36  #include <stdio.h>  #include <stdio.h>
# Line 40  Line 41 
41  #include "../prediction/mbprediction.h"  #include "../prediction/mbprediction.h"
42  #include "../global.h"  #include "../global.h"
43  #include "../utils/timer.h"  #include "../utils/timer.h"
44    #include "motion.h"
45  #include "sad.h"  #include "sad.h"
46    
 // 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 PMVfastSearch16(  
                                         const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const uint32_t MotionFlags,  
                                         const MBParam * const pParam,  
                                         MACROBLOCK * const pMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
 int32_t EPZSSearch16(  
                                         const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const uint32_t MotionFlags,  
                                         const MBParam * const pParam,  
                                         MACROBLOCK * const pMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
   
 int32_t PMVfastSearch8(  
                                         const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const int start_x, int start_y,  
                                         const uint32_t MotionFlags,  
                                         const MBParam * const pParam,  
                                         MACROBLOCK * const pMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
 int32_t EPZSSearch8(  
                                         const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const int start_x, int start_y,  
                                         const uint32_t MotionFlags,  
                                         const MBParam * const pParam,  
                                         MACROBLOCK * const pMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
47    
 typedef int32_t (MainSearch16Func)(  
         const uint8_t * const pRef,  
         const uint8_t * const pRefH,  
         const uint8_t * const pRefV,  
         const uint8_t * const pRefHV,  
         const uint8_t * const cur,  
         const int x, const int y,  
         int32_t startx, int32_t starty,  
         int32_t iMinSAD,  
         VECTOR * const currMV,  
         const VECTOR * const pmv,  
         const int32_t min_dx, const int32_t max_dx,  
         const int32_t min_dy, const int32_t max_dy,  
         const int32_t iEdgedWidth,  
         const int32_t iDiamondSize,  
         const int32_t iFcode,  
         const int32_t iQuant,  
         int iFound);  
48    
49  typedef MainSearch16Func* MainSearch16FuncPtr;  static int32_t lambda_vec16[32] =       /* rounded values for lambda param for weight of motion bits as in modified H.26L */
50    { 0, (int) (1.00235 + 0.5), (int) (1.15582 + 0.5), (int) (1.31976 + 0.5),
51                    (int) (1.49591 + 0.5), (int) (1.68601 + 0.5),
52            (int) (1.89187 + 0.5), (int) (2.11542 + 0.5), (int) (2.35878 + 0.5),
53                    (int) (2.62429 + 0.5), (int) (2.91455 + 0.5),
54            (int) (3.23253 + 0.5), (int) (3.58158 + 0.5), (int) (3.96555 + 0.5),
55                    (int) (4.38887 + 0.5), (int) (4.85673 + 0.5),
56            (int) (5.37519 + 0.5), (int) (5.95144 + 0.5), (int) (6.59408 + 0.5),
57                    (int) (7.31349 + 0.5), (int) (8.12242 + 0.5),
58            (int) (9.03669 + 0.5), (int) (10.0763 + 0.5), (int) (11.2669 + 0.5),
59                    (int) (12.6426 + 0.5), (int) (14.2493 + 0.5),
60            (int) (16.1512 + 0.5), (int) (18.442 + 0.5), (int) (21.2656 + 0.5),
61                    (int) (24.8580 + 0.5), (int) (29.6436 + 0.5),
62            (int) (36.4949 + 0.5)
63    };
64    
65    static int32_t *lambda_vec8 = lambda_vec16;     /* same table for INTER and INTER4V for now */
66    
 typedef int32_t (MainSearch8Func)(  
         const uint8_t * const pRef,  
         const uint8_t * const pRefH,  
         const uint8_t * const pRefV,  
         const uint8_t * const pRefHV,  
         const uint8_t * const cur,  
         const int x, const int y,  
         int32_t startx, int32_t starty,  
         int32_t iMinSAD,  
         VECTOR * const currMV,  
         const VECTOR * const pmv,  
         const int32_t min_dx, const int32_t max_dx,  
         const int32_t min_dy, const int32_t max_dy,  
         const int32_t iEdgedWidth,  
         const int32_t iDiamondSize,  
         const int32_t iFcode,  
         const int32_t iQuant,  
         int iFound);  
67    
 typedef MainSearch8Func* MainSearch8FuncPtr;  
68    
69  // mv.length table  // mv.length table
70  static const uint32_t mvtab[33] = {  static const uint32_t mvtab[33] = {
# Line 181  Line 75 
75  };  };
76    
77    
78  static __inline uint32_t mv_bits(int32_t component, const uint32_t iFcode)  static __inline uint32_t
79    mv_bits(int32_t component,
80                    const uint32_t iFcode)
81  {  {
82      if (component == 0)      if (component == 0)
83                  return 1;                  return 1;
# Line 189  Line 85 
85      if (component < 0)      if (component < 0)
86                  component = -component;                  component = -component;
87    
88      if (iFcode == 1)          if (iFcode == 1) {
     {  
89                  if (component > 32)                  if (component > 32)
90                      component = 32;                      component = 32;
91    
# Line 207  Line 102 
102  }  }
103    
104    
105  static __inline uint32_t calc_delta_16(const int32_t dx, const int32_t dy, const uint32_t iFcode)  static __inline uint32_t
106  {  calc_delta_16(const int32_t dx,
107          return NEIGH_TEND_16X16 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));                            const int32_t dy,
108  }                            const uint32_t iFcode,
109                              const uint32_t iQuant)
110  static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode)  {
111            return NEIGH_TEND_16X16 * lambda_vec16[iQuant] * (mv_bits(dx, iFcode) +
112  {                                                                                                            mv_bits(dy, iFcode));
113      return NEIGH_TEND_8X8 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));  }
114  }  
115    static __inline uint32_t
116    calc_delta_8(const int32_t dx,
117                             const int32_t dy,
118                             const uint32_t iFcode,
119  /* calculate the min/max range (in halfpixels)                           const uint32_t iQuant)
120          relative to the _MACROBLOCK_ position  {
121  */          return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) +
122                                                                                                       mv_bits(dy, iFcode));
123  static void __inline get_range(  }
124          int32_t * const min_dx, int32_t * const max_dx,  
125          int32_t * const min_dy, int32_t * const max_dy,  bool
126          const uint32_t x, const uint32_t y,  MotionEstimation(MBParam * const pParam,
127          const uint32_t block_sz,                                        // block dimension, 8 or 16                                   FRAMEINFO * const current,
128          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  
 //#define SEARCH16      FullSearch16  
 //#define SEARCH16      EPZSSearch16  
 #endif  
   
 #ifndef SEARCH8  
 #define SEARCH8         PMVfastSearch8  
 //#define SEARCH8       EPZSSearch8  
 #endif  
   
 bool MotionEstimation(  
         MACROBLOCK * const pMBs,  
         MBParam * const pParam,  
         const IMAGE * const pRef,  
129          const IMAGE * const pRefH,          const IMAGE * const pRefH,
130          const IMAGE * const pRefV,          const IMAGE * const pRefV,
131          const IMAGE * const pRefHV,          const IMAGE * const pRefHV,
         IMAGE * const pCurrent,  
132          const uint32_t iLimit)          const uint32_t iLimit)
   
133  {  {
134          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
135          const uint32_t iHcount = pParam->mb_height;          const uint32_t iHcount = pParam->mb_height;
136            MACROBLOCK *const pMBs = current->mbs;
137            MACROBLOCK *const prevMBs = reference->mbs;
138            const IMAGE *const pCurrent = &current->image;
139            const IMAGE *const pRef = &reference->image;
140    
141            static const VECTOR zeroMV = { 0, 0 };
142            VECTOR predMV;
143    
144            int32_t x, y;
145            int32_t iIntra = 0;
146            VECTOR pmv;
147    
148          uint32_t i, j, iIntra = 0;          if (sadInit)
149                    (*sadInit) ();
150    
151          VECTOR mv16;          for (y = 0; y < iHcount; y++)   {
152          VECTOR pmv16;                  for (x = 0; x < iWcount; x ++)  {
153    
154          int32_t sad8 = 0;                          MACROBLOCK *const pMB = &pMBs[x + y * iWcount];
         int32_t sad16;  
         int32_t deviation;  
   
         if (sadInit);  
                 (*sadInit)();  
155    
156          // note: i==horizontal, j==vertical                          if (pMB->mode == MODE_NOT_CODED)
157          for (i = 0; i < iHcount; i++)                                  continue;
                 for (j = 0; j < iWcount; j++)  
                 {  
                         MACROBLOCK *pMB = &pMBs[j + i * iWcount];  
158    
159                          sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                          predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
                                          j, i, pParam->motion_flags,  
                                          pParam, pMBs, &mv16, &pmv16);  
                         pMB->sad16=sad16;  
160    
161                            pMB->sad16 =
162                                    SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
163                                                     x, y, predMV.x, predMV.y, predMV.x, predMV.y,
164                                                     current->motion_flags, current->quant,
165                                                     current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,
166                                                     &pMB->pmvs[0]);
167    
168                          /* decide: MODE_INTER or MODE_INTRA                          if (0 < (pMB->sad16 - MV16_INTER_BIAS)) {
169                             if (dev_intra < sad_inter - 2 * nb) use_intra                                  int32_t deviation;
                         */  
170    
171                          deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width);                                  deviation =
172                                            dev16(pCurrent->y + x * 16 + y * 16 * pParam->edged_width,
173                                                      pParam->edged_width);
174    
175                          if (deviation < (sad16 - INTER_BIAS))                                  if (deviation < (pMB->sad16 - MV16_INTER_BIAS)) {
                         {  
176                                  pMB->mode = MODE_INTRA;                                  pMB->mode = MODE_INTRA;
177                                  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] =
178                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;                                                  pMB->mvs[3] = zeroMV;
179                                            pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
180                                                    pMB->sad8[3] = 0;
181    
182                                  iIntra++;                                  iIntra++;
183                                  if(iIntra >= iLimit)                                  if(iIntra >= iLimit)
# Line 373  Line 185 
185    
186                                  continue;                                  continue;
187                          }                          }
   
                         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];  
188                          }                          }
189    
190                            pmv = pMB->pmvs[0];
191                            if (current->global_flags & XVID_INTER4V)
192                                    if ((!(current->global_flags & XVID_LUMIMASKING) ||
193                                             pMB->dquant == NO_CHANGE)) {
194                                            int32_t sad8 = IMV16X16 * current->quant;
195    
196                                            if (sad8 < pMB->sad16) {
197                                                    sad8 += pMB->sad8[0] =
198                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
199                                                                            pCurrent, 2 * x, 2 * y,
200                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
201                                                                            current->motion_flags,
202                                                                            current->quant, current->fcode, pParam,
203                                                                            pMBs, prevMBs, &pMB->mvs[0],
204                                                                            &pMB->pmvs[0]);
205                                            }
206                                            if (sad8 < pMB->sad16) {
207    
208                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 1);
209                                                    sad8 += pMB->sad8[1] =
210                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
211                                                                            pCurrent, 2 * x + 1, 2 * y,
212                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
213                                                                            current->motion_flags,
214                                                                            current->quant, current->fcode, pParam,
215                                                                            pMBs, prevMBs, &pMB->mvs[1],
216                                                                            &pMB->pmvs[1]);
217                                            }
218                                            if (sad8 < pMB->sad16) {
219                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 2);
220                                                    sad8 += pMB->sad8[2] =
221                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
222                                                                            pCurrent, 2 * x, 2 * y + 1,
223                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
224                                                                            current->motion_flags,
225                                                                            current->quant, current->fcode, pParam,
226                                                                            pMBs, prevMBs, &pMB->mvs[2],
227                                                                            &pMB->pmvs[2]);
228                                            }
229                                            if (sad8 < pMB->sad16) {
230                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 3);
231                                                    sad8 += pMB->sad8[3] =
232                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
233                                                                            pCurrent, 2 * x + 1, 2 * y + 1,
234                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
235                                                                            current->motion_flags,
236                                                                            current->quant, current->fcode, pParam,
237                                                                            pMBs, prevMBs,
238                                                                            &pMB->mvs[3],
239                                                                            &pMB->pmvs[3]);
240                                            }
241    
242                          /* decide: MODE_INTER or MODE_INTER4V                          /* decide: MODE_INTER or MODE_INTER4V
243                             mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v                                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
244                          */                          */
245    
246                          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  
247                                          pMB->mode = MODE_INTER4V;                                          pMB->mode = MODE_INTER4V;
248                                                    pMB->sad8[0] *= 4;
249                                                    pMB->sad8[1] *= 4;
250                                                    pMB->sad8[2] *= 4;
251                                                    pMB->sad8[3] *= 4;
252                                                    continue;
253                          }                          }
254                          else  
255                          {                                  }
256                                  sad8 = sad16;  
257                                  pMB->mode = MODE_INTER;                                  pMB->mode = MODE_INTER;
258                                  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 */
259                                  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;
260                                  pMB->pmvs[0].x = pmv16.x;                          pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =
261                                  pMB->pmvs[0].y = pmv16.y;                                  pMB->sad16;
262                          }                          }
263                  }                  }
264    
265          return 0;          return 0;
266  }  }
267    
 #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )  
   
 #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )  
   
268    
269  #define CHECK_MV16_ZERO {\  #define CHECK_MV16_ZERO {\
270    if ( (0 <= max_dx) && (0 >= min_dx) \    if ( (0 <= max_dx) && (0 >= min_dx) \
271      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
272    { \    { \
273      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); \
274      iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16(-center_x, -center_y, (uint8_t)iFcode, iQuant);\
     if (iSAD <= iQuant * 96)    \  
         iSAD -= MV16_00_BIAS; \  
275      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
276      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
277  }  }
278    
279  #define NOCHECK_MV16_CANDIDATE(X,Y) { \  #define NOCHECK_MV16_CANDIDATE(X,Y) { \
280      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); \
281      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
282      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
283      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
284  }  }
# Line 457  Line 288 
288      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
289    { \    { \
290      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); \
291      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
292      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
293      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
294  }  }
# Line 467  Line 298 
298      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
299    { \    { \
300      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); \
301      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
302      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
303      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
304  }  }
# Line 477  Line 308 
308      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
309    { \    { \
310      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
311      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
312      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
313      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
314  }  }
# Line 485  Line 316 
316    
317  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
318    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); \
319    iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;\    iSAD += calc_delta_8(-center_x, -center_y, (uint8_t)iFcode, iQuant);\
320    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
321    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
322  }  }
# Line 493  Line 324 
324  #define NOCHECK_MV8_CANDIDATE(X,Y) \  #define NOCHECK_MV8_CANDIDATE(X,Y) \
325    { \    { \
326      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); \
327      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
328      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
329      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
330  }  }
# Line 503  Line 334 
334      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
335    { \    { \
336      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); \
337      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
338      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
339      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
340  }  }
# Line 513  Line 344 
344      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
345    { \    { \
346      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); \
347      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
348      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
349      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
350  }  }
# Line 523  Line 354 
354      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
355    { \    { \
356      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
357      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
358      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
359      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
360  }  }
# Line 538  Line 369 
369                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
370                                          const int x, const int y,                                          const int x, const int y,
371                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
372                                            const uint32_t iQuant,
373                                            const uint32_t iFcode,
374                                          MBParam * const pParam,                                          MBParam * const pParam,
375                                          MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
376                                            const MACROBLOCK * const prevMBs,
377                                          VECTOR * const currMV,                                          VECTOR * const currMV,
378                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
379  {  {
380          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
         const int32_t iQuant = pParam->quant;  
381          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
382          int32_t iSAD;          int32_t iSAD;
383          int32_t pred_x,pred_y;          VECTOR pred;
384    
385    
386          get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);          pred = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
387    
388          iSAD = sad16( cur,          iSAD = sad16( cur,
389                  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 559  Line 393 
393    
394          currMV->x = 0;          currMV->x = 0;
395          currMV->y = 0;          currMV->y = 0;
396          currPMV->x = -pred_x;          currPMV->x = -pred.x;
397          currPMV->y = -pred_y;          currPMV->y = -pred.y;
398    
399          return iSAD;          return iSAD;
400    
401  }  }
402  */  */
403    
404  int32_t Diamond16_MainSearch(  int32_t
405          const uint8_t * const pRef,  Diamond16_MainSearch(const uint8_t * const pRef,
406          const uint8_t * const pRefH,          const uint8_t * const pRefH,
407          const uint8_t * const pRefV,          const uint8_t * const pRefV,
408          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
409          const uint8_t * const cur,          const uint8_t * const cur,
410          const int x, const int y,                                           const int x,
411          int32_t startx, int32_t starty,                                           const int y,
412          int32_t iMinSAD,                                     const int start_x,
413                                       const int start_y,
414                                       int iMinSAD,
415          VECTOR * const currMV,          VECTOR * const currMV,
416          const VECTOR * const pmv,                                     const int center_x,
417          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
418          const int32_t min_dy, const int32_t max_dy,                                           const int32_t min_dx,
419                                             const int32_t max_dx,
420                                             const int32_t min_dy,
421                                             const int32_t max_dy,
422          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
423          const int32_t iDiamondSize,          const int32_t iDiamondSize,
424          const int32_t iFcode,          const int32_t iFcode,
# Line 589  Line 428 
428  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
429    
430          int32_t iDirection=0;          int32_t iDirection=0;
431            int32_t iDirectionBackup;
432          int32_t iSAD;          int32_t iSAD;
433          VECTOR backupMV;          VECTOR backupMV;
434          backupMV.x = startx;  
435          backupMV.y = starty;          backupMV.x = start_x;
436            backupMV.y = start_y;
437    
438  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
439    
# Line 601  Line 442 
442          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
443          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
444    
445          if (iDirection)          if (iDirection) {
446                  while (!iFound)                  while (!iFound) {
                 {  
447                          iFound = 1;                          iFound = 1;
448                          backupMV=*currMV;                          backupMV=*currMV;
449                            iDirectionBackup = iDirection;
450    
451                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
452                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
453                          if ( iDirection != 1)                                                                                     backupMV.y, 1);
454                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
455                          if ( iDirection != 4)                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
456                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                     backupMV.y, 2);
457                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
458                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
459                                                                                       backupMV.y - iDiamondSize, 3);
460                            if (iDirectionBackup != 3)
461                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
462                                                                                       backupMV.y + iDiamondSize, 4);
463                  }                  }
464          else          } else {
465          {                  currMV->x = start_x;
466                  currMV->x = startx;                  currMV->y = start_y;
                 currMV->y = starty;  
467          }          }
468          return iMinSAD;          return iMinSAD;
469  }  }
470    
471  int32_t Square16_MainSearch(  int32_t
472                                          const uint8_t * const pRef,  Square16_MainSearch(const uint8_t * const pRef,
473                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
474                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
475                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
476                                          const uint8_t * const cur,                                          const uint8_t * const cur,
477                                          const int x, const int y,                                          const int x,
478                                          int32_t startx, int32_t starty,                                          const int y,
479                                          int32_t iMinSAD,                                     const int start_x,
480                                       const int start_y,
481                                       int iMinSAD,
482                                          VECTOR * const currMV,                                          VECTOR * const currMV,
483                                          const VECTOR * const pmv,                                     const int center_x,
484                                          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
485                                          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
486                                            const int32_t max_dx,
487                                            const int32_t min_dy,
488                                            const int32_t max_dy,
489                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
490                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
491                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 648  Line 497 
497          int32_t iDirection=0;          int32_t iDirection=0;
498          int32_t iSAD;          int32_t iSAD;
499          VECTOR backupMV;          VECTOR backupMV;
500          backupMV.x = startx;  
501          backupMV.y = starty;          backupMV.x = start_x;
502            backupMV.y = start_y;
503    
504  /* It's one search with full square pattern, and new parts for all following diamonds */  /* It's one search with full square pattern, and new parts for all following diamonds */
505    
# Line 664  Line 514 
514          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
515          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
516    
517          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
518          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                           backupMV.y - iDiamondSize, 5);
519          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
520          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                                           backupMV.y + iDiamondSize, 6);
521            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
522                                                             backupMV.y - iDiamondSize, 7);
523            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
524                                                             backupMV.y + iDiamondSize, 8);
525    
526    
527          if (iDirection)          if (iDirection) {
528                  while (!iFound)                  while (!iFound) {
                 {  
529                          iFound = 1;                          iFound = 1;
530                          backupMV=*currMV;                          backupMV=*currMV;
531    
532                          switch (iDirection)                          switch (iDirection) {
                         {  
533                                  case 1:                                  case 1:
534                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
535                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                     backupMV.y, 1);
536                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
537                                                                                     backupMV.y - iDiamondSize, 5);
538                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
539                                                                                     backupMV.y - iDiamondSize, 7);
540                                          break;                                          break;
541                                  case 2:                                  case 2:
542                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
543                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   2);
544                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
545                                                                                     backupMV.y + iDiamondSize, 6);
546                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
547                                                                                     backupMV.y + iDiamondSize, 8);
548                                          break;                                          break;
549    
550                                  case 3:                                  case 3:
551                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
552                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
553                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
554                                                                                     backupMV.y - iDiamondSize, 7);
555                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
556                                                                                     backupMV.y + iDiamondSize, 8);
557                                          break;                                          break;
558    
559                                  case 4:                                  case 4:
560                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
561                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
562                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
563                                                                                     backupMV.y - iDiamondSize, 5);
564                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
565                                                                                     backupMV.y + iDiamondSize, 6);
566                                          break;                                          break;
567    
568                                  case 5:                                  case 5:
569                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
570                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   1);
571                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
572                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   3);
573                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
574                                                                                     backupMV.y - iDiamondSize, 5);
575                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
576                                                                                     backupMV.y + iDiamondSize, 6);
577                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
578                                                                                     backupMV.y - iDiamondSize, 7);
579                                          break;                                          break;
580    
581                                  case 6:                                  case 6:
582                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
583                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   2);
584                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
585                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
586                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);  
587                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
588                                                                                     backupMV.y - iDiamondSize, 5);
589                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
590                                                                                     backupMV.y + iDiamondSize, 6);
591                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
592                                                                                     backupMV.y + iDiamondSize, 8);
593    
594                                          break;                                          break;
595    
596                                  case 7:                                  case 7:
597                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
598                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                     backupMV.y, 1);
599                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
600                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
601                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
602                                                                                     backupMV.y - iDiamondSize, 5);
603                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
604                                                                                     backupMV.y - iDiamondSize, 7);
605                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
606                                                                                     backupMV.y + iDiamondSize, 8);
607                                          break;                                          break;
608    
609                                  case 8:                                  case 8:
610                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
611                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
612                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
613                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
614                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
615                                                                                     backupMV.y + iDiamondSize, 6);
616                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
617                                                                                     backupMV.y - iDiamondSize, 7);
618                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
619                                                                                     backupMV.y + iDiamondSize, 8);
620                                          break;                                          break;
621                          default:                          default:
622                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
623                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                                                                   1);
624                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
625                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
626                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
627                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
628                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
629                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
630                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);  
631                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
632                                                                                     backupMV.y - iDiamondSize, 5);
633                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
634                                                                                     backupMV.y + iDiamondSize, 6);
635                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
636                                                                                     backupMV.y - iDiamondSize, 7);
637                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
638                                                                                     backupMV.y + iDiamondSize, 8);
639                                          break;                                          break;
640                          }                          }
641                  }                  }
642          else          } else {
643                  {                  currMV->x = start_x;
644                          currMV->x = startx;                  currMV->y = start_y;
                         currMV->y = starty;  
645                  }                  }
646          return iMinSAD;          return iMinSAD;
647  }  }
648    
649    
650  int32_t Full16_MainSearch(  int32_t
651                                          const uint8_t * const pRef,  Full16_MainSearch(const uint8_t * const pRef,
652                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
653                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
654                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
655                                          const uint8_t * const cur,                                          const uint8_t * const cur,
656                                          const int x, const int y,                                    const int x,
657                                          int32_t startx, int32_t starty,                                    const int y,
658                                          int32_t iMinSAD,                                     const int start_x,
659                                       const int start_y,
660                                       int iMinSAD,
661                                          VECTOR * const currMV,                                          VECTOR * const currMV,
662                                          const VECTOR * const pmv,                                     const int center_x,
663                                          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
664                                          const int32_t min_dy, const int32_t max_dy,                                    const int32_t min_dx,
665                                      const int32_t max_dx,
666                                      const int32_t min_dy,
667                                      const int32_t max_dy,
668                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
669                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
670                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 778  Line 674 
674          int32_t iSAD;          int32_t iSAD;
675          int32_t dx,dy;          int32_t dx,dy;
676          VECTOR backupMV;          VECTOR backupMV;
677          backupMV.x = startx;  
678          backupMV.y = starty;          backupMV.x = start_x;
679            backupMV.y = start_y;
680    
681          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
682                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
# Line 788  Line 685 
685          return iMinSAD;          return iMinSAD;
686  }  }
687    
688  int32_t Full8_MainSearch(  int32_t
689                                          const uint8_t * const pRef,  AdvDiamond16_MainSearch(const uint8_t * const pRef,
690                                                    const uint8_t * const pRefH,
691                                                    const uint8_t * const pRefV,
692                                                    const uint8_t * const pRefHV,
693                                                    const uint8_t * const cur,
694                                                    const int x,
695                                                    const int y,
696                                               int start_x,
697                                               int start_y,
698                                               int iMinSAD,
699                                               VECTOR * const currMV,
700                                               const int center_x,
701                                               const int center_y,
702                                                    const int32_t min_dx,
703                                                    const int32_t max_dx,
704                                                    const int32_t min_dy,
705                                                    const int32_t max_dy,
706                                                    const int32_t iEdgedWidth,
707                                                    const int32_t iDiamondSize,
708                                                    const int32_t iFcode,
709                                                    const int32_t iQuant,
710                                                    int iDirection)
711    {
712    
713            int32_t iSAD;
714    
715    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
716    
717            if (iDirection) {
718                    CHECK_MV16_CANDIDATE(start_x - iDiamondSize, start_y);
719                    CHECK_MV16_CANDIDATE(start_x + iDiamondSize, start_y);
720                    CHECK_MV16_CANDIDATE(start_x, start_y - iDiamondSize);
721                    CHECK_MV16_CANDIDATE(start_x, start_y + iDiamondSize);
722            } else {
723                    int bDirection = 1 + 2 + 4 + 8;
724    
725                    do {
726                            iDirection = 0;
727                            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)
728                                    CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
729    
730                            if (bDirection & 2)
731                                    CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
732    
733                            if (bDirection & 4)
734                                    CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
735    
736                            if (bDirection & 8)
737                                    CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
738    
739                            /* now we're doing diagonal checks near our candidate */
740    
741                            if (iDirection)         //checking if anything found
742                            {
743                                    bDirection = iDirection;
744                                    iDirection = 0;
745                                    start_x = currMV->x;
746                                    start_y = currMV->y;
747                                    if (bDirection & 3)     //our candidate is left or right
748                                    {
749                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
750                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
751                                    } else                  // what remains here is up or down
752                                    {
753                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
754                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
755                                    }
756    
757                                    if (iDirection) {
758                                            bDirection += iDirection;
759                                            start_x = currMV->x;
760                                            start_y = currMV->y;
761                                    }
762                            } else                          //about to quit, eh? not so fast....
763                            {
764                                    switch (bDirection) {
765                                    case 2:
766                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
767                                                                                             start_y - iDiamondSize, 2 + 4);
768                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
769                                                                                             start_y + iDiamondSize, 2 + 8);
770                                            break;
771                                    case 1:
772    
773                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
774                                                                                             start_y - iDiamondSize, 1 + 4);
775                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
776                                                                                             start_y + iDiamondSize, 1 + 8);
777                                            break;
778                                    case 2 + 4:
779                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
780                                                                                             start_y - iDiamondSize, 1 + 4);
781                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
782                                                                                             start_y - iDiamondSize, 2 + 4);
783                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
784                                                                                             start_y + iDiamondSize, 2 + 8);
785                                            break;
786                                    case 4:
787                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
788                                                                                             start_y - iDiamondSize, 2 + 4);
789                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
790                                                                                             start_y - iDiamondSize, 1 + 4);
791                                            break;
792                                    case 8:
793                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
794                                                                                             start_y + iDiamondSize, 2 + 8);
795                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
796                                                                                             start_y + iDiamondSize, 1 + 8);
797                                            break;
798                                    case 1 + 4:
799                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
800                                                                                             start_y + iDiamondSize, 1 + 8);
801                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
802                                                                                             start_y - iDiamondSize, 1 + 4);
803                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
804                                                                                             start_y - iDiamondSize, 2 + 4);
805                                            break;
806                                    case 2 + 8:
807                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
808                                                                                             start_y - iDiamondSize, 1 + 4);
809                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
810                                                                                             start_y + iDiamondSize, 1 + 8);
811                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
812                                                                                             start_y + iDiamondSize, 2 + 8);
813                                            break;
814                                    case 1 + 8:
815                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
816                                                                                             start_y - iDiamondSize, 2 + 4);
817                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
818                                                                                             start_y + iDiamondSize, 2 + 8);
819                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
820                                                                                             start_y + iDiamondSize, 1 + 8);
821                                            break;
822                                    default:                //1+2+4+8 == we didn't find anything at all
823                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
824                                                                                             start_y - iDiamondSize, 1 + 4);
825                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
826                                                                                             start_y + iDiamondSize, 1 + 8);
827                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
828                                                                                             start_y - iDiamondSize, 2 + 4);
829                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
830                                                                                             start_y + iDiamondSize, 2 + 8);
831                                            break;
832                                    }
833                                    if (!iDirection)
834                                            break;          //ok, the end. really
835                                    else {
836                                            bDirection = iDirection;
837                                            start_x = currMV->x;
838                                            start_y = currMV->y;
839                                    }
840                            }
841                    }
842                    while (1);                              //forever
843            }
844            return iMinSAD;
845    }
846    
847    #define CHECK_MV16_F_INTERPOL(X,Y) { \
848      if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
849        && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
850      { \
851        iSAD = sad16bi( cur, \
852                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
853                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
854                            iEdgedWidth); \
855        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
856        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
857        if (iSAD < iMinSAD) \
858        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); } } \
859    }
860    
861    #define CHECK_MV16_F_INTERPOL_FOUND(X,Y) { \
862      if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
863        && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
864      { \
865        iSAD = sad16bi( cur, \
866                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
867                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
868                            iEdgedWidth); \
869        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
870        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
871        if (iSAD < iMinSAD) \
872        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); iFound=0;} } \
873    }
874    
875    #define CHECK_MV16_B_INTERPOL(X,Y) { \
876      if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
877        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
878      { \
879        iSAD = sad16bi( cur, \
880                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
881                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
882                            iEdgedWidth); \
883        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
884        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
885        if (iSAD < iMinSAD) \
886        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); } } \
887    }
888    
889    #define CHECK_MV16_B_INTERPOL_FOUND(X,Y) { \
890      if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
891        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
892      { \
893        iSAD = sad16bi( cur, \
894                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
895                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
896                            iEdgedWidth); \
897        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
898        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
899        if (iSAD < iMinSAD) \
900        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); iFound=0;} } \
901    }
902    
903    int32_t
904    Diamond16_InterpolMainSearch(
905                                            const uint8_t * const f_pRef,
906                                             const uint8_t * const f_pRefH,
907                                             const uint8_t * const f_pRefV,
908                                             const uint8_t * const f_pRefHV,
909    
910                                             const uint8_t * const cur,
911    
912                                            const uint8_t * const b_pRef,
913                                             const uint8_t * const b_pRefH,
914                                             const uint8_t * const b_pRefV,
915                                             const uint8_t * const b_pRefHV,
916    
917                                             const int x,
918                                             const int y,
919    
920                                       const int f_start_x,
921                                       const int f_start_y,
922                                       const int b_start_x,
923                                       const int b_start_y,
924    
925                                       int iMinSAD,
926                                       VECTOR * const f_currMV,
927                                       VECTOR * const b_currMV,
928    
929                                       const int f_center_x,
930                                       const int f_center_y,
931                                       const int b_center_x,
932                                       const int b_center_y,
933    
934                                        const int32_t f_min_dx,
935                                            const int32_t f_max_dx,
936                                            const int32_t f_min_dy,
937                                            const int32_t f_max_dy,
938    
939                                        const int32_t b_min_dx,
940                                            const int32_t b_max_dx,
941                                            const int32_t b_min_dy,
942                                            const int32_t b_max_dy,
943    
944                                            const int32_t iEdgedWidth,
945                                            const int32_t iDiamondSize,
946    
947                                            const int32_t f_iFcode,
948                                            const int32_t b_iFcode,
949    
950                                            const int32_t iQuant,
951                                            int iFound)
952    {
953    /* Do a diamond search around given starting point, return SAD of best */
954    
955            int32_t iSAD;
956    
957            VECTOR f_backupMV;
958            VECTOR b_backupMV;
959    
960            f_currMV->x = f_start_x;
961            f_currMV->y = f_start_y;
962            b_currMV->x = b_start_x;
963            b_currMV->y = b_start_y;
964    
965            do
966            {
967                    iFound = 1;
968    
969                    f_backupMV = *f_currMV;
970    
971                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x - iDiamondSize, f_backupMV.y);
972                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x + iDiamondSize, f_backupMV.y);
973                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y - iDiamondSize);
974                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y + iDiamondSize);
975    
976                    b_backupMV = *b_currMV;
977    
978                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x - iDiamondSize, b_backupMV.y);
979                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x + iDiamondSize, b_backupMV.y);
980                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y - iDiamondSize);
981                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y + iDiamondSize);
982    
983            } while (!iFound);
984    
985            return iMinSAD;
986    }
987    
988    /* Sorry, these MACROS really got too large... I'll turn them into function soon! */
989    
990    #define CHECK_MV16_DIRECT_FOUND(X,Y) \
991            if ( (X)>=(-32) && (X)<=(31) && ((Y)>=-32) && ((Y)<=31) ) \
992            { int k;\
993            VECTOR mvs,b_mvs;       \
994            iSAD = 0;\
995            for (k = 0; k < 4; k++) {       \
996                                            mvs.x = (int32_t) ((TRB * directmv[k].x) / TRD + (X));          \
997                        b_mvs.x = (int32_t) (((X) == 0)                                                     \
998                                                                                    ? ((TRB - TRD) * directmv[k].x) / TRD   \
999                                                : mvs.x - directmv[k].x);                           \
1000                                                                                                                                                                    \
1001                        mvs.y = (int32_t) ((TRB * directmv[k].y) / TRD + (Y));              \
1002                            b_mvs.y = (int32_t) (((Y) == 0)                                                         \
1003                                                                                    ? ((TRB - TRD) * directmv[k].y) / TRD   \
1004                                                : mvs.y - directmv[k].y);                           \
1005                                                                                                                                                                    \
1006      if ( (mvs.x <= max_dx) && (mvs.x >= min_dx) \
1007        && (mvs.y <= max_dy) && (mvs.y >= min_dy)  \
1008            && (b_mvs.x <= max_dx) && (b_mvs.x >= min_dx)  \
1009        && (b_mvs.y <= max_dy) && (b_mvs.y >= min_dy) ) { \
1010                iSAD += sad8bi( cur + 8*(k&1) + 8*(k>>1)*iEdgedWidth,                                                                                                       \
1011                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \
1012                                            mvs.x, mvs.y, iEdgedWidth),                                                             \
1013                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \
1014                                            b_mvs.x, b_mvs.y, iEdgedWidth),                                                         \
1015                            iEdgedWidth); \
1016                    }       \
1017            else    \
1018                    iSAD = 65535;   \
1019            } \
1020            iSAD += calc_delta_16((X),(Y), 1, iQuant);\
1021            if (iSAD < iMinSAD) \
1022                {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iFound=0; } \
1023    }
1024    
1025    
1026    
1027    int32_t
1028    Diamond16_DirectMainSearch(
1029                                            const uint8_t * const f_pRef,
1030                                            const uint8_t * const f_pRefH,
1031                                            const uint8_t * const f_pRefV,
1032                                            const uint8_t * const f_pRefHV,
1033    
1034                                            const uint8_t * const cur,
1035    
1036                                            const uint8_t * const b_pRef,
1037                                            const uint8_t * const b_pRefH,
1038                                            const uint8_t * const b_pRefV,
1039                                            const uint8_t * const b_pRefHV,
1040    
1041                                            const int x,
1042                                            const int y,
1043    
1044                                            const int TRB,
1045                                            const int TRD,
1046    
1047                                        const int start_x,
1048                                        const int start_y,
1049    
1050                                        int iMinSAD,
1051                                        VECTOR * const currMV,
1052                                            const VECTOR * const directmv,
1053    
1054                                        const int32_t min_dx,
1055                                            const int32_t max_dx,
1056                                            const int32_t min_dy,
1057                                            const int32_t max_dy,
1058    
1059                                            const int32_t iEdgedWidth,
1060                                            const int32_t iDiamondSize,
1061    
1062                                            const int32_t iQuant,
1063                                            int iFound)
1064    {
1065    /* Do a diamond search around given starting point, return SAD of best */
1066    
1067            int32_t iSAD;
1068    
1069            VECTOR backupMV;
1070    
1071            currMV->x = start_x;
1072            currMV->y = start_y;
1073    
1074    /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1075    
1076            do
1077            {
1078                    iFound = 1;
1079    
1080                    backupMV = *currMV;
1081    
1082                    CHECK_MV16_DIRECT_FOUND(backupMV.x - iDiamondSize, backupMV.y);
1083                    CHECK_MV16_DIRECT_FOUND(backupMV.x + iDiamondSize, backupMV.y);
1084                    CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y - iDiamondSize);
1085                    CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y + iDiamondSize);
1086    
1087            } while (!iFound);
1088    
1089            return iMinSAD;
1090    }
1091    
1092    
1093    int32_t
1094    AdvDiamond8_MainSearch(const uint8_t * const pRef,
1095                                               const uint8_t * const pRefH,
1096                                               const uint8_t * const pRefV,
1097                                               const uint8_t * const pRefHV,
1098                                               const uint8_t * const cur,
1099                                               const int x,
1100                                               const int y,
1101                                               int start_x,
1102                                               int start_y,
1103                                               int iMinSAD,
1104                                               VECTOR * const currMV,
1105                                               const int center_x,
1106                                               const int center_y,
1107                                               const int32_t min_dx,
1108                                               const int32_t max_dx,
1109                                               const int32_t min_dy,
1110                                               const int32_t max_dy,
1111                                               const int32_t iEdgedWidth,
1112                                               const int32_t iDiamondSize,
1113                                               const int32_t iFcode,
1114                                               const int32_t iQuant,
1115                                               int iDirection)
1116    {
1117    
1118            int32_t iSAD;
1119    
1120    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
1121    
1122            if (iDirection) {
1123                    CHECK_MV8_CANDIDATE(start_x - iDiamondSize, start_y);
1124                    CHECK_MV8_CANDIDATE(start_x + iDiamondSize, start_y);
1125                    CHECK_MV8_CANDIDATE(start_x, start_y - iDiamondSize);
1126                    CHECK_MV8_CANDIDATE(start_x, start_y + iDiamondSize);
1127            } else {
1128                    int bDirection = 1 + 2 + 4 + 8;
1129    
1130                    do {
1131                            iDirection = 0;
1132                            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)
1133                                    CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1134    
1135                            if (bDirection & 2)
1136                                    CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1137    
1138                            if (bDirection & 4)
1139                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1140    
1141                            if (bDirection & 8)
1142                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1143    
1144                            /* now we're doing diagonal checks near our candidate */
1145    
1146                            if (iDirection)         //checking if anything found
1147                            {
1148                                    bDirection = iDirection;
1149                                    iDirection = 0;
1150                                    start_x = currMV->x;
1151                                    start_y = currMV->y;
1152                                    if (bDirection & 3)     //our candidate is left or right
1153                                    {
1154                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1155                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1156                                    } else                  // what remains here is up or down
1157                                    {
1158                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1159                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1160                                    }
1161    
1162                                    if (iDirection) {
1163                                            bDirection += iDirection;
1164                                            start_x = currMV->x;
1165                                            start_y = currMV->y;
1166                                    }
1167                            } else                          //about to quit, eh? not so fast....
1168                            {
1169                                    switch (bDirection) {
1170                                    case 2:
1171                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1172                                                                                            start_y - iDiamondSize, 2 + 4);
1173                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1174                                                                                            start_y + iDiamondSize, 2 + 8);
1175                                            break;
1176                                    case 1:
1177                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1178                                                                                            start_y - iDiamondSize, 1 + 4);
1179                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1180                                                                                            start_y + iDiamondSize, 1 + 8);
1181                                            break;
1182                                    case 2 + 4:
1183                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1184                                                                                            start_y - iDiamondSize, 1 + 4);
1185                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1186                                                                                            start_y - iDiamondSize, 2 + 4);
1187                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1188                                                                                            start_y + iDiamondSize, 2 + 8);
1189                                            break;
1190                                    case 4:
1191                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1192                                                                                            start_y - iDiamondSize, 2 + 4);
1193                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1194                                                                                            start_y - iDiamondSize, 1 + 4);
1195                                            break;
1196                                    case 8:
1197                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1198                                                                                            start_y + iDiamondSize, 2 + 8);
1199                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1200                                                                                            start_y + iDiamondSize, 1 + 8);
1201                                            break;
1202                                    case 1 + 4:
1203                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1204                                                                                            start_y + iDiamondSize, 1 + 8);
1205                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1206                                                                                            start_y - iDiamondSize, 1 + 4);
1207                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1208                                                                                            start_y - iDiamondSize, 2 + 4);
1209                                            break;
1210                                    case 2 + 8:
1211                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1212                                                                                            start_y - iDiamondSize, 1 + 4);
1213                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1214                                                                                            start_y + iDiamondSize, 1 + 8);
1215                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1216                                                                                            start_y + iDiamondSize, 2 + 8);
1217                                            break;
1218                                    case 1 + 8:
1219                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1220                                                                                            start_y - iDiamondSize, 2 + 4);
1221                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1222                                                                                            start_y + iDiamondSize, 2 + 8);
1223                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1224                                                                                            start_y + iDiamondSize, 1 + 8);
1225                                            break;
1226                                    default:                //1+2+4+8 == we didn't find anything at all
1227                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1228                                                                                            start_y - iDiamondSize, 1 + 4);
1229                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1230                                                                                            start_y + iDiamondSize, 1 + 8);
1231                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1232                                                                                            start_y - iDiamondSize, 2 + 4);
1233                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1234                                                                                            start_y + iDiamondSize, 2 + 8);
1235                                            break;
1236                                    }
1237                                    if (!(iDirection))
1238                                            break;          //ok, the end. really
1239                                    else {
1240                                            bDirection = iDirection;
1241                                            start_x = currMV->x;
1242                                            start_y = currMV->y;
1243                                    }
1244                            }
1245                    }
1246                    while (1);                              //forever
1247            }
1248            return iMinSAD;
1249    }
1250    
1251    
1252    int32_t
1253    Full8_MainSearch(const uint8_t * const pRef,
1254                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1255                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1256                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1257                                          const uint8_t * const cur,                                          const uint8_t * const cur,
1258                                          const int x, const int y,                                   const int x,
1259                                          int32_t startx, int32_t starty,                                   const int y,
1260                                          int32_t iMinSAD,                             const int start_x,
1261                               const int start_y,
1262                               int iMinSAD,
1263                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1264                                          const VECTOR * const pmv,                             const int center_x,
1265                                          const int32_t min_dx, const int32_t max_dx,                             const int center_y,
1266                                          const int32_t min_dy, const int32_t max_dy,                                   const int32_t min_dx,
1267                                     const int32_t max_dx,
1268                                     const int32_t min_dy,
1269                                     const int32_t max_dy,
1270                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
1271                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
1272                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 810  Line 1276 
1276          int32_t iSAD;          int32_t iSAD;
1277          int32_t dx,dy;          int32_t dx,dy;
1278          VECTOR backupMV;          VECTOR backupMV;
1279          backupMV.x = startx;  
1280          backupMV.y = starty;          backupMV.x = start_x;
1281            backupMV.y = start_y;
1282    
1283          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
1284                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
# Line 820  Line 1287 
1287          return iMinSAD;          return iMinSAD;
1288  }  }
1289    
1290    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1291    
1292    int32_t
1293  int32_t Halfpel16_Refine(  Halfpel16_Refine(const uint8_t * const pRef,
         const uint8_t * const pRef,  
1294          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1295          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1296          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1297          const uint8_t * const cur,          const uint8_t * const cur,
1298          const int x, const int y,                                   const int x,
1299                                     const int y,
1300          VECTOR * const currMV,          VECTOR * const currMV,
1301          int32_t iMinSAD,          int32_t iMinSAD,
1302          const VECTOR * const pmv,                             const int center_x,
1303          const int32_t min_dx, const int32_t max_dx,                             const int center_y,
1304          const int32_t min_dy, const int32_t max_dy,                                   const int32_t min_dx,
1305                                     const int32_t max_dx,
1306                                     const int32_t min_dy,
1307                                     const int32_t max_dy,
1308          const int32_t iFcode,          const int32_t iFcode,
1309          const int32_t iQuant,          const int32_t iQuant,
1310          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 858  Line 1329 
1329  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1330    
1331    
1332  int32_t PMVfastSearch16(  
1333                                          const uint8_t * const pRef,  int32_t
1334    PMVfastSearch16(const uint8_t * const pRef,
1335                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1336                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1337                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1338                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1339                                          const int x, const int y,                                  const int x,
1340                                    const int y,
1341                                    const int start_x,      /* start is searched first, so it should contain the most */
1342                                    const int start_y,  /* likely motion vector for this block */
1343                                    const int center_x,     /* center is from where length of MVs is measured */
1344                                    const int center_y,
1345                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1346                                    const uint32_t iQuant,
1347                                    const uint32_t iFcode,
1348                                          const MBParam * const pParam,                                          const MBParam * const pParam,
1349                                          MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1350                                    const MACROBLOCK * const prevMBs,
1351                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1352                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
1353  {  {
1354          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;  
1355          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1356          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
1357          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 895  Line 1373 
1373          VECTOR pmv[4];          VECTOR pmv[4];
1374          int32_t psad[4];          int32_t psad[4];
1375    
1376          MACROBLOCK * const pMB = pMBs + x + y * iWcount;          MainSearch16FuncPtr MainSearchPtr;
1377    
1378            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
1379    
1380          static int32_t threshA,threshB;          int32_t threshA, threshB;
1381          int32_t bPredEq;          int32_t bPredEq;
1382          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1383    
1384  /* Get maximum range */  /* Get maximum range */
1385          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
1386                    x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
1387    
1388  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1389    
1390          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
1391          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1392          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1393          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1394          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1395          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
   
1396    
1397          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1398            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1399    
1400          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1401                  threshA =  512;                  threshA =  512;
1402                  threshB = 1024;                  threshB = 1024;
1403            } else {
         }  
         else  
         {  
1404                  threshA = psad[0];                  threshA = psad[0];
1405                  threshB = threshA+256;                  threshB = threshA+256;
1406                  if (threshA< 512) threshA =  512;                  if (threshA < 512)
1407                  if (threshA>1024) threshA = 1024;                          threshA = 512;
1408                  if (threshB>1792) threshB = 1792;                  if (threshA > 1024)
1409                            threshA = 1024;
1410                    if (threshB > 1792)
1411                            threshB = 1792;
1412          }          }
1413    
1414          iFound=0;          iFound=0;
1415    
 /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  
    vector of the median.  
    If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2  
 */  
   
         if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[0]) ) )  
                 iFound=2;  
   
 /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  
    Otherwise select large Diamond Search.  
 */  
   
         if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536) || (bPredEq) )  
                 iDiamondSize=1; // halfpel!  
         else  
                 iDiamondSize=2; // halfpel!  
   
         if (!(MotionFlags & PMV_HALFPELDIAMOND16) )  
                 iDiamondSize*=2;  
   
1416  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1417     MinSAD=SAD     MinSAD=SAD
1418     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 961  Line 1420 
1420     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
1421  */  */
1422    
1423            currMV->x = start_x;
1424            currMV->y = start_y;
1425    
1426  // Prepare for main loop          if (!(MotionFlags & PMV_HALFPEL16)) {   /* This should NOT be necessary! */
   
         *currMV=pmv[0];         /* current best := prediction */  
         if (!(MotionFlags & PMV_HALFPEL16 ))  
         {       /* This should NOT be necessary! */  
1427                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1428                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
1429          }          }
1430    
1431          if (currMV->x > max_dx)          if (currMV->x > max_dx) {
         {  
1432                  currMV->x=max_dx;                  currMV->x=max_dx;
1433          }          }
1434          if (currMV->x < min_dx)          if (currMV->x < min_dx) {
         {  
1435                  currMV->x=min_dx;                  currMV->x=min_dx;
1436          }          }
1437          if (currMV->y > max_dy)          if (currMV->y > max_dy) {
         {  
1438                  currMV->y=max_dy;                  currMV->y=max_dy;
1439          }          }
1440          if (currMV->y < min_dy)          if (currMV->y < min_dy) {
         {  
1441                  currMV->y=min_dy;                  currMV->y=min_dy;
1442          }          }
1443    
1444          iMinSAD = sad16( cur,          iMinSAD =
1445                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1446                           iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1447          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1448            iMinSAD +=
1449          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
1450          {                                            (uint8_t) iFcode, iQuant);
1451    
1452            if ((iMinSAD < 256) ||
1453                    ((MVequal(*currMV, prevMB->mvs[0])) &&
1454                     ((int32_t) iMinSAD < prevMB->sad16))) {
1455                    if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode
1456                    {
1457                            if (!MVzero(*currMV)) {
1458                                    iMinSAD += MV16_00_BIAS;
1459                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
1460                                    iMinSAD -= MV16_00_BIAS;
1461                            }
1462                    }
1463    
1464                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1465                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
# Line 1002  Line 1467 
1467                          goto PMVfast16_Terminate_with_Refine;                          goto PMVfast16_Terminate_with_Refine;
1468          }          }
1469    
1470    
1471    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1472       vector of the median.
1473       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1474    */
1475    
1476            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[0])))
1477                    iFound = 2;
1478    
1479    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1480       Otherwise select large Diamond Search.
1481    */
1482    
1483            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
1484                    iDiamondSize = 1;               // halfpel!
1485            else
1486                    iDiamondSize = 2;               // halfpel!
1487    
1488            if (!(MotionFlags & PMV_HALFPELDIAMOND16))
1489                    iDiamondSize *= 2;
1490    
1491  /*  /*
1492     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.
1493     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1494     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1495     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1496  */  */
1497    
1498  // (0,0) is always possible  // (0,0) is always possible
1499    
1500            if (!MVzero(pmv[0]))
1501          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1502    
1503  // previous frame MV is always possible  // previous frame MV is always possible
1504          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);  
1505            if (!MVzero(prevMB->mvs[0]))
1506                    if (!MVequal(prevMB->mvs[0], pmv[0]))
1507                            CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
1508    
1509  // left neighbour, if allowed  // left neighbour, if allowed
1510          if (x != 0)  
1511          {          if (!MVzero(pmv[1]))
1512                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!MVequal(pmv[1], prevMB->mvs[0]))
1513                  {       pmv[1].x = EVEN(pmv[1].x);                          if (!MVequal(pmv[1], pmv[0])) {
1514                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1515                                            pmv[1].x = EVEN(pmv[1].x);
1516                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1517                  }                  }
1518    
1519                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1520          }          }
   
1521  // top neighbour, if allowed  // top neighbour, if allowed
1522          if (y != 0)          if (!MVzero(pmv[2]))
1523          {                  if (!MVequal(pmv[2], prevMB->mvs[0]))
1524                  if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!MVequal(pmv[2], pmv[0]))
1525                  {       pmv[2].x = EVEN(pmv[2].x);                                  if (!MVequal(pmv[2], pmv[1])) {
1526                                            if (!(MotionFlags & PMV_HALFPEL16)) {
1527                                                    pmv[2].x = EVEN(pmv[2].x);
1528                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
1529                  }                  }
1530                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1531    
1532  // top right neighbour, if allowed  // top right neighbour, if allowed
1533                  if (x != (iWcount-1))                                          if (!MVzero(pmv[3]))
1534                  {                                                  if (!MVequal(pmv[3], prevMB->mvs[0]))
1535                          if (!(MotionFlags & PMV_HALFPEL16 ))                                                          if (!MVequal(pmv[3], pmv[0]))
1536                          {       pmv[3].x = EVEN(pmv[3].x);                                                                  if (!MVequal(pmv[3], pmv[1]))
1537                                                                            if (!MVequal(pmv[3], pmv[2])) {
1538                                                                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1539                                                                                            pmv[3].x = EVEN(pmv[3].x);
1540                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1541                          }                          }
1542                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                  CHECK_MV16_CANDIDATE(pmv[3].x,
1543                                                                                                                             pmv[3].y);
1544                  }                  }
1545          }          }
1546    
1547            if ((MVzero(*currMV)) &&
1548                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1549                    iMinSAD -= MV16_00_BIAS;
1550    
1551    
1552  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1553     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.
1554  */  */
1555    
1556          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )          if ((iMinSAD <= threshA) ||
1557          {                  (MVequal(*currMV, prevMB->mvs[0]) &&
1558                     ((int32_t) iMinSAD < prevMB->sad16))) {
1559                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1560                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
1561                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1069  Line 1573 
1573     Refine by using small diamond and goto step 10.     Refine by using small diamond and goto step 10.
1574  */  */
1575    
1576            if (MotionFlags & PMV_USESQUARES16)
1577                    MainSearchPtr = Square16_MainSearch;
1578            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
1579                    MainSearchPtr = AdvDiamond16_MainSearch;
1580            else
1581                    MainSearchPtr = Diamond16_MainSearch;
1582    
1583          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1584    
1585    
1586  /* 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 */
1587          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1588                                            x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1589                                            currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->x, currMV->y, iMinSAD, &newMV, center_x, center_y,
1590                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dx, max_dx,
1591                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1592                                                      iQuant, iFound);
1593    
1594          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1595                  *currMV = newMV;                  *currMV = newMV;
1596                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1597          }          }
1598    
1599          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
1600  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1601    
1602                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1603                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1604                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1605                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    center_x, center_y, iMinSAD, &newMV, center_x, center_y,
1606                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1607                                                                      iDiamondSize, iFcode, iQuant, iFound);
1608    
1609                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1610                          *currMV = newMV;                          *currMV = newMV;
1611                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1612                  }                  }
1613                  }                  }
1614    
1615                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1616                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1617                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1618                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y,
1619                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy,
1620                                                                      iEdgedWidth, iDiamondSize, iFcode,
1621                                                                      iQuant, iFound);
1622    
1623                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1624                          *currMV = newMV;                          *currMV = newMV;
1625                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1626                  }                  }
# Line 1120  Line 1633 
1633    
1634  PMVfast16_Terminate_with_Refine:  PMVfast16_Terminate_with_Refine:
1635          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1636                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1637                                    x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1638                                    currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1639                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1640    
1641  PMVfast16_Terminate_without_Refine:  PMVfast16_Terminate_without_Refine:
1642          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
1643          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
1644          return iMinSAD;          return iMinSAD;
1645  }  }
1646    
# Line 1136  Line 1649 
1649    
1650    
1651    
1652  int32_t Diamond8_MainSearch(  int32_t
1653          const uint8_t * const pRef,  Diamond8_MainSearch(const uint8_t * const pRef,
1654          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1655          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1656          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1657          const uint8_t * const cur,          const uint8_t * const cur,
1658          const int x, const int y,                                          const int x,
1659          int32_t startx, int32_t starty,                                          const int y,
1660                                            int32_t start_x,
1661                                            int32_t start_y,
1662          int32_t iMinSAD,          int32_t iMinSAD,
1663          VECTOR * const currMV,          VECTOR * const currMV,
1664          const VECTOR * const pmv,                                     const int center_x,
1665          const int32_t min_dx, const int32_t max_dx,                                     const int center_y,
1666          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
1667                                            const int32_t max_dx,
1668                                            const int32_t min_dy,
1669                                            const int32_t max_dy,
1670          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
1671          const int32_t iDiamondSize,          const int32_t iDiamondSize,
1672          const int32_t iFcode,          const int32_t iFcode,
# Line 1158  Line 1676 
1676  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
1677    
1678          int32_t iDirection=0;          int32_t iDirection=0;
1679            int32_t iDirectionBackup;
1680          int32_t iSAD;          int32_t iSAD;
1681          VECTOR backupMV;          VECTOR backupMV;
1682          backupMV.x = startx;  
1683          backupMV.y = starty;          backupMV.x = start_x;
1684            backupMV.y = start_y;
1685    
1686  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */  /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1687    
# Line 1170  Line 1690 
1690          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
1691          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1692    
1693          if (iDirection)          if (iDirection) {
1694                  while (!iFound)                  while (!iFound) {
                 {  
1695                          iFound = 1;                          iFound = 1;
1696                          backupMV=*currMV;       // since iDirection!=0, this is well defined!                          backupMV=*currMV;       // since iDirection!=0, this is well defined!
1697                            iDirectionBackup = iDirection;
1698    
1699                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
1700                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1701                          if ( iDirection != 1)                                                                                    backupMV.y, 1);
1702                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
1703                          if ( iDirection != 4)                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1704                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                    backupMV.y, 2);
1705                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
1706                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1707                                                                                      backupMV.y - iDiamondSize, 3);
1708                            if (iDirectionBackup != 3)
1709                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1710                                                                                      backupMV.y + iDiamondSize, 4);
1711                  }                  }
1712          else          } else {
1713                    currMV->x = start_x;
1714                    currMV->y = start_y;
1715            }
1716            return iMinSAD;
1717    }
1718    
1719    
1720    
1721    
1722    int32_t
1723    Square8_MainSearch(const uint8_t * const pRef,
1724                                            const uint8_t * const pRefH,
1725                                            const uint8_t * const pRefV,
1726                                            const uint8_t * const pRefHV,
1727                                            const uint8_t * const cur,
1728                                            const int x,
1729                                            const int y,
1730                                            int32_t start_x,
1731                                            int32_t start_y,
1732                                            int32_t iMinSAD,
1733                                            VECTOR * const currMV,
1734                                       const int center_x,
1735                                       const int center_y,
1736                                            const int32_t min_dx,
1737                                            const int32_t max_dx,
1738                                            const int32_t min_dy,
1739                                            const int32_t max_dy,
1740                                            const int32_t iEdgedWidth,
1741                                            const int32_t iDiamondSize,
1742                                            const int32_t iFcode,
1743                                            const int32_t iQuant,
1744                                            int iFound)
1745          {          {
1746                  currMV->x = startx;  /* Do a square search around given starting point, return SAD of best */
1747                  currMV->y = starty;  
1748            int32_t iDirection = 0;
1749            int32_t iSAD;
1750            VECTOR backupMV;
1751    
1752            backupMV.x = start_x;
1753            backupMV.y = start_y;
1754    
1755    /* It's one search with full square pattern, and new parts for all following diamonds */
1756    
1757    /*   new direction are extra, so 1-4 is normal diamond
1758          537
1759          1*2
1760          648
1761    */
1762    
1763            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1764            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1765            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1766            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1767    
1768            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1769                                                             backupMV.y - iDiamondSize, 5);
1770            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1771                                                             backupMV.y + iDiamondSize, 6);
1772            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1773                                                             backupMV.y - iDiamondSize, 7);
1774            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1775                                                             backupMV.y + iDiamondSize, 8);
1776    
1777    
1778            if (iDirection) {
1779                    while (!iFound) {
1780                            iFound = 1;
1781                            backupMV = *currMV;
1782    
1783                            switch (iDirection) {
1784                            case 1:
1785                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1786                                                                                       backupMV.y, 1);
1787                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1788                                                                                     backupMV.y - iDiamondSize, 5);
1789                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1790                                                                                     backupMV.y - iDiamondSize, 7);
1791                                    break;
1792                            case 2:
1793                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1794                                                                                     2);
1795                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1796                                                                                     backupMV.y + iDiamondSize, 6);
1797                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1798                                                                                     backupMV.y + iDiamondSize, 8);
1799                                    break;
1800    
1801                            case 3:
1802                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1803                                                                                     4);
1804                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1805                                                                                     backupMV.y - iDiamondSize, 7);
1806                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1807                                                                                     backupMV.y + iDiamondSize, 8);
1808                                    break;
1809    
1810                            case 4:
1811                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1812                                                                                     3);
1813                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1814                                                                                     backupMV.y - iDiamondSize, 5);
1815                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1816                                                                                     backupMV.y + iDiamondSize, 6);
1817                                    break;
1818    
1819                            case 5:
1820                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1821                                                                                     1);
1822                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1823                                                                                     3);
1824                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1825                                                                                     backupMV.y - iDiamondSize, 5);
1826                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1827                                                                                     backupMV.y + iDiamondSize, 6);
1828                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1829                                                                                     backupMV.y - iDiamondSize, 7);
1830                                    break;
1831    
1832                            case 6:
1833                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1834                                                                                     2);
1835                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1836                                                                                     3);
1837    
1838                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1839                                                                                     backupMV.y - iDiamondSize, 5);
1840                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1841                                                                                     backupMV.y + iDiamondSize, 6);
1842                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1843                                                                                     backupMV.y + iDiamondSize, 8);
1844    
1845                                    break;
1846    
1847                            case 7:
1848                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1849                                                                                       backupMV.y, 1);
1850                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1851                                                                                     4);
1852                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1853                                                                                     backupMV.y - iDiamondSize, 5);
1854                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1855                                                                                     backupMV.y - iDiamondSize, 7);
1856                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1857                                                                                     backupMV.y + iDiamondSize, 8);
1858                                    break;
1859    
1860                            case 8:
1861                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1862                                                                                     2);
1863                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1864                                                                                     4);
1865                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1866                                                                                     backupMV.y + iDiamondSize, 6);
1867                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1868                                                                                     backupMV.y - iDiamondSize, 7);
1869                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1870                                                                                     backupMV.y + iDiamondSize, 8);
1871                                    break;
1872                            default:
1873                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1874                                                                                     1);
1875                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1876                                                                                     2);
1877                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1878                                                                                     3);
1879                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1880                                                                                     4);
1881    
1882                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1883                                                                                     backupMV.y - iDiamondSize, 5);
1884                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1885                                                                                     backupMV.y + iDiamondSize, 6);
1886                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1887                                                                                     backupMV.y - iDiamondSize, 7);
1888                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1889                                                                                     backupMV.y + iDiamondSize, 8);
1890                                    break;
1891                            }
1892                    }
1893            } else {
1894                    currMV->x = start_x;
1895                    currMV->y = start_y;
1896          }          }
1897          return iMinSAD;          return iMinSAD;
1898  }  }
1899    
1900  int32_t Halfpel8_Refine(  
1901          const uint8_t * const pRef,  
1902    
1903    
1904    int32_t
1905    Halfpel8_Refine_c(const uint8_t * const pRef,
1906          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1907          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1908          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1909          const uint8_t * const cur,          const uint8_t * const cur,
1910          const int x, const int y,                                  const int x,
1911                                    const int y,
1912          VECTOR * const currMV,          VECTOR * const currMV,
1913          int32_t iMinSAD,          int32_t iMinSAD,
1914          const VECTOR * const pmv,                             const int center_x,
1915          const int32_t min_dx, const int32_t max_dx,                             const int center_y,
1916          const int32_t min_dy, const int32_t max_dy,                                  const int32_t min_dx,
1917                                    const int32_t max_dx,
1918                                    const int32_t min_dy,
1919                                    const int32_t max_dy,
1920          const int32_t iFcode,          const int32_t iFcode,
1921          const int32_t iQuant,          const int32_t iQuant,
1922          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 1229  Line 1941 
1941    
1942  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1943    
1944  int32_t PMVfastSearch8(  int32_t
1945                                          const uint8_t * const pRef,  PMVfastSearch8(const uint8_t * const pRef,
1946                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1947                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1948                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1949                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1950                                          const int x, const int y,                             const int x,
1951                                          const int start_x, int start_y,                             const int y,
1952                               const int start_x,
1953                               const int start_y,
1954                                    const int center_x,
1955                                    const int center_y,
1956                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1957                               const uint32_t iQuant,
1958                               const uint32_t iFcode,
1959                                          const MBParam * const pParam,                                          const MBParam * const pParam,
1960                                          MACROBLOCK * const pMBs,                             const MACROBLOCK * const pMBs,
1961                               const MACROBLOCK * const prevMBs,
1962                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1963                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
1964  {  {
1965          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;  
1966          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1967          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
1968          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 1264  Line 1980 
1980          int32_t psad[4];          int32_t psad[4];
1981          VECTOR newMV;          VECTOR newMV;
1982          VECTOR backupMV;          VECTOR backupMV;
1983            VECTOR startMV;
1984    
1985          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1986            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
1987    
1988          static int32_t threshA,threshB;           int32_t threshA, threshB;
1989          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
1990          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1991    
1992          int32_t iSubBlock = ((y&1)<<1) + (x&1);          int32_t iSubBlock = (y & 1) + (y & 1) + (x & 1);
1993    
1994  /* Get maximum range */          MainSearch8FuncPtr MainSearchPtr;
         get_range(&min_dx, &max_dx, &min_dy, &max_dy,  
                   x, y, 8, iWidth, iHeight, iFcode);  
1995    
1996  /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */          /* Init variables */
1997            startMV.x = start_x;
1998            startMV.y = start_y;
1999    
2000          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          /* Get maximum range */
2001          { min_dx = EVEN(min_dx);          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2002                              iFcode);
2003    
2004            if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
2005                    min_dx = EVEN(min_dx);
2006          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
2007          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
2008          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
2009          }               /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          }
   
2010    
2011          bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
2012            bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
2013    
2014          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
2015                  threshA =  512/4;                  threshA =  512/4;
2016                  threshB = 1024/4;                  threshB = 1024/4;
2017    
2018          }          } else {
2019          else                  threshA = psad[0] / 4;  /* good estimate? */
         {  
                 threshA = psad[0]/4;                    /* good estimate */  
2020                  threshB = threshA+256/4;                  threshB = threshA+256/4;
2021                  if (threshA< 512/4) threshA =  512/4;                  if (threshA < 512 / 4)
2022                  if (threshA>1024/4) threshA = 1024/4;                          threshA = 512 / 4;
2023                  if (threshB>1792/4) threshB = 1792/4;                  if (threshA > 1024 / 4)
2024                            threshA = 1024 / 4;
2025                    if (threshB > 1792 / 4)
2026                            threshB = 1792 / 4;
2027          }          }
2028    
2029          iFound=0;          iFound=0;
2030    
 /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  
    vector of the median.  
    If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2  
 */  
   
         if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[iSubBlock]) ) )  
                 iFound=2;  
   
 /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  
    Otherwise select large Diamond Search.  
 */  
   
         if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536/4) || (bPredEq) )  
                 iDiamondSize=1; // 1 halfpel!  
         else  
                 iDiamondSize=2; // 2 halfpel = 1 full pixel!  
   
         if (!(MotionFlags & PMV_HALFPELDIAMOND8) )  
                 iDiamondSize*=2;  
   
2031  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2032     MinSAD=SAD     MinSAD=SAD
2033     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 1336  Line 2038 
2038    
2039  // Prepare for main loop  // Prepare for main loop
2040    
2041          currMV->x=start_x;              /* start with mv16 */    if (MotionFlags & PMV_USESQUARES8)
2042          currMV->y=start_y;        MainSearchPtr = Square8_MainSearch;
2043      else
2044    
2045          iMinSAD = sad8( cur,          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2046                          get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  MainSearchPtr = AdvDiamond8_MainSearch;
2047                          iEdgedWidth);          else
2048          iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode) * iQuant;                  MainSearchPtr = Diamond8_MainSearch;
2049    
2050          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && (iMinSAD < pMB->sad8[iSubBlock]) ) )  
2051          {          *currMV = startMV;
2052    
2053            iMinSAD =
2054                    sad8(cur,
2055                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2056                                                    iEdgedWidth), iEdgedWidth);
2057            iMinSAD +=
2058                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2059                                             (uint8_t) iFcode, iQuant);
2060    
2061            if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))
2062                                                                    && ((int32_t) iMinSAD <
2063                                                                            prevMB->sad8[iSubBlock]))) {
2064                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2065                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2066                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
2067                          goto PMVfast8_Terminate_with_Refine;                          goto PMVfast8_Terminate_with_Refine;
2068          }          }
2069    
2070    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2071       vector of the median.
2072       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2073    */
2074    
2075            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[iSubBlock])))
2076                    iFound = 2;
2077    
2078    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2079       Otherwise select large Diamond Search.
2080    */
2081    
2082            if ((!MVzero(pmv[0])) || (threshB < 1536 / 4) || (bPredEq))
2083                    iDiamondSize = 1;               // 1 halfpel!
2084            else
2085                    iDiamondSize = 2;               // 2 halfpel = 1 full pixel!
2086    
2087            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2088                    iDiamondSize *= 2;
2089    
2090    
2091  /*  /*
2092     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.
2093     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
2094     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
2095     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
2096  */  */
2097    
2098  // the prediction might be even better than mv16  // the median prediction might be even better than mv16
         CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);  
2099    
2100  // (0,0) is always possible          if (!MVequal(pmv[0], startMV))
2101                    CHECK_MV8_CANDIDATE(center_x, center_y);
2102    
2103    // (0,0) if needed
2104            if (!MVzero(pmv[0]))
2105                    if (!MVzero(startMV))
2106          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
2107    
2108  // previous frame MV is always possible  // previous frame MV if needed
2109          CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);          if (!MVzero(prevMB->mvs[iSubBlock]))
2110                    if (!MVequal(prevMB->mvs[iSubBlock], startMV))
2111                            if (!MVequal(prevMB->mvs[iSubBlock], pmv[0]))
2112                                    CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,
2113                                                                            prevMB->mvs[iSubBlock].y);
2114    
2115            if ((iMinSAD <= threshA) ||
2116                    (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2117                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2118                    if (MotionFlags & PMV_QUICKSTOP16)
2119                            goto PMVfast8_Terminate_without_Refine;
2120                    if (MotionFlags & PMV_EARLYSTOP16)
2121                            goto PMVfast8_Terminate_with_Refine;
2122            }
2123    
2124  // left neighbour, if allowed  // left neighbour, if allowed and needed
2125          if (psad[1] != MV_MAX_ERROR)          if (!MVzero(pmv[1]))
2126          {                  if (!MVequal(pmv[1], startMV))
2127                  if (!(MotionFlags & PMV_HALFPEL8 ))                          if (!MVequal(pmv[1], prevMB->mvs[iSubBlock]))
2128                  {       pmv[1].x = EVEN(pmv[1].x);                                  if (!MVequal(pmv[1], pmv[0])) {
2129                                            if (!(MotionFlags & PMV_HALFPEL8)) {
2130                                                    pmv[1].x = EVEN(pmv[1].x);
2131                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
2132                  }                  }
2133                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
2134          }          }
2135    // top neighbour, if allowed and needed
2136  // top neighbour, if allowed          if (!MVzero(pmv[2]))
2137          if (psad[2] != MV_MAX_ERROR)                  if (!MVequal(pmv[2], startMV))
2138          {                          if (!MVequal(pmv[2], prevMB->mvs[iSubBlock]))
2139                  if (!(MotionFlags & PMV_HALFPEL8 ))                                  if (!MVequal(pmv[2], pmv[0]))
2140                  {       pmv[2].x = EVEN(pmv[2].x);                                          if (!MVequal(pmv[2], pmv[1])) {
2141                                                    if (!(MotionFlags & PMV_HALFPEL8)) {
2142                                                            pmv[2].x = EVEN(pmv[2].x);
2143                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
2144                  }                  }
2145                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
2146    
2147  // top right neighbour, if allowed  // top right neighbour, if allowed and needed
2148                  if (psad[3] != MV_MAX_ERROR)                                                  if (!MVzero(pmv[3]))
2149                  {                                                          if (!MVequal(pmv[3], startMV))
2150                          if (!(MotionFlags & PMV_HALFPEL8 ))                                                                  if (!MVequal(pmv[3], prevMB->mvs[iSubBlock]))
2151                          {       pmv[3].x = EVEN(pmv[3].x);                                                                          if (!MVequal(pmv[3], pmv[0]))
2152                                                                                    if (!MVequal(pmv[3], pmv[1]))
2153                                                                                            if (!MVequal(pmv[3], pmv[2])) {
2154                                                                                                    if (!
2155                                                                                                            (MotionFlags &
2156                                                                                                             PMV_HALFPEL8)) {
2157                                                                                                            pmv[3].x = EVEN(pmv[3].x);
2158                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
2159                          }                          }
2160                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                                  CHECK_MV8_CANDIDATE(pmv[3].x,
2161                                                                                                                                            pmv[3].y);
2162                  }                  }
2163          }          }
2164    
2165            if ((MVzero(*currMV)) &&
2166                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2167                    iMinSAD -= MV8_00_BIAS;
2168    
2169    
2170  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
2171     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.
2172  */  */
2173    
2174          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
2175          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2176                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2177                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
2178                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
2179                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1424  Line 2193 
2193          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2194    
2195  /* 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 */
2196          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
2197                                           x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2198                                           currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2199                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2200                                                      iQuant, iFound);
2201    
2202          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
2203                  *currMV = newMV;                  *currMV = newMV;
2204                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2205          }          }
2206    
2207          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2208  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
2209    
2210                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2211                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2212                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2213                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2214                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2215                                                                      iDiamondSize, iFcode, iQuant, iFound);
2216    
2217                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2218                          *currMV = newMV;                          *currMV = newMV;
2219                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2220                  }                  }
2221                  }                  }
2222    
2223                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2224                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2225                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2226                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2227                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2228                                                                      iQuant, iFound);
2229    
2230                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2231                          *currMV = newMV;                          *currMV = newMV;
2232                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2233                  }                  }
# Line 1472  Line 2240 
2240    
2241  PMVfast8_Terminate_with_Refine:  PMVfast8_Terminate_with_Refine:
2242          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2243                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2244                                                   x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2245                                                   currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2246                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2247    
2248    
2249  PMVfast8_Terminate_without_Refine:  PMVfast8_Terminate_without_Refine:
2250          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2251          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2252    
2253          return iMinSAD;          return iMinSAD;
2254  }  }
2255    
2256  int32_t EPZSSearch16(  int32_t
2257                                          const uint8_t * const pRef,  EPZSSearch16(const uint8_t * const pRef,
2258                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2259                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2260                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2261                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2262                                          const int x, const int y,                           const int x,
2263                             const int y,
2264                            const int start_x,
2265                            const int start_y,
2266                            const int center_x,
2267                            const int center_y,
2268                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2269                             const uint32_t iQuant,
2270                             const uint32_t iFcode,
2271                                          const MBParam * const pParam,                                          const MBParam * const pParam,
2272                                          MACROBLOCK * const pMBs,                           const MACROBLOCK * const pMBs,
2273                             const MACROBLOCK * const prevMBs,
2274                                          VECTOR * const currMV,                                          VECTOR * const currMV,
2275                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
2276  {  {
2277          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
2278          const uint32_t iHcount = pParam->mb_height;          const uint32_t iHcount = pParam->mb_height;
         const int32_t iFcode = pParam->fixed_code;  
         const int32_t iQuant = pParam->quant;  
2279    
2280          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
2281          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
# Line 1521  Line 2295 
2295          int32_t psad[8];          int32_t psad[8];
2296    
2297          static MACROBLOCK * oldMBs = NULL;          static MACROBLOCK * oldMBs = NULL;
2298          MACROBLOCK * const pMB = pMBs + x + y * iWcount;  
2299    //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
2300            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2301          MACROBLOCK * oldMB = NULL;          MACROBLOCK * oldMB = NULL;
2302    
2303          static int32_t thresh2;           int32_t thresh2;
2304          int32_t bPredEq;          int32_t bPredEq;
2305          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2306    
2307          MainSearch16FuncPtr EPZSMainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
2308    
2309          if (oldMBs == NULL)          if (oldMBs == NULL) {
2310          {       oldMBs = (MACROBLOCK*) calloc(1,iWcount*iHcount*sizeof(MACROBLOCK));                  oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
2311                  fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));  //      fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
2312          }          }
2313          oldMB = oldMBs + x + y * iWcount;          oldMB = oldMBs + x + y * iWcount;
2314    
2315  /* Get maximum range */  /* Get maximum range */
2316          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2317                          x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
   
 /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  
2318    
2319          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
2320          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2321            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2322            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2323            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2324          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2325            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2326          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2327    
2328  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2329          MinSAD=SAD          MinSAD=SAD
# Line 1560  Line 2334 
2334    
2335  // Prepare for main loop  // Prepare for main loop
2336    
2337          *currMV=pmv[0];         /* current best := median prediction */          currMV->x = start_x;
2338          if (!(MotionFlags & PMV_HALFPEL16))          currMV->y = start_y;
2339          {  
2340            if (!(MotionFlags & PMV_HALFPEL16)) {
2341                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2342                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2343          }          }
# Line 1578  Line 2353 
2353    
2354  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2355    
2356          iMinSAD = sad16( cur,          iMinSAD =
2357                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
2358                  iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2359          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2360            iMinSAD +=
2361                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2362                                              (uint8_t) iFcode, iQuant);
2363    
2364  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2365          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )          if ((iMinSAD < 256) ||
2366                  {                  ((MVequal(*currMV, prevMB->mvs[0])) &&
2367                     ((int32_t) iMinSAD < prevMB->sad16))) {
2368                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2369                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2370                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1595  Line 2374 
2374  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2375    
2376  // previous frame MV  // previous frame MV
2377          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
2378    
2379  // set threshhold based on Min of Prediction and SAD of collocated block  // set threshhold based on Min of Prediction and SAD of collocated block
2380  // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want  // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
2381    
2382          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
2383                  thresh2 =  512;                  thresh2 =  512;
2384          }          } else {
         else  
         {  
2385  /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */  /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */
2386    
2387                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
# Line 1617  Line 2393 
2393    
2394    
2395  // left neighbour, if allowed  // left neighbour, if allowed
2396          if (x != 0)          if (x != 0) {
2397          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2398                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2399                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2400                  }                  }
2401                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
2402          }          }
   
2403  // top neighbour, if allowed  // top neighbour, if allowed
2404          if (y != 0)          if (y != 0) {
2405          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2406                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2407                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2408                  }                  }
2409                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
2410    
2411  // top right neighbour, if allowed  // top right neighbour, if allowed
2412                  if (x != (iWcount-1))                  if ((uint32_t) x != (iWcount - 1)) {
2413                  {                          if (!(MotionFlags & PMV_HALFPEL16)) {
2414                          if (!(MotionFlags & PMV_HALFPEL16 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2415                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2416                          }                          }
2417                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
# Line 1651  Line 2423 
2423  */  */
2424    
2425          if ( (iMinSAD <= thresh2)          if ( (iMinSAD <= thresh2)
2426                  || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD <= pMB->sad16) ) )                  || (MVequal(*currMV, prevMB->mvs[0]) &&
2427                  {                          ((int32_t) iMinSAD <= prevMB->sad16))) {
2428                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2429                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2430                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1661  Line 2433 
2433    
2434  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
2435    
2436          backupMV = pMB->mvs[0];                 // last MV          backupMV = prevMB->mvs[0];      // collocated MV
2437          backupMV.x += (pMB->mvs[0].x - oldMB->mvs[0].x );       // acceleration X          backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x);     // acceleration X
2438          backupMV.y += (pMB->mvs[0].y - oldMB->mvs[0].y );       // acceleration Y          backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y);     // acceleration Y
2439    
2440          CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);          CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);
2441    
2442  // left neighbour  // left neighbour
2443          if (x != 0)          if (x != 0)
2444                  CHECK_MV16_CANDIDATE((oldMB-1)->mvs[0].x,oldMB->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB - 1)->mvs[0].x, (prevMB - 1)->mvs[0].y);
2445    
2446  // top neighbour  // top neighbour
2447          if (y != 0)          if (y != 0)
2448                  CHECK_MV16_CANDIDATE((oldMB-iWcount)->mvs[0].x,oldMB->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,
2449                                                             (prevMB - iWcount)->mvs[0].y);
2450    
2451  // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs  // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
2452    
2453          if (x != iWcount-1)          if ((uint32_t) x != iWcount - 1)
2454                  CHECK_MV16_CANDIDATE((pMB+1)->mvs[0].x,oldMB->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB + 1)->mvs[0].x, (prevMB + 1)->mvs[0].y);
2455    
2456  // bottom neighbour, dito  // bottom neighbour, dito
2457          if (y != iHcount-1)          if ((uint32_t) y != iHcount - 1)
2458                  CHECK_MV16_CANDIDATE((pMB+iWcount)->mvs[0].x,oldMB->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,
2459                                                             (prevMB + iWcount)->mvs[0].y);
2460    
2461  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
2462          if (iMinSAD <= thresh2)          if (iMinSAD <= thresh2) {
                 {  
2463                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2464                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2465                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1697  Line 2470 
2470    
2471          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2472    
 /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  
   
2473          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
2474                  EPZSMainSearchPtr = Square16_MainSearch;                  MainSearchPtr = Square16_MainSearch;
2475          else          else
2476                  EPZSMainSearchPtr = Diamond16_MainSearch;           if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2477                    MainSearchPtr = AdvDiamond16_MainSearch;
2478            else
2479                    MainSearchPtr = Diamond16_MainSearch;
2480    
2481          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
                         x, y,  
                         currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,  
                         2, iFcode, iQuant, 0);  
2482    
2483          if (iSAD < iMinSAD)          iSAD =
2484          {                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2485                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2486                                                      min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2487    
2488            if (iSAD < iMinSAD) {
2489                  *currMV = newMV;                  *currMV = newMV;
2490                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2491          }          }
2492    
2493    
2494          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
2495  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2496    
2497                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2498                  {                          iSAD =
2499                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2500                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2501                                  pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2502                                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    2, iFcode, iQuant, 0);
2503                  }                  }
2504    
2505                  if (iSAD < iMinSAD)                  if (iSAD < iMinSAD) {
                 {  
2506                          *currMV = newMV;                          *currMV = newMV;
2507                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2508                  }                  }
2509    
2510                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2511                  {                          iSAD =
2512                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2513                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2514                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
                         pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, /*iDiamondSize*/ 2, iFcode, iQuant, 0);  
2515    
2516                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2517                                  *currMV = newMV;                                  *currMV = newMV;
2518                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2519                          }                          }
# Line 1753  Line 2524 
2524    
2525  EPZS16_Terminate_with_Refine:  EPZS16_Terminate_with_Refine:
2526          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
2527                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2528                                  x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2529                                  currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2530                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
2531    
2532  EPZS16_Terminate_without_Refine:  EPZS16_Terminate_without_Refine:
2533    
2534          *oldMB = *pMB;          *oldMB = *prevMB;
2535    
2536          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2537          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2538          return iMinSAD;          return iMinSAD;
2539  }  }
2540    
2541    
2542  int32_t EPZSSearch8(  int32_t
2543                                          const uint8_t * const pRef,  EPZSSearch8(const uint8_t * const pRef,
2544                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2545                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2546                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2547                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2548                                          const int x, const int y,                          const int x,
2549                                          const int start_x, const int start_y,                          const int y,
2550                            const int start_x,
2551                            const int start_y,
2552                            const int center_x,
2553                            const int center_y,
2554                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2555                            const uint32_t iQuant,
2556                            const uint32_t iFcode,
2557                                          const MBParam * const pParam,                                          const MBParam * const pParam,
2558                                          MACROBLOCK * const pMBs,                          const MACROBLOCK * const pMBs,
2559                            const MACROBLOCK * const prevMBs,
2560                                          VECTOR * const currMV,                                          VECTOR * const currMV,
2561                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
2562  {  {
2563          const uint32_t iWcount = pParam->mb_width;  /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
         const int32_t iFcode = pParam->fixed_code;  
         const int32_t iQuant = pParam->quant;  
2564    
2565            const uint32_t iWcount = pParam->mb_width;
2566          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
2567          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
2568          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 1807  Line 2584 
2584    
2585          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);
2586    
2587          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2588            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
2589    
2590          int32_t bPredEq;          int32_t bPredEq;
2591          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2592    
2593          MainSearch8FuncPtr EPZSMainSearchPtr;          MainSearch8FuncPtr MainSearchPtr;
2594    
2595  /* Get maximum range */  /* Get maximum range */
2596          get_range(&min_dx, &max_dx, &min_dy, &max_dy,          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2597                          x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2598    
2599  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2600    
2601          if (!(MotionFlags & PMV_HALFPEL8 ))          if (!(MotionFlags & PMV_HALFPEL8)) {
2602          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2603            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2604            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2605            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2606          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2607            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2608          bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);          bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2609    
2610    
2611  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
# Line 1840  Line 2618 
2618  // Prepare for main loop  // Prepare for main loop
2619    
2620    
2621          if (!(MotionFlags & PMV_HALFPEL8))          if (!(MotionFlags & PMV_HALFPEL8)) {
         {  
2622                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2623                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2624          }          }
# Line 1858  Line 2635 
2635  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2636    
2637    
2638          iMinSAD = sad8( cur,          iMinSAD =
2639                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  sad8(cur,
2640                  iEdgedWidth);                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2641          iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                  iEdgedWidth), iEdgedWidth);
2642            iMinSAD +=
2643                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2644                                             (uint8_t) iFcode, iQuant);
2645    
2646    
2647  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2648          if (iMinSAD < 256/4 )          if (iMinSAD < 256 / 4) {
                 {  
2649                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2650                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2651                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
# Line 1875  Line 2654 
2654    
2655  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2656    
 // previous frame MV  
         CHECK_MV8_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);  
2657    
2658  // MV=(0,0) is often a good choice  // MV=(0,0) is often a good choice
   
2659          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
2660    
2661    // previous frame MV
2662            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x, prevMB->mvs[iSubBlock].y);
2663    
2664    // left neighbour, if allowed
2665            if (psad[1] != MV_MAX_ERROR) {
2666                    if (!(MotionFlags & PMV_HALFPEL8)) {
2667                            pmv[1].x = EVEN(pmv[1].x);
2668                            pmv[1].y = EVEN(pmv[1].y);
2669                    }
2670                    CHECK_MV8_CANDIDATE(pmv[1].x, pmv[1].y);
2671            }
2672    // top neighbour, if allowed
2673            if (psad[2] != MV_MAX_ERROR) {
2674                    if (!(MotionFlags & PMV_HALFPEL8)) {
2675                            pmv[2].x = EVEN(pmv[2].x);
2676                            pmv[2].y = EVEN(pmv[2].y);
2677                    }
2678                    CHECK_MV8_CANDIDATE(pmv[2].x, pmv[2].y);
2679    
2680    // top right neighbour, if allowed
2681                    if (psad[3] != MV_MAX_ERROR) {
2682                            if (!(MotionFlags & PMV_HALFPEL8)) {
2683                                    pmv[3].x = EVEN(pmv[3].x);
2684                                    pmv[3].y = EVEN(pmv[3].y);
2685                            }
2686                            CHECK_MV8_CANDIDATE(pmv[3].x, pmv[3].y);
2687                    }
2688            }
2689    
2690    /*  // this bias is zero anyway, at the moment!
2691    
2692            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
2693                    iMinSAD -= MV8_00_BIAS;
2694    
2695    */
2696    
2697  /* Terminate if MinSAD <= T_2  /* Terminate if MinSAD <= T_2
2698     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
2699  */  */
2700    
2701          if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */          if (iMinSAD < 512 / 4) {        /* T_2 == 512/4 hardcoded */
                 {  
2702                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2703                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2704                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
2705                                  goto EPZS8_Terminate_with_Refine;                                  goto EPZS8_Terminate_with_Refine;
2706                  }                  }
2707    
2708  /************ (if Diamond Search)  **************/  /************ (Diamond Search)  **************/
2709    
2710          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2711    
2712          if (!(MotionFlags & PMV_HALFPELDIAMOND8))          if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2713                  iDiamondSize *= 2;                  iDiamondSize *= 2;
2714    
2715  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  /* default: use best prediction as starting point for one call of EPZS_MainSearch */
2716    
2717  //      if (MotionFlags & PMV_USESQUARES8)  // there is no EPZS^2 for inter4v at the moment
 //              EPZSMainSearchPtr = Square8_MainSearch;  
 //      else  
                 EPZSMainSearchPtr = Diamond8_MainSearch;  
   
         iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,  
                 x, y,  
                 currMV->x, currMV->y, iMinSAD, &newMV,  
                 pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth,  
                 iDiamondSize, iFcode, iQuant, 00);  
2718    
2719      if (MotionFlags & PMV_USESQUARES8)
2720          MainSearchPtr = Square8_MainSearch;
2721      else
2722    
2723          if (iSAD < iMinSAD)          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2724          {                  MainSearchPtr = AdvDiamond8_MainSearch;
2725            else
2726                    MainSearchPtr = Diamond8_MainSearch;
2727    
2728            iSAD =
2729                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2730                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2731                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2732                                                      iQuant, 0);
2733    
2734    
2735            if (iSAD < iMinSAD) {
2736                  *currMV = newMV;                  *currMV = newMV;
2737                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2738          }          }
2739    
2740          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2741  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2742    
2743                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2744                  {                          iSAD =
2745                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2746                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2747                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2748                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, 0);
2749    
2750                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2751                                  *currMV = newMV;                                  *currMV = newMV;
2752                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2753                          }                          }
2754                  }                  }
2755    
2756                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2757                  {                          iSAD =
2758                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2759                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2760                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2761                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iQuant, 0);
2762    
2763                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2764                                  *currMV = newMV;                                  *currMV = newMV;
2765                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2766                          }                          }
# Line 1958  Line 2771 
2771    
2772  EPZS8_Terminate_with_Refine:  EPZS8_Terminate_with_Refine:
2773          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2774                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2775                                  x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2776                                  currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2777                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2778    
2779  EPZS8_Terminate_without_Refine:  EPZS8_Terminate_without_Refine:
2780    
2781          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2782          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2783            return iMinSAD;
2784    }
2785    
2786    
2787    
2788    int32_t
2789    PMVfastIntSearch16(const uint8_t * const pRef,
2790                                    const uint8_t * const pRefH,
2791                                    const uint8_t * const pRefV,
2792                                    const uint8_t * const pRefHV,
2793                                    const IMAGE * const pCur,
2794                                    const int x,
2795                                    const int y,
2796                                    const int start_x,              /* start should be most likely vector */
2797                                    const int start_y,
2798                                    const int center_x,             /* center is from where length of MVs is measured */
2799                                    const int center_y,
2800                                    const uint32_t MotionFlags,
2801                           &