[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 96, Mon Apr 1 22:47:58 2002 UTC revision 605, Sat Oct 19 12:20:33 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   *               2002 Michael Militzer <michael@xvid.org>
  *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop  
  *             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.  
8   *   *
9   *  Michael Militzer <isibaar@videocoding.de>   *  This program is an implementation of a part of one or more MPEG-4
10     *  Video tools as specified in ISO/IEC 14496-2 standard.  Those intending
11     *  to use this software module in hardware or software products are
12     *  advised that its use may infringe existing patents or copyrights, and
13     *  any such use would be at such party's own risk.  The original
14     *  developer of this software module and his/her company, and subsequent
15     *  editors and their companies, will have no liability for use of this
16     *  software or modifications or derivatives thereof.
17   *   *
18   **************************************************************************/   *  This program is free software; you can redistribute it and/or modify
19     *  it under the terms of the GNU General Public License as published by
20     *  the Free Software Foundation; either version 2 of the License, or
21     *  (at your option) any later version.
22     *
23     *  This program is distributed in the hope that it will be useful,
24     *  but WITHOUT ANY WARRANTY; without even the implied warranty of
25     *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26     *  GNU General Public License for more details.
27     *
28     *  You should have received a copy of the GNU General Public License
29     *  along with this program; if not, write to the Free Software
30     *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
31     *
32     *************************************************************************/
33    
34  #include <assert.h>  #include <assert.h>
35  #include <stdio.h>  #include <stdio.h>
# Line 40  Line 40 
40  #include "../prediction/mbprediction.h"  #include "../prediction/mbprediction.h"
41  #include "../global.h"  #include "../global.h"
42  #include "../utils/timer.h"  #include "../utils/timer.h"
43    #include "motion.h"
44  #include "sad.h"  #include "sad.h"
45    
 // 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);  
46    
47    
48  int32_t PMVfastSearch8(  static int32_t lambda_vec16[32] =       /* rounded values for lambda param for weight of motion bits as in modified H.26L */
49                                          const uint8_t * const pRef,  { 0, (int) (1.00235 + 0.5), (int) (1.15582 + 0.5), (int) (1.31976 + 0.5),
50                                          const uint8_t * const pRefH,                  (int) (1.49591 + 0.5), (int) (1.68601 + 0.5),
51                                          const uint8_t * const pRefV,          (int) (1.89187 + 0.5), (int) (2.11542 + 0.5), (int) (2.35878 + 0.5),
52                                          const uint8_t * const pRefHV,                  (int) (2.62429 + 0.5), (int) (2.91455 + 0.5),
53                                          const IMAGE * const pCur,          (int) (3.23253 + 0.5), (int) (3.58158 + 0.5), (int) (3.96555 + 0.5),
54                                          const int x, const int y,                  (int) (4.38887 + 0.5), (int) (4.85673 + 0.5),
55                                          const int start_x, int start_y,          (int) (5.37519 + 0.5), (int) (5.95144 + 0.5), (int) (6.59408 + 0.5),
56                                          const uint32_t MotionFlags,                  (int) (7.31349 + 0.5), (int) (8.12242 + 0.5),
57                                          const MBParam * const pParam,          (int) (9.03669 + 0.5), (int) (10.0763 + 0.5), (int) (11.2669 + 0.5),
58                                          MACROBLOCK * const pMBs,                  (int) (12.6426 + 0.5), (int) (14.2493 + 0.5),
59                                          VECTOR * const currMV,          (int) (16.1512 + 0.5), (int) (18.442 + 0.5), (int) (21.2656 + 0.5),
60                                          VECTOR * const currPMV);                  (int) (24.8580 + 0.5), (int) (29.6436 + 0.5),
61            (int) (36.4949 + 0.5)
62  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);  
63    
64    static int32_t *lambda_vec8 = lambda_vec16;     /* same table for INTER and INTER4V for now */
65    
 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);  
66    
 typedef MainSearch16Func* MainSearch16FuncPtr;  
   
   
 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);  
   
 typedef MainSearch8Func* MainSearch8FuncPtr;  
67    
68  // mv.length table  // mv.length table
69  static const uint32_t mvtab[33] = {  static const uint32_t mvtab[33] = {
# Line 181  Line 74 
74  };  };
75    
76    
77  static __inline uint32_t mv_bits(int32_t component, const uint32_t iFcode)  static __inline uint32_t
78    mv_bits(int32_t component,
79                    const uint32_t iFcode)
80  {  {
81      if (component == 0)      if (component == 0)
82                  return 1;                  return 1;
# Line 189  Line 84 
84      if (component < 0)      if (component < 0)
85                  component = -component;                  component = -component;
86    
87      if (iFcode == 1)          if (iFcode == 1) {
     {  
88                  if (component > 32)                  if (component > 32)
89                      component = 32;                      component = 32;
90    
# Line 207  Line 101 
101  }  }
102    
103    
104  static __inline uint32_t calc_delta_16(const int32_t dx, const int32_t dy, const uint32_t iFcode)  static __inline uint32_t
105  {  calc_delta_16(const int32_t dx,
106          return NEIGH_TEND_16X16 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));                            const int32_t dy,
107  }                            const uint32_t iFcode,
108                              const uint32_t iQuant)
109  static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode)  {
110            return NEIGH_TEND_16X16 * lambda_vec16[iQuant] * (mv_bits(dx, iFcode) +
111  {                                                                                                            mv_bits(dy, iFcode));
112      return NEIGH_TEND_8X8 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));  }
113  }  
114    static __inline uint32_t
115    calc_delta_8(const int32_t dx,
116                             const int32_t dy,
117                             const uint32_t iFcode,
118  /* calculate the min/max range (in halfpixels)                           const uint32_t iQuant)
119          relative to the _MACROBLOCK_ position  {
120  */          return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) +
121                                                                                                       mv_bits(dy, iFcode));
122  static void __inline get_range(  }
123          int32_t * const min_dx, int32_t * const max_dx,  
124          int32_t * const min_dy, int32_t * const max_dy,  bool
125          const uint32_t x, const uint32_t y,  MotionEstimation(MBParam * const pParam,
126          const uint32_t block_sz,                                        // block dimension, 8 or 16                                   FRAMEINFO * const current,
127          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,  
128          const IMAGE * const pRefH,          const IMAGE * const pRefH,
129          const IMAGE * const pRefV,          const IMAGE * const pRefV,
130          const IMAGE * const pRefHV,          const IMAGE * const pRefHV,
         IMAGE * const pCurrent,  
131          const uint32_t iLimit)          const uint32_t iLimit)
   
132  {  {
133          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
134          const uint32_t iHcount = pParam->mb_height;          const uint32_t iHcount = pParam->mb_height;
135            MACROBLOCK *const pMBs = current->mbs;
136            MACROBLOCK *const prevMBs = reference->mbs;
137            const IMAGE *const pCurrent = &current->image;
138            const IMAGE *const pRef = &reference->image;
139    
140          uint32_t i, j, iIntra = 0;          static const VECTOR zeroMV = { 0, 0 };
141            VECTOR predMV;
142    
143          VECTOR mv16;          uint32_t x, y;
144          VECTOR pmv16;          uint32_t iIntra = 0;
145            VECTOR pmv;
146    
147          int32_t sad8 = 0;          if (sadInit)
148          int32_t sad16;                  (*sadInit) ();
         int32_t deviation;  
149    
150          // note: i==horizontal, j==vertical          for (y = 0; y < iHcount; y++)   {
151          for (i = 0; i < iHcount; i++)                  for (x = 0; x < iWcount; x ++)  {
                 for (j = 0; j < iWcount; j++)  
                 {  
                         MACROBLOCK *pMB = &pMBs[j + i * iWcount];  
152    
153                          sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,                          MACROBLOCK *const pMB = &pMBs[x + y * iWcount];
                                          j, i, pParam->motion_flags,  
                                          pParam, pMBs, &mv16, &pmv16);  
                         pMB->sad16=sad16;  
154    
155                            predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
156    
157                          /* decide: MODE_INTER or MODE_INTRA                          pMB->sad16 =
158                             if (dev_intra < sad_inter - 2 * nb) use_intra                                  SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
159                          */                                                   x, y, predMV.x, predMV.y, predMV.x, predMV.y,
160                                                     current->motion_flags, current->quant,
161                                                     current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,
162                                                     &pMB->pmvs[0]);
163    
164                          deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width);                          if (0 < (pMB->sad16 - MV16_INTER_BIAS)) {
165                                    int32_t deviation;
166    
167                          if (deviation < (sad16 - INTER_BIAS))                                  deviation =
168                          {                                          dev16(pCurrent->y + x * 16 + y * 16 * pParam->edged_width,
169                                                      pParam->edged_width);
170    
171                                    if (deviation < (pMB->sad16 - MV16_INTER_BIAS)) {
172                                  pMB->mode = MODE_INTRA;                                  pMB->mode = MODE_INTRA;
173                                  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] =
174                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;                                                  pMB->mvs[3] = zeroMV;
175                                            pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
176                                                    pMB->sad8[3] = 0;
177    
178                                  iIntra++;                                  iIntra++;
179                                  if(iIntra >= iLimit)                                  if(iIntra >= iLimit)
# Line 370  Line 181 
181    
182                                  continue;                                  continue;
183                          }                          }
   
                         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];  
184                          }                          }
185    
186                            pmv = pMB->pmvs[0];
187                            if (current->global_flags & XVID_INTER4V)
188                                    if ((!(current->global_flags & XVID_LUMIMASKING) ||
189                                             pMB->dquant == NO_CHANGE)) {
190                                            int32_t sad8 = IMV16X16 * current->quant;
191    
192                                            if (sad8 < pMB->sad16) {
193                                                    sad8 += pMB->sad8[0] =
194                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
195                                                                            pCurrent, 2 * x, 2 * y,
196                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
197                                                                            current->motion_flags,
198                                                                            current->quant, current->fcode, pParam,
199                                                                            pMBs, prevMBs, &pMB->mvs[0],
200                                                                            &pMB->pmvs[0]);
201                                            }
202                                            if (sad8 < pMB->sad16) {
203    
204                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 1);
205                                                    sad8 += pMB->sad8[1] =
206                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
207                                                                            pCurrent, 2 * x + 1, 2 * y,
208                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
209                                                                            current->motion_flags,
210                                                                            current->quant, current->fcode, pParam,
211                                                                            pMBs, prevMBs, &pMB->mvs[1],
212                                                                            &pMB->pmvs[1]);
213                                            }
214                                            if (sad8 < pMB->sad16) {
215                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 2);
216                                                    sad8 += pMB->sad8[2] =
217                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
218                                                                            pCurrent, 2 * x, 2 * y + 1,
219                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
220                                                                            current->motion_flags,
221                                                                            current->quant, current->fcode, pParam,
222                                                                            pMBs, prevMBs, &pMB->mvs[2],
223                                                                            &pMB->pmvs[2]);
224                                            }
225                                            if (sad8 < pMB->sad16) {
226                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 3);
227                                                    sad8 += pMB->sad8[3] =
228                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
229                                                                            pCurrent, 2 * x + 1, 2 * y + 1,
230                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
231                                                                            current->motion_flags,
232                                                                            current->quant, current->fcode, pParam,
233                                                                            pMBs, prevMBs,
234                                                                            &pMB->mvs[3],
235                                                                            &pMB->pmvs[3]);
236                                            }
237    
238                          /* decide: MODE_INTER or MODE_INTER4V                          /* decide: MODE_INTER or MODE_INTER4V
239                             mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v                                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
240                          */                          */
241    
242                          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  
243                                          pMB->mode = MODE_INTER4V;                                          pMB->mode = MODE_INTER4V;
244                                                    pMB->sad8[0] *= 4;
245                                                    pMB->sad8[1] *= 4;
246                                                    pMB->sad8[2] *= 4;
247                                                    pMB->sad8[3] *= 4;
248                                                    continue;
249                          }                          }
250                          else  
251                          {                                  }
252                                  sad8 = sad16;  
253                                  pMB->mode = MODE_INTER;                                  pMB->mode = MODE_INTER;
254                                  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 */
255                                  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;
256                                  pMB->pmvs[0].x = pmv16.x;                          pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =
257                                  pMB->pmvs[0].y = pmv16.y;                                  pMB->sad16;
258                          }                          }
259                  }                  }
260    
261          return 0;          return 0;
262  }  }
263    
 #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )  
   
 #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )  
   
264    
265  #define CHECK_MV16_ZERO {\  #define CHECK_MV16_ZERO {\
266    if ( (0 <= max_dx) && (0 >= min_dx) \    if ( (0 <= max_dx) && (0 >= min_dx) \
267      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
268    { \    { \
269      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); \
270      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; \  
271      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
272      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
273  }  }
274    
275  #define NOCHECK_MV16_CANDIDATE(X,Y) { \  #define NOCHECK_MV16_CANDIDATE(X,Y) { \
276      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); \
277      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);\
278      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
279      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
280  }  }
# Line 454  Line 284 
284      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
285    { \    { \
286      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); \
287      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);\
288      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
289      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
290  }  }
# Line 464  Line 294 
294      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
295    { \    { \
296      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); \
297      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);\
298      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
299      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
300  }  }
# Line 474  Line 304 
304      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
305    { \    { \
306      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
307      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
308      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
309      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
310  }  }
# Line 482  Line 312 
312    
313  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
314    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); \
315    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);\
316    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
317    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
318  }  }
# Line 490  Line 320 
320  #define NOCHECK_MV8_CANDIDATE(X,Y) \  #define NOCHECK_MV8_CANDIDATE(X,Y) \
321    { \    { \
322      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); \
323      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);\
324      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
325      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
326  }  }
# Line 500  Line 330 
330      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
331    { \    { \
332      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); \
333      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);\
334      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
335      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
336  }  }
# Line 510  Line 340 
340      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
341    { \    { \
342      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); \
343      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);\
344      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
345      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
346  }  }
# Line 520  Line 350 
350      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
351    { \    { \
352      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
353      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
354      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
355      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
356  }  }
357    
358    #if 0
359  /* too slow and not fully functional at the moment */  /* too slow and not fully functional at the moment */
 /*  
360  int32_t ZeroSearch16(  int32_t ZeroSearch16(
361                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
362                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
# Line 535  Line 365 
365                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
366                                          const int x, const int y,                                          const int x, const int y,
367                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
368                                            const uint32_t iQuant,
369                                            const uint32_t iFcode,
370                                          MBParam * const pParam,                                          MBParam * const pParam,
371                                          MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
372                                            const MACROBLOCK * const prevMBs,
373                                          VECTOR * const currMV,                                          VECTOR * const currMV,
374                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
375  {  {
376          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
         const int32_t iQuant = pParam->quant;  
377          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
378          int32_t iSAD;          int32_t iSAD;
379          int32_t pred_x,pred_y;          VECTOR pred;
380    
381    
382          get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);          pred = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
383    
384          iSAD = sad16( cur,          iSAD = sad16( cur,
385                  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 556  Line 389 
389    
390          currMV->x = 0;          currMV->x = 0;
391          currMV->y = 0;          currMV->y = 0;
392          currPMV->x = -pred_x;          currPMV->x = -pred.x;
393          currPMV->y = -pred_y;          currPMV->y = -pred.y;
394    
395          return iSAD;          return iSAD;
396    
397  }  }
398  */  #endif /* 0 */
399    
400  int32_t Diamond16_MainSearch(  int32_t
401          const uint8_t * const pRef,  Diamond16_MainSearch(const uint8_t * const pRef,
402          const uint8_t * const pRefH,          const uint8_t * const pRefH,
403          const uint8_t * const pRefV,          const uint8_t * const pRefV,
404          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
405          const uint8_t * const cur,          const uint8_t * const cur,
406          const int x, const int y,                                           const int x,
407          int32_t startx, int32_t starty,                                           const int y,
408          int32_t iMinSAD,                                           const int start_x,
409                                             const int start_y,
410                                             int iMinSAD,
411          VECTOR * const currMV,          VECTOR * const currMV,
412          const VECTOR * const pmv,                                           const int center_x,
413          const int32_t min_dx, const int32_t max_dx,                                           const int center_y,
414          const int32_t min_dy, const int32_t max_dy,                                           const int32_t min_dx,
415                                             const int32_t max_dx,
416                                             const int32_t min_dy,
417                                             const int32_t max_dy,
418          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
419          const int32_t iDiamondSize,          const int32_t iDiamondSize,
420          const int32_t iFcode,          const int32_t iFcode,
# Line 586  Line 424 
424  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
425    
426          int32_t iDirection=0;          int32_t iDirection=0;
427            int32_t iDirectionBackup;
428          int32_t iSAD;          int32_t iSAD;
429          VECTOR backupMV;          VECTOR backupMV;
430          backupMV.x = startx;  
431          backupMV.y = starty;          backupMV.x = start_x;
432            backupMV.y = start_y;
433    
434  /* 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 */
435    
# Line 598  Line 438 
438          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
439          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
440    
441          if (iDirection)          if (iDirection) {
442                  while (!iFound)                  while (!iFound) {
                 {  
443                          iFound = 1;                          iFound = 1;
444                          backupMV=*currMV;                          backupMV=*currMV;
445                            iDirectionBackup = iDirection;
446    
447                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
448                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
449                          if ( iDirection != 1)                                                                                     backupMV.y, 1);
450                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
451                          if ( iDirection != 4)                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
452                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                     backupMV.y, 2);
453                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
454                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
455                                                                                       backupMV.y - iDiamondSize, 3);
456                            if (iDirectionBackup != 3)
457                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
458                                                                                       backupMV.y + iDiamondSize, 4);
459                  }                  }
460          else          } else {
461          {                  currMV->x = start_x;
462                  currMV->x = startx;                  currMV->y = start_y;
                 currMV->y = starty;  
463          }          }
464          return iMinSAD;          return iMinSAD;
465  }  }
466    
467  int32_t Square16_MainSearch(  int32_t
468                                          const uint8_t * const pRef,  Square16_MainSearch(const uint8_t * const pRef,
469                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
470                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
471                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
472                                          const uint8_t * const cur,                                          const uint8_t * const cur,
473                                          const int x, const int y,                                          const int x,
474                                          int32_t startx, int32_t starty,                                          const int y,
475                                          int32_t iMinSAD,                                          const int start_x,
476                                            const int start_y,
477                                            int iMinSAD,
478                                          VECTOR * const currMV,                                          VECTOR * const currMV,
479                                          const VECTOR * const pmv,                                          const int center_x,
480                                          const int32_t min_dx, const int32_t max_dx,                                          const int center_y,
481                                          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
482                                            const int32_t max_dx,
483                                            const int32_t min_dy,
484                                            const int32_t max_dy,
485                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
486                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
487                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 645  Line 493 
493          int32_t iDirection=0;          int32_t iDirection=0;
494          int32_t iSAD;          int32_t iSAD;
495          VECTOR backupMV;          VECTOR backupMV;
496          backupMV.x = startx;  
497          backupMV.y = starty;          backupMV.x = start_x;
498            backupMV.y = start_y;
499    
500  /* 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 */
501    
# Line 661  Line 510 
510          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
511          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
512    
513          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
514          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                           backupMV.y - iDiamondSize, 5);
515          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
516          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                                           backupMV.y + iDiamondSize, 6);
517            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
518                                                             backupMV.y - iDiamondSize, 7);
519            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
520                                                             backupMV.y + iDiamondSize, 8);
521    
522    
523          if (iDirection)          if (iDirection) {
524                  while (!iFound)                  while (!iFound) {
                 {  
525                          iFound = 1;                          iFound = 1;
526                          backupMV=*currMV;                          backupMV=*currMV;
527    
528                          switch (iDirection)                          switch (iDirection) {
                         {  
529                                  case 1:                                  case 1:
530                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
531                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                     backupMV.y, 1);
532                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
533                                                                                     backupMV.y - iDiamondSize, 5);
534                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
535                                                                                     backupMV.y - iDiamondSize, 7);
536                                          break;                                          break;
537                                  case 2:                                  case 2:
538                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
539                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   2);
540                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
541                                                                                     backupMV.y + iDiamondSize, 6);
542                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
543                                                                                     backupMV.y + iDiamondSize, 8);
544                                          break;                                          break;
545    
546                                  case 3:                                  case 3:
547                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
548                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
549                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
550                                                                                     backupMV.y - iDiamondSize, 7);
551                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
552                                                                                     backupMV.y + iDiamondSize, 8);
553                                          break;                                          break;
554    
555                                  case 4:                                  case 4:
556                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
557                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
558                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
559                                                                                     backupMV.y - iDiamondSize, 5);
560                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
561                                                                                     backupMV.y + iDiamondSize, 6);
562                                          break;                                          break;
563    
564                                  case 5:                                  case 5:
565                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
566                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   1);
567                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
568                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   3);
569                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
570                                                                                     backupMV.y - iDiamondSize, 5);
571                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
572                                                                                     backupMV.y + iDiamondSize, 6);
573                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
574                                                                                     backupMV.y - iDiamondSize, 7);
575                                          break;                                          break;
576    
577                                  case 6:                                  case 6:
578                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
579                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   2);
580                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
581                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
582                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);  
583                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
584                                                                                     backupMV.y - iDiamondSize, 5);
585                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
586                                                                                     backupMV.y + iDiamondSize, 6);
587                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
588                                                                                     backupMV.y + iDiamondSize, 8);
589    
590                                          break;                                          break;
591    
592                                  case 7:                                  case 7:
593                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
594                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                     backupMV.y, 1);
595                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
596                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
597                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
598                                                                                     backupMV.y - iDiamondSize, 5);
599                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
600                                                                                     backupMV.y - iDiamondSize, 7);
601                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
602                                                                                     backupMV.y + iDiamondSize, 8);
603                                          break;                                          break;
604    
605                                  case 8:                                  case 8:
606                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
607                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
608                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
609                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
610                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
611                                                                                     backupMV.y + iDiamondSize, 6);
612                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
613                                                                                     backupMV.y - iDiamondSize, 7);
614                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
615                                                                                     backupMV.y + iDiamondSize, 8);
616                                          break;                                          break;
617                          default:                          default:
618                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
619                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                                                                   1);
620                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
621                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
622                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
623                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
624                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
625                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
626                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);  
627                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
628                                                                                     backupMV.y - iDiamondSize, 5);
629                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
630                                                                                     backupMV.y + iDiamondSize, 6);
631                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
632                                                                                     backupMV.y - iDiamondSize, 7);
633                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
634                                                                                     backupMV.y + iDiamondSize, 8);
635                                          break;                                          break;
636                          }                          }
637                  }                  }
638          else          } else {
639                  {                  currMV->x = start_x;
640                          currMV->x = startx;                  currMV->y = start_y;
                         currMV->y = starty;  
641                  }                  }
642          return iMinSAD;          return iMinSAD;
643  }  }
644    
645    
646  int32_t Full16_MainSearch(  int32_t
647                                          const uint8_t * const pRef,  Full16_MainSearch(const uint8_t * const pRef,
648                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
649                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
650                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
651                                          const uint8_t * const cur,                                          const uint8_t * const cur,
652                                          const int x, const int y,                                    const int x,
653                                          int32_t startx, int32_t starty,                                    const int y,
654                                          int32_t iMinSAD,                                    const int start_x,
655                                      const int start_y,
656                                      int iMinSAD,
657                                          VECTOR * const currMV,                                          VECTOR * const currMV,
658                                          const VECTOR * const pmv,                                    const int center_x,
659                                          const int32_t min_dx, const int32_t max_dx,                                    const int center_y,
660                                          const int32_t min_dy, const int32_t max_dy,                                    const int32_t min_dx,
661                                      const int32_t max_dx,
662                                      const int32_t min_dy,
663                                      const int32_t max_dy,
664                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
665                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
666                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 775  Line 670 
670          int32_t iSAD;          int32_t iSAD;
671          int32_t dx,dy;          int32_t dx,dy;
672          VECTOR backupMV;          VECTOR backupMV;
673          backupMV.x = startx;  
674          backupMV.y = starty;          backupMV.x = start_x;
675            backupMV.y = start_y;
676    
677          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
678                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
# Line 785  Line 681 
681          return iMinSAD;          return iMinSAD;
682  }  }
683    
684  int32_t Full8_MainSearch(  int32_t
685                                          const uint8_t * const pRef,  AdvDiamond16_MainSearch(const uint8_t * const pRef,
686                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
687                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
688                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
689                                          const uint8_t * const cur,                                          const uint8_t * const cur,
690                                          const int x, const int y,                                                  const int x,
691                                          int32_t startx, int32_t starty,                                                  const int y,
692                                          int32_t iMinSAD,                                                  const int start_xi,
693                                                    const int start_yi,
694                                                    int iMinSAD,
695                                                    VECTOR * const currMV,
696                                                    const int center_x,
697                                                    const int center_y,
698                                                    const int32_t min_dx,
699                                                    const int32_t max_dx,
700                                                    const int32_t min_dy,
701                                                    const int32_t max_dy,
702                                                    const int32_t iEdgedWidth,
703                                                    const int32_t iDiamondSize,
704                                                    const int32_t iFcode,
705                                                    const int32_t iQuant,
706                                                    int iDirection)
707    {
708    
709            int32_t iSAD;
710            int start_x = start_xi, start_y = start_yi;
711    
712    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
713    
714            if (iDirection) {
715                    CHECK_MV16_CANDIDATE(start_x - iDiamondSize, start_y);
716                    CHECK_MV16_CANDIDATE(start_x + iDiamondSize, start_y);
717                    CHECK_MV16_CANDIDATE(start_x, start_y - iDiamondSize);
718                    CHECK_MV16_CANDIDATE(start_x, start_y + iDiamondSize);
719            } else {
720                    int bDirection = 1 + 2 + 4 + 8;
721    
722                    do {
723                            iDirection = 0;
724                            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)
725                                    CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
726    
727                            if (bDirection & 2)
728                                    CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
729    
730                            if (bDirection & 4)
731                                    CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
732    
733                            if (bDirection & 8)
734                                    CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
735    
736                            /* now we're doing diagonal checks near our candidate */
737    
738                            if (iDirection)         //checking if anything found
739                            {
740                                    bDirection = iDirection;
741                                    iDirection = 0;
742                                    start_x = currMV->x;
743                                    start_y = currMV->y;
744                                    if (bDirection & 3)     //our candidate is left or right
745                                    {
746                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
747                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
748                                    } else                  // what remains here is up or down
749                                    {
750                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
751                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
752                                    }
753    
754                                    if (iDirection) {
755                                            bDirection += iDirection;
756                                            start_x = currMV->x;
757                                            start_y = currMV->y;
758                                    }
759                            } else                          //about to quit, eh? not so fast....
760                            {
761                                    switch (bDirection) {
762                                    case 2:
763                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
764                                                                                             start_y - iDiamondSize, 2 + 4);
765                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
766                                                                                             start_y + iDiamondSize, 2 + 8);
767                                            break;
768                                    case 1:
769    
770                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
771                                                                                             start_y - iDiamondSize, 1 + 4);
772                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
773                                                                                             start_y + iDiamondSize, 1 + 8);
774                                            break;
775                                    case 2 + 4:
776                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
777                                                                                             start_y - iDiamondSize, 1 + 4);
778                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
779                                                                                             start_y - iDiamondSize, 2 + 4);
780                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
781                                                                                             start_y + iDiamondSize, 2 + 8);
782                                            break;
783                                    case 4:
784                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
785                                                                                             start_y - iDiamondSize, 2 + 4);
786                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
787                                                                                             start_y - iDiamondSize, 1 + 4);
788                                            break;
789                                    case 8:
790                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
791                                                                                             start_y + iDiamondSize, 2 + 8);
792                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
793                                                                                             start_y + iDiamondSize, 1 + 8);
794                                            break;
795                                    case 1 + 4:
796                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
797                                                                                             start_y + iDiamondSize, 1 + 8);
798                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
799                                                                                             start_y - iDiamondSize, 1 + 4);
800                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
801                                                                                             start_y - iDiamondSize, 2 + 4);
802                                            break;
803                                    case 2 + 8:
804                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
805                                                                                             start_y - iDiamondSize, 1 + 4);
806                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
807                                                                                             start_y + iDiamondSize, 1 + 8);
808                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
809                                                                                             start_y + iDiamondSize, 2 + 8);
810                                            break;
811                                    case 1 + 8:
812                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
813                                                                                             start_y - iDiamondSize, 2 + 4);
814                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
815                                                                                             start_y + iDiamondSize, 2 + 8);
816                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
817                                                                                             start_y + iDiamondSize, 1 + 8);
818                                            break;
819                                    default:                //1+2+4+8 == we didn't find anything at all
820                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
821                                                                                             start_y - iDiamondSize, 1 + 4);
822                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
823                                                                                             start_y + iDiamondSize, 1 + 8);
824                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
825                                                                                             start_y - iDiamondSize, 2 + 4);
826                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
827                                                                                             start_y + iDiamondSize, 2 + 8);
828                                            break;
829                                    }
830                                    if (!iDirection)
831                                            break;          //ok, the end. really
832                                    else {
833                                            bDirection = iDirection;
834                                            start_x = currMV->x;
835                                            start_y = currMV->y;
836                                    }
837                            }
838                    }
839                    while (1);                              //forever
840            }
841    
842            return iMinSAD;
843    }
844    
845    int32_t
846    AdvDiamond8_MainSearch(const uint8_t * const pRef,
847                                               const uint8_t * const pRefH,
848                                               const uint8_t * const pRefV,
849                                               const uint8_t * const pRefHV,
850                                               const uint8_t * const cur,
851                                               const int x,
852                                               const int y,
853                                               const int start_xi,
854                                               const int start_yi,
855                                               int iMinSAD,
856                                               VECTOR * const currMV,
857                                               const int center_x,
858                                               const int center_y,
859                                               const int32_t min_dx,
860                                               const int32_t max_dx,
861                                               const int32_t min_dy,
862                                               const int32_t max_dy,
863                                               const int32_t iEdgedWidth,
864                                               const int32_t iDiamondSize,
865                                               const int32_t iFcode,
866                                               const int32_t iQuant,
867                                               int iDirection)
868    {
869    
870            int32_t iSAD;
871            int start_x = start_xi, start_y = start_yi;
872    
873    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
874    
875            if (iDirection) {
876                    CHECK_MV8_CANDIDATE(start_x - iDiamondSize, start_y);
877                    CHECK_MV8_CANDIDATE(start_x + iDiamondSize, start_y);
878                    CHECK_MV8_CANDIDATE(start_x, start_y - iDiamondSize);
879                    CHECK_MV8_CANDIDATE(start_x, start_y + iDiamondSize);
880            } else {
881                    int bDirection = 1 + 2 + 4 + 8;
882    
883                    do {
884                            iDirection = 0;
885                            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)
886                                    CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
887    
888                            if (bDirection & 2)
889                                    CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
890    
891                            if (bDirection & 4)
892                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
893    
894                            if (bDirection & 8)
895                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
896    
897                            /* now we're doing diagonal checks near our candidate */
898    
899                            if (iDirection)         //checking if anything found
900                            {
901                                    bDirection = iDirection;
902                                    iDirection = 0;
903                                    start_x = currMV->x;
904                                    start_y = currMV->y;
905                                    if (bDirection & 3)     //our candidate is left or right
906                                    {
907                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
908                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
909                                    } else                  // what remains here is up or down
910                                    {
911                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
912                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
913                                    }
914    
915                                    if (iDirection) {
916                                            bDirection += iDirection;
917                                            start_x = currMV->x;
918                                            start_y = currMV->y;
919                                    }
920                            } else                          //about to quit, eh? not so fast....
921                            {
922                                    switch (bDirection) {
923                                    case 2:
924                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
925                                                                                            start_y - iDiamondSize, 2 + 4);
926                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
927                                                                                            start_y + iDiamondSize, 2 + 8);
928                                            break;
929                                    case 1:
930                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
931                                                                                            start_y - iDiamondSize, 1 + 4);
932                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
933                                                                                            start_y + iDiamondSize, 1 + 8);
934                                            break;
935                                    case 2 + 4:
936                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
937                                                                                            start_y - iDiamondSize, 1 + 4);
938                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
939                                                                                            start_y - iDiamondSize, 2 + 4);
940                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
941                                                                                            start_y + iDiamondSize, 2 + 8);
942                                            break;
943                                    case 4:
944                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
945                                                                                            start_y - iDiamondSize, 2 + 4);
946                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
947                                                                                            start_y - iDiamondSize, 1 + 4);
948                                            break;
949                                    case 8:
950                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
951                                                                                            start_y + iDiamondSize, 2 + 8);
952                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
953                                                                                            start_y + iDiamondSize, 1 + 8);
954                                            break;
955                                    case 1 + 4:
956                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
957                                                                                            start_y + iDiamondSize, 1 + 8);
958                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
959                                                                                            start_y - iDiamondSize, 1 + 4);
960                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
961                                                                                            start_y - iDiamondSize, 2 + 4);
962                                            break;
963                                    case 2 + 8:
964                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
965                                                                                            start_y - iDiamondSize, 1 + 4);
966                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
967                                                                                            start_y + iDiamondSize, 1 + 8);
968                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
969                                                                                            start_y + iDiamondSize, 2 + 8);
970                                            break;
971                                    case 1 + 8:
972                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
973                                                                                            start_y - iDiamondSize, 2 + 4);
974                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
975                                                                                            start_y + iDiamondSize, 2 + 8);
976                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
977                                                                                            start_y + iDiamondSize, 1 + 8);
978                                            break;
979                                    default:                //1+2+4+8 == we didn't find anything at all
980                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
981                                                                                            start_y - iDiamondSize, 1 + 4);
982                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
983                                                                                            start_y + iDiamondSize, 1 + 8);
984                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
985                                                                                            start_y - iDiamondSize, 2 + 4);
986                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
987                                                                                            start_y + iDiamondSize, 2 + 8);
988                                            break;
989                                    }
990                                    if (!(iDirection))
991                                            break;          //ok, the end. really
992                                    else {
993                                            bDirection = iDirection;
994                                            start_x = currMV->x;
995                                            start_y = currMV->y;
996                                    }
997                            }
998                    }
999                    while (1);                              //forever
1000            }
1001            return iMinSAD;
1002    }
1003    
1004    
1005    int32_t
1006    Full8_MainSearch(const uint8_t * const pRef,
1007                                     const uint8_t * const pRefH,
1008                                     const uint8_t * const pRefV,
1009                                     const uint8_t * const pRefHV,
1010                                     const uint8_t * const cur,
1011                                     const int x,
1012                                     const int y,
1013                               const int start_x,
1014                               const int start_y,
1015                               int iMinSAD,
1016                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1017                                          const VECTOR * const pmv,                             const int center_x,
1018                                          const int32_t min_dx, const int32_t max_dx,                             const int center_y,
1019                                          const int32_t min_dy, const int32_t max_dy,                                   const int32_t min_dx,
1020                                     const int32_t max_dx,
1021                                     const int32_t min_dy,
1022                                     const int32_t max_dy,
1023                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
1024                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
1025                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 807  Line 1029 
1029          int32_t iSAD;          int32_t iSAD;
1030          int32_t dx,dy;          int32_t dx,dy;
1031          VECTOR backupMV;          VECTOR backupMV;
1032          backupMV.x = startx;  
1033          backupMV.y = starty;          backupMV.x = start_x;
1034            backupMV.y = start_y;
1035    
1036          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
1037                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
# Line 817  Line 1040 
1040          return iMinSAD;          return iMinSAD;
1041  }  }
1042    
1043    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1044    
1045    int32_t
1046  int32_t Halfpel16_Refine(  Halfpel16_Refine(const uint8_t * const pRef,
         const uint8_t * const pRef,  
1047          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1048          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1049          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1050          const uint8_t * const cur,          const uint8_t * const cur,
1051          const int x, const int y,                                   const int x,
1052                                     const int y,
1053          VECTOR * const currMV,          VECTOR * const currMV,
1054          int32_t iMinSAD,          int32_t iMinSAD,
1055          const VECTOR * const pmv,                             const int center_x,
1056          const int32_t min_dx, const int32_t max_dx,                             const int center_y,
1057          const int32_t min_dy, const int32_t max_dy,                                   const int32_t min_dx,
1058                                     const int32_t max_dx,
1059                                     const int32_t min_dy,
1060                                     const int32_t max_dy,
1061          const int32_t iFcode,          const int32_t iFcode,
1062          const int32_t iQuant,          const int32_t iQuant,
1063          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 855  Line 1082 
1082  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1083    
1084    
1085  int32_t PMVfastSearch16(  
1086                                          const uint8_t * const pRef,  int32_t
1087    PMVfastSearch16(const uint8_t * const pRef,
1088                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1089                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1090                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1091                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1092                                          const int x, const int y,                                  const int x,
1093                                    const int y,
1094                                    const int start_x,      /* start is searched first, so it should contain the most */
1095                                    const int start_y,  /* likely motion vector for this block */
1096                                    const int center_x,     /* center is from where length of MVs is measured */
1097                                    const int center_y,
1098                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1099                                    const uint32_t iQuant,
1100                                    const uint32_t iFcode,
1101                                          const MBParam * const pParam,                                          const MBParam * const pParam,
1102                                          MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1103                                    const MACROBLOCK * const prevMBs,
1104                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1105                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
1106  {  {
1107          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;  
1108          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1109          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
1110          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 892  Line 1126 
1126          VECTOR pmv[4];          VECTOR pmv[4];
1127          int32_t psad[4];          int32_t psad[4];
1128    
1129          MACROBLOCK * const pMB = pMBs + x + y * iWcount;          MainSearch16FuncPtr MainSearchPtr;
1130    
1131          static int32_t threshA,threshB;          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
1132    
1133            int32_t threshA, threshB;
1134          int32_t bPredEq;          int32_t bPredEq;
1135          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1136    
1137  /* Get maximum range */  /* Get maximum range */
1138          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,
1139                    x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
1140    
1141  /* 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 */
1142    
1143          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
1144          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1145          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1146          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1147          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1148          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
   
1149    
1150          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1151            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1152    
1153          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1154                  threshA =  512;                  threshA =  512;
1155                  threshB = 1024;                  threshB = 1024;
1156            } else {
         }  
         else  
         {  
1157                  threshA = psad[0];                  threshA = psad[0];
1158                  threshB = threshA+256;                  threshB = threshA+256;
1159                  if (threshA< 512) threshA =  512;                  if (threshA < 512)
1160                  if (threshA>1024) threshA = 1024;                          threshA = 512;
1161                  if (threshB>1792) threshB = 1792;                  if (threshA > 1024)
1162                            threshA = 1024;
1163                    if (threshB > 1792)
1164                            threshB = 1792;
1165          }          }
1166    
1167          iFound=0;          iFound=0;
1168    
 /* 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;  
   
1169  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1170     MinSAD=SAD     MinSAD=SAD
1171     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 958  Line 1173 
1173     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
1174  */  */
1175    
1176            currMV->x = start_x;
1177            currMV->y = start_y;
1178    
1179  // 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! */  
1180                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1181                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
1182          }          }
1183    
1184          if (currMV->x > max_dx)          if (currMV->x > max_dx) {
         {  
1185                  currMV->x=max_dx;                  currMV->x=max_dx;
1186          }          }
1187          if (currMV->x < min_dx)          if (currMV->x < min_dx) {
         {  
1188                  currMV->x=min_dx;                  currMV->x=min_dx;
1189          }          }
1190          if (currMV->y > max_dy)          if (currMV->y > max_dy) {
         {  
1191                  currMV->y=max_dy;                  currMV->y=max_dy;
1192          }          }
1193          if (currMV->y < min_dy)          if (currMV->y < min_dy) {
         {  
1194                  currMV->y=min_dy;                  currMV->y=min_dy;
1195          }          }
1196    
1197          iMinSAD = sad16( cur,          iMinSAD =
1198                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1199                           iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1200          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1201            iMinSAD +=
1202          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
1203          {                                            (uint8_t) iFcode, iQuant);
1204    
1205            if ((iMinSAD < 256) ||
1206                    ((MVequal(*currMV, prevMB->mvs[0])) &&
1207                     ((int32_t) iMinSAD < prevMB->sad16))) {
1208                    if (iMinSAD < (int)(2 * iQuant))        // high chances for SKIP-mode
1209                    {
1210                            if (!MVzero(*currMV)) {
1211                                    iMinSAD += MV16_00_BIAS;
1212                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
1213                                    iMinSAD -= MV16_00_BIAS;
1214                            }
1215                    }
1216    
1217                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1218                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
# Line 999  Line 1220 
1220                          goto PMVfast16_Terminate_with_Refine;                          goto PMVfast16_Terminate_with_Refine;
1221          }          }
1222    
1223    
1224    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1225       vector of the median.
1226       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1227    */
1228    
1229            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[0])))
1230                    iFound = 2;
1231    
1232    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1233       Otherwise select large Diamond Search.
1234    */
1235    
1236            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
1237                    iDiamondSize = 1;               // halfpel!
1238            else
1239                    iDiamondSize = 2;               // halfpel!
1240    
1241            if (!(MotionFlags & PMV_HALFPELDIAMOND16))
1242                    iDiamondSize *= 2;
1243    
1244  /*  /*
1245     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.
1246     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1247     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1248     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1249  */  */
1250    
1251  // (0,0) is always possible  // (0,0) is always possible
1252    
1253            if (!MVzero(pmv[0]))
1254          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1255    
1256  // previous frame MV is always possible  // previous frame MV is always possible
1257          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);  
1258            if (!MVzero(prevMB->mvs[0]))
1259                    if (!MVequal(prevMB->mvs[0], pmv[0]))
1260                            CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
1261    
1262  // left neighbour, if allowed  // left neighbour, if allowed
1263          if (x != 0)  
1264          {          if (!MVzero(pmv[1]))
1265                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!MVequal(pmv[1], prevMB->mvs[0]))
1266                  {       pmv[1].x = EVEN(pmv[1].x);                          if (!MVequal(pmv[1], pmv[0])) {
1267                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1268                                            pmv[1].x = EVEN(pmv[1].x);
1269                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1270                  }                  }
1271    
1272                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1273          }          }
   
1274  // top neighbour, if allowed  // top neighbour, if allowed
1275          if (y != 0)          if (!MVzero(pmv[2]))
1276          {                  if (!MVequal(pmv[2], prevMB->mvs[0]))
1277                  if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!MVequal(pmv[2], pmv[0]))
1278                  {       pmv[2].x = EVEN(pmv[2].x);                                  if (!MVequal(pmv[2], pmv[1])) {
1279                                            if (!(MotionFlags & PMV_HALFPEL16)) {
1280                                                    pmv[2].x = EVEN(pmv[2].x);
1281                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
1282                  }                  }
1283                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1284    
1285  // top right neighbour, if allowed  // top right neighbour, if allowed
1286                  if (x != (iWcount-1))                                          if (!MVzero(pmv[3]))
1287                  {                                                  if (!MVequal(pmv[3], prevMB->mvs[0]))
1288                          if (!(MotionFlags & PMV_HALFPEL16 ))                                                          if (!MVequal(pmv[3], pmv[0]))
1289                          {       pmv[3].x = EVEN(pmv[3].x);                                                                  if (!MVequal(pmv[3], pmv[1]))
1290                                                                            if (!MVequal(pmv[3], pmv[2])) {
1291                                                                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1292                                                                                            pmv[3].x = EVEN(pmv[3].x);
1293                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1294                          }                          }
1295                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                  CHECK_MV16_CANDIDATE(pmv[3].x,
1296                                                                                                                             pmv[3].y);
1297                  }                  }
1298          }          }
1299    
1300            if ((MVzero(*currMV)) &&
1301                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1302                    iMinSAD -= MV16_00_BIAS;
1303    
1304    
1305  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1306     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.
1307  */  */
1308    
1309          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )          if ((iMinSAD <= threshA) ||
1310          {                  (MVequal(*currMV, prevMB->mvs[0]) &&
1311                     ((int32_t) iMinSAD < prevMB->sad16))) {
1312                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1313                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
1314                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1066  Line 1326 
1326     Refine by using small diamond and goto step 10.     Refine by using small diamond and goto step 10.
1327  */  */
1328    
1329            if (MotionFlags & PMV_USESQUARES16)
1330                    MainSearchPtr = Square16_MainSearch;
1331            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
1332                    MainSearchPtr = AdvDiamond16_MainSearch;
1333            else
1334                    MainSearchPtr = Diamond16_MainSearch;
1335    
1336          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1337    
1338    
1339  /* 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 */
1340          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1341                                            x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1342                                            currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->x, currMV->y, iMinSAD, &newMV, center_x, center_y,
1343                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dx, max_dx,
1344                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1345                                                      iQuant, iFound);
1346    
1347          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1348                  *currMV = newMV;                  *currMV = newMV;
1349                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1350          }          }
1351    
1352          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
1353  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1354    
1355                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1356                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1357                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1358                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    center_x, center_y, iMinSAD, &newMV, center_x, center_y,
1359                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1360                                                                      iDiamondSize, iFcode, iQuant, iFound);
1361    
1362                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1363                          *currMV = newMV;                          *currMV = newMV;
1364                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1365                  }                  }
1366                  }                  }
1367    
1368                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1369                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1370                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1371                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y,
1372                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy,
1373                                                                      iEdgedWidth, iDiamondSize, iFcode,
1374                                                                      iQuant, iFound);
1375    
1376                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1377                          *currMV = newMV;                          *currMV = newMV;
1378                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1379                  }                  }
# Line 1117  Line 1386 
1386    
1387  PMVfast16_Terminate_with_Refine:  PMVfast16_Terminate_with_Refine:
1388          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1389                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1390                                    x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1391                                    currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1392                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1393    
1394  PMVfast16_Terminate_without_Refine:  PMVfast16_Terminate_without_Refine:
1395          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
1396          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
1397          return iMinSAD;          return iMinSAD;
1398  }  }
1399    
# Line 1133  Line 1402 
1402    
1403    
1404    
1405  int32_t Diamond8_MainSearch(  int32_t
1406          const uint8_t * const pRef,  Diamond8_MainSearch(const uint8_t * const pRef,
1407          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1408          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1409          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1410          const uint8_t * const cur,          const uint8_t * const cur,
1411          const int x, const int y,                                          const int x,
1412          int32_t startx, int32_t starty,                                          const int y,
1413                                            const int32_t start_x,
1414                                            const int32_t start_y,
1415          int32_t iMinSAD,          int32_t iMinSAD,
1416          VECTOR * const currMV,          VECTOR * const currMV,
1417          const VECTOR * const pmv,                                          const int center_x,
1418          const int32_t min_dx, const int32_t max_dx,                                          const int center_y,
1419          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
1420                                            const int32_t max_dx,
1421                                            const int32_t min_dy,
1422                                            const int32_t max_dy,
1423          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
1424          const int32_t iDiamondSize,          const int32_t iDiamondSize,
1425          const int32_t iFcode,          const int32_t iFcode,
# Line 1155  Line 1429 
1429  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
1430    
1431          int32_t iDirection=0;          int32_t iDirection=0;
1432            int32_t iDirectionBackup;
1433          int32_t iSAD;          int32_t iSAD;
1434          VECTOR backupMV;          VECTOR backupMV;
1435          backupMV.x = startx;  
1436          backupMV.y = starty;          backupMV.x = start_x;
1437            backupMV.y = start_y;
1438    
1439  /* 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 */
1440    
# Line 1167  Line 1443 
1443          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
1444          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1445    
1446          if (iDirection)          if (iDirection) {
1447                  while (!iFound)                  while (!iFound) {
                 {  
1448                          iFound = 1;                          iFound = 1;
1449                          backupMV=*currMV;       // since iDirection!=0, this is well defined!                          backupMV=*currMV;       // since iDirection!=0, this is well defined!
1450                            iDirectionBackup = iDirection;
1451    
1452                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
1453                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1454                          if ( iDirection != 1)                                                                                    backupMV.y, 1);
1455                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
1456                          if ( iDirection != 4)                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1457                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                    backupMV.y, 2);
1458                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
1459                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1460                                                                                      backupMV.y - iDiamondSize, 3);
1461                            if (iDirectionBackup != 3)
1462                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1463                                                                                      backupMV.y + iDiamondSize, 4);
1464                  }                  }
1465          else          } else {
1466                    currMV->x = start_x;
1467                    currMV->y = start_y;
1468            }
1469            return iMinSAD;
1470    }
1471    
1472    
1473    
1474    
1475    int32_t
1476    Square8_MainSearch(const uint8_t * const pRef,
1477                                       const uint8_t * const pRefH,
1478                                       const uint8_t * const pRefV,
1479                                       const uint8_t * const pRefHV,
1480                                       const uint8_t * const cur,
1481                                       const int x,
1482                                       const int y,
1483                                       const int32_t start_x,
1484                                       const int32_t start_y,
1485                                       int32_t iMinSAD,
1486                                       VECTOR * const currMV,
1487                                       const int center_x,
1488                                       const int center_y,
1489                                       const int32_t min_dx,
1490                                       const int32_t max_dx,
1491                                       const int32_t min_dy,
1492                                       const int32_t max_dy,
1493                                       const int32_t iEdgedWidth,
1494                                       const int32_t iDiamondSize,
1495                                       const int32_t iFcode,
1496                                       const int32_t iQuant,
1497                                       int iFound)
1498          {          {
1499                  currMV->x = startx;  /* Do a square search around given starting point, return SAD of best */
1500                  currMV->y = starty;  
1501            int32_t iDirection = 0;
1502            int32_t iSAD;
1503            VECTOR backupMV;
1504    
1505            backupMV.x = start_x;
1506            backupMV.y = start_y;
1507    
1508    /* It's one search with full square pattern, and new parts for all following diamonds */
1509    
1510    /*   new direction are extra, so 1-4 is normal diamond
1511          537
1512          1*2
1513          648
1514    */
1515    
1516            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1517            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1518            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1519            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1520    
1521            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1522                                                             backupMV.y - iDiamondSize, 5);
1523            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1524                                                             backupMV.y + iDiamondSize, 6);
1525            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1526                                                             backupMV.y - iDiamondSize, 7);
1527            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1528                                                             backupMV.y + iDiamondSize, 8);
1529    
1530    
1531            if (iDirection) {
1532                    while (!iFound) {
1533                            iFound = 1;
1534                            backupMV = *currMV;
1535    
1536                            switch (iDirection) {
1537                            case 1:
1538                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1539                                                                                       backupMV.y, 1);
1540                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1541                                                                                     backupMV.y - iDiamondSize, 5);
1542                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1543                                                                                     backupMV.y - iDiamondSize, 7);
1544                                    break;
1545                            case 2:
1546                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1547                                                                                     2);
1548                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1549                                                                                     backupMV.y + iDiamondSize, 6);
1550                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1551                                                                                     backupMV.y + iDiamondSize, 8);
1552                                    break;
1553    
1554                            case 3:
1555                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1556                                                                                     4);
1557                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1558                                                                                     backupMV.y - iDiamondSize, 7);
1559                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1560                                                                                     backupMV.y + iDiamondSize, 8);
1561                                    break;
1562    
1563                            case 4:
1564                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1565                                                                                     3);
1566                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1567                                                                                     backupMV.y - iDiamondSize, 5);
1568                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1569                                                                                     backupMV.y + iDiamondSize, 6);
1570                                    break;
1571    
1572                            case 5:
1573                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1574                                                                                     1);
1575                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1576                                                                                     3);
1577                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1578                                                                                     backupMV.y - iDiamondSize, 5);
1579                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1580                                                                                     backupMV.y + iDiamondSize, 6);
1581                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1582                                                                                     backupMV.y - iDiamondSize, 7);
1583                                    break;
1584    
1585                            case 6:
1586                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1587                                                                                     2);
1588                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1589                                                                                     3);
1590    
1591                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1592                                                                                     backupMV.y - iDiamondSize, 5);
1593                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1594                                                                                     backupMV.y + iDiamondSize, 6);
1595                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1596                                                                                     backupMV.y + iDiamondSize, 8);
1597    
1598                                    break;
1599    
1600                            case 7:
1601                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1602                                                                                       backupMV.y, 1);
1603                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1604                                                                                     4);
1605                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1606                                                                                     backupMV.y - iDiamondSize, 5);
1607                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1608                                                                                     backupMV.y - iDiamondSize, 7);
1609                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1610                                                                                     backupMV.y + iDiamondSize, 8);
1611                                    break;
1612    
1613                            case 8:
1614                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1615                                                                                     2);
1616                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1617                                                                                     4);
1618                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1619                                                                                     backupMV.y + iDiamondSize, 6);
1620                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1621                                                                                     backupMV.y - iDiamondSize, 7);
1622                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1623                                                                                     backupMV.y + iDiamondSize, 8);
1624                                    break;
1625                            default:
1626                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1627                                                                                     1);
1628                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1629                                                                                     2);
1630                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1631                                                                                     3);
1632                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1633                                                                                     4);
1634    
1635                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1636                                                                                     backupMV.y - iDiamondSize, 5);
1637                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1638                                                                                     backupMV.y + iDiamondSize, 6);
1639                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1640                                                                                     backupMV.y - iDiamondSize, 7);
1641                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1642                                                                                     backupMV.y + iDiamondSize, 8);
1643                                    break;
1644                            }
1645                    }
1646            } else {
1647                    currMV->x = start_x;
1648                    currMV->y = start_y;
1649          }          }
1650          return iMinSAD;          return iMinSAD;
1651  }  }
1652    
1653  int32_t Halfpel8_Refine(  
1654          const uint8_t * const pRef,  
1655    
1656    
1657    int32_t
1658    Halfpel8_Refine_c(const uint8_t * const pRef,
1659          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1660          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1661          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1662          const uint8_t * const cur,          const uint8_t * const cur,
1663          const int x, const int y,                                    const int x,
1664                                      const int y,
1665          VECTOR * const currMV,          VECTOR * const currMV,
1666          int32_t iMinSAD,          int32_t iMinSAD,
1667          const VECTOR * const pmv,                                    const int center_x,
1668          const int32_t min_dx, const int32_t max_dx,                                    const int center_y,
1669          const int32_t min_dy, const int32_t max_dy,                                    const int32_t min_dx,
1670                                      const int32_t max_dx,
1671                                      const int32_t min_dy,
1672                                      const int32_t max_dy,
1673          const int32_t iFcode,          const int32_t iFcode,
1674          const int32_t iQuant,          const int32_t iQuant,
1675          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 1226  Line 1694 
1694    
1695  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1696    
1697  int32_t PMVfastSearch8(  int32_t
1698                                          const uint8_t * const pRef,  PMVfastSearch8(const uint8_t * const pRef,
1699                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1700                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1701                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1702                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1703                                          const int x, const int y,                             const int x,
1704                                          const int start_x, int start_y,                             const int y,
1705                               const int start_x,
1706                               const int start_y,
1707                                    const int center_x,
1708                                    const int center_y,
1709                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1710                               const uint32_t iQuant,
1711                               const uint32_t iFcode,
1712                                          const MBParam * const pParam,                                          const MBParam * const pParam,
1713                                          MACROBLOCK * const pMBs,                             const MACROBLOCK * const pMBs,
1714                               const MACROBLOCK * const prevMBs,
1715                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1716                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
1717  {  {
1718          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;  
1719          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1720          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
1721          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 1261  Line 1733 
1733          int32_t psad[4];          int32_t psad[4];
1734          VECTOR newMV;          VECTOR newMV;
1735          VECTOR backupMV;          VECTOR backupMV;
1736            VECTOR startMV;
1737    
1738          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1739            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
1740    
1741          static int32_t threshA,threshB;           int32_t threshA, threshB;
1742          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
1743          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1744    
1745          int32_t iSubBlock = ((y&1)<<1) + (x&1);          int32_t iSubBlock = (y & 1) + (y & 1) + (x & 1);
1746    
1747  /* Get maximum range */          MainSearch8FuncPtr MainSearchPtr;
         get_range(&min_dx, &max_dx, &min_dy, &max_dy,  
                   x, y, 8, iWidth, iHeight, iFcode);  
1748    
1749  /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */          /* Init variables */
1750            startMV.x = start_x;
1751            startMV.y = start_y;
1752    
1753          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          /* Get maximum range */
1754          { min_dx = EVEN(min_dx);          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
1755                              iFcode);
1756    
1757            if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
1758                    min_dx = EVEN(min_dx);
1759          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1760          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1761          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1762          }               /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          }
   
1763    
1764          bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
1765            bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
1766    
1767          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1768                  threshA =  512/4;                  threshA =  512/4;
1769                  threshB = 1024/4;                  threshB = 1024/4;
1770    
1771          }          } else {
1772          else                  threshA = psad[0] / 4;  /* good estimate? */
         {  
                 threshA = psad[0]/4;                    /* good estimate */  
1773                  threshB = threshA+256/4;                  threshB = threshA+256/4;
1774                  if (threshA< 512/4) threshA =  512/4;                  if (threshA < 512 / 4)
1775                  if (threshA>1024/4) threshA = 1024/4;                          threshA = 512 / 4;
1776                  if (threshB>1792/4) threshB = 1792/4;                  if (threshA > 1024 / 4)
1777                            threshA = 1024 / 4;
1778                    if (threshB > 1792 / 4)
1779                            threshB = 1792 / 4;
1780          }          }
1781    
1782          iFound=0;          iFound=0;
1783    
 /* 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;  
   
1784  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1785     MinSAD=SAD     MinSAD=SAD
1786     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 1333  Line 1791 
1791    
1792  // Prepare for main loop  // Prepare for main loop
1793    
1794          currMV->x=start_x;              /* start with mv16 */    if (MotionFlags & PMV_USESQUARES8)
1795          currMV->y=start_y;        MainSearchPtr = Square8_MainSearch;
1796      else
1797    
1798            if (MotionFlags & PMV_ADVANCEDDIAMOND8)
1799                    MainSearchPtr = AdvDiamond8_MainSearch;
1800            else
1801                    MainSearchPtr = Diamond8_MainSearch;
1802    
         iMinSAD = sad8( cur,  
                         get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),  
                         iEdgedWidth);  
         iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode) * iQuant;  
1803    
1804          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          *currMV = startMV;
1805          {  
1806            iMinSAD =
1807                    sad8(cur,
1808                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
1809                                                    iEdgedWidth), iEdgedWidth);
1810            iMinSAD +=
1811                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
1812                                             (uint8_t) iFcode, iQuant);
1813    
1814            if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))
1815                                                                    && ((int32_t) iMinSAD <
1816                                                                            prevMB->sad8[iSubBlock]))) {
1817                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1818                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
1819                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
1820                          goto PMVfast8_Terminate_with_Refine;                          goto PMVfast8_Terminate_with_Refine;
1821          }          }
1822    
1823    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1824       vector of the median.
1825       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1826    */
1827    
1828            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[iSubBlock])))
1829                    iFound = 2;
1830    
1831    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1832       Otherwise select large Diamond Search.
1833    */
1834    
1835            if ((!MVzero(pmv[0])) || (threshB < 1536 / 4) || (bPredEq))
1836                    iDiamondSize = 1;               // 1 halfpel!
1837            else
1838                    iDiamondSize = 2;               // 2 halfpel = 1 full pixel!
1839    
1840            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
1841                    iDiamondSize *= 2;
1842    
1843    
1844  /*  /*
1845     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.
1846     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1847     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1848     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1849  */  */
1850    
1851  // 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);  
1852    
1853  // (0,0) is always possible          if (!MVequal(pmv[0], startMV))
1854                    CHECK_MV8_CANDIDATE(center_x, center_y);
1855    
1856    // (0,0) if needed
1857            if (!MVzero(pmv[0]))
1858                    if (!MVzero(startMV))
1859          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
1860    
1861  // previous frame MV is always possible  // previous frame MV if needed
1862          CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);          if (!MVzero(prevMB->mvs[iSubBlock]))
1863                    if (!MVequal(prevMB->mvs[iSubBlock], startMV))
1864                            if (!MVequal(prevMB->mvs[iSubBlock], pmv[0]))
1865                                    CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,
1866                                                                            prevMB->mvs[iSubBlock].y);
1867    
1868            if ((iMinSAD <= threshA) ||
1869                    (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
1870                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
1871                    if (MotionFlags & PMV_QUICKSTOP16)
1872                            goto PMVfast8_Terminate_without_Refine;
1873                    if (MotionFlags & PMV_EARLYSTOP16)
1874                            goto PMVfast8_Terminate_with_Refine;
1875            }
1876    
1877  // left neighbour, if allowed  // left neighbour, if allowed and needed
1878          if (psad[1] != MV_MAX_ERROR)          if (!MVzero(pmv[1]))
1879          {                  if (!MVequal(pmv[1], startMV))
1880                  if (!(MotionFlags & PMV_HALFPEL8 ))                          if (!MVequal(pmv[1], prevMB->mvs[iSubBlock]))
1881                  {       pmv[1].x = EVEN(pmv[1].x);                                  if (!MVequal(pmv[1], pmv[0])) {
1882                                            if (!(MotionFlags & PMV_HALFPEL8)) {
1883                                                    pmv[1].x = EVEN(pmv[1].x);
1884                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1885                  }                  }
1886                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1887          }          }
1888    // top neighbour, if allowed and needed
1889  // top neighbour, if allowed          if (!MVzero(pmv[2]))
1890          if (psad[2] != MV_MAX_ERROR)                  if (!MVequal(pmv[2], startMV))
1891          {                          if (!MVequal(pmv[2], prevMB->mvs[iSubBlock]))
1892                  if (!(MotionFlags & PMV_HALFPEL8 ))                                  if (!MVequal(pmv[2], pmv[0]))
1893                  {       pmv[2].x = EVEN(pmv[2].x);                                          if (!MVequal(pmv[2], pmv[1])) {
1894                                                    if (!(MotionFlags & PMV_HALFPEL8)) {
1895                                                            pmv[2].x = EVEN(pmv[2].x);
1896                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
1897                  }                  }
1898                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1899    
1900  // top right neighbour, if allowed  // top right neighbour, if allowed and needed
1901                  if (psad[3] != MV_MAX_ERROR)                                                  if (!MVzero(pmv[3]))
1902                  {                                                          if (!MVequal(pmv[3], startMV))
1903                          if (!(MotionFlags & PMV_HALFPEL8 ))                                                                  if (!MVequal(pmv[3], prevMB->mvs[iSubBlock]))
1904                          {       pmv[3].x = EVEN(pmv[3].x);                                                                          if (!MVequal(pmv[3], pmv[0]))
1905                                                                                    if (!MVequal(pmv[3], pmv[1]))
1906                                                                                            if (!MVequal(pmv[3], pmv[2])) {
1907                                                                                                    if (!
1908                                                                                                            (MotionFlags &
1909                                                                                                             PMV_HALFPEL8)) {
1910                                                                                                            pmv[3].x = EVEN(pmv[3].x);
1911                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1912                          }                          }
1913                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                                  CHECK_MV8_CANDIDATE(pmv[3].x,
1914                                                                                                                                            pmv[3].y);
1915                  }                  }
1916          }          }
1917    
1918            if ((MVzero(*currMV)) &&
1919                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1920                    iMinSAD -= MV8_00_BIAS;
1921    
1922    
1923  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1924     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.
1925  */  */
1926    
1927          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
1928          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
1929                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
1930                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1931                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
1932                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1421  Line 1946 
1946          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1947    
1948  /* 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 */
1949          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1950                                           x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
1951                                           currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
1952                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1953                                                      iQuant, iFound);
1954    
1955          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1956                  *currMV = newMV;                  *currMV = newMV;
1957                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1958          }          }
1959    
1960          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
1961  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1962    
1963                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1964                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1965                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1966                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
1967                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1968                                                                      iDiamondSize, iFcode, iQuant, iFound);
1969    
1970                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1971                          *currMV = newMV;                          *currMV = newMV;
1972                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1973                  }                  }
1974                  }                  }
1975    
1976                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1977                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1978                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1979                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
1980                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
1981                                                                      iQuant, iFound);
1982    
1983                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1984                          *currMV = newMV;                          *currMV = newMV;
1985                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1986                  }                  }
# Line 1469  Line 1993 
1993    
1994  PMVfast8_Terminate_with_Refine:  PMVfast8_Terminate_with_Refine:
1995          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
1996                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1997                                                   x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1998                                                   currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1999                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2000    
2001    
2002  PMVfast8_Terminate_without_Refine:  PMVfast8_Terminate_without_Refine:
2003          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2004          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2005    
2006          return iMinSAD;          return iMinSAD;
2007  }  }
2008    
2009  int32_t EPZSSearch16(  int32_t
2010                                          const uint8_t * const pRef,  EPZSSearch16(const uint8_t * const pRef,
2011                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2012                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2013                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2014                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2015                                          const int x, const int y,                           const int x,
2016                             const int y,
2017                            const int start_x,
2018                            const int start_y,
2019                            const int center_x,
2020                            const int center_y,
2021                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2022                             const uint32_t iQuant,
2023                             const uint32_t iFcode,
2024                                          const MBParam * const pParam,                                          const MBParam * const pParam,
2025                                          MACROBLOCK * const pMBs,                           const MACROBLOCK * const pMBs,
2026                             const MACROBLOCK * const prevMBs,
2027                                          VECTOR * const currMV,                                          VECTOR * const currMV,
2028                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
2029  {  {
2030          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
2031          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;  
2032    
2033          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
2034          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
# Line 1518  Line 2048 
2048          int32_t psad[8];          int32_t psad[8];
2049    
2050          static MACROBLOCK * oldMBs = NULL;          static MACROBLOCK * oldMBs = NULL;
2051          MACROBLOCK * const pMB = pMBs + x + y * iWcount;  
2052    //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
2053            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2054          MACROBLOCK * oldMB = NULL;          MACROBLOCK * oldMB = NULL;
2055    
2056          static int32_t thresh2;           int32_t thresh2;
2057          int32_t bPredEq;          int32_t bPredEq;
2058          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2059    
2060          MainSearch16FuncPtr EPZSMainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
2061    
2062          if (oldMBs == NULL)          if (oldMBs == NULL) {
2063          {       oldMBs = (MACROBLOCK*) calloc(1,iWcount*iHcount*sizeof(MACROBLOCK));                  oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
2064                  fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));  //      fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
2065          }          }
2066          oldMB = oldMBs + x + y * iWcount;          oldMB = oldMBs + x + y * iWcount;
2067    
2068  /* Get maximum range */  /* Get maximum range */
2069          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,
2070                          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 */  
2071    
2072          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
2073          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2074            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2075            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2076            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2077          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2078            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2079          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2080    
2081  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2082          MinSAD=SAD          MinSAD=SAD
# Line 1557  Line 2087 
2087    
2088  // Prepare for main loop  // Prepare for main loop
2089    
2090          *currMV=pmv[0];         /* current best := median prediction */          currMV->x = start_x;
2091          if (!(MotionFlags & PMV_HALFPEL16))          currMV->y = start_y;
2092          {  
2093            if (!(MotionFlags & PMV_HALFPEL16)) {
2094                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2095                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2096          }          }
# Line 1575  Line 2106 
2106    
2107  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2108    
2109          iMinSAD = sad16( cur,          iMinSAD =
2110                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
2111                  iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2112          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2113            iMinSAD +=
2114                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2115                                              (uint8_t) iFcode, iQuant);
2116    
2117  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2118          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )          if ((iMinSAD < 256) ||
2119                  {                  ((MVequal(*currMV, prevMB->mvs[0])) &&
2120                     ((int32_t) iMinSAD < prevMB->sad16))) {
2121                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2122                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2123                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1592  Line 2127 
2127  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2128    
2129  // previous frame MV  // previous frame MV
2130          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
2131    
2132  // set threshhold based on Min of Prediction and SAD of collocated block  // set threshhold based on Min of Prediction and SAD of collocated block
2133  // 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
2134    
2135          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
2136                  thresh2 =  512;                  thresh2 =  512;
2137          }          } else {
         else  
         {  
2138  /* 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] */
2139    
2140                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
# Line 1614  Line 2146 
2146    
2147    
2148  // left neighbour, if allowed  // left neighbour, if allowed
2149          if (x != 0)          if (x != 0) {
2150          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2151                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2152                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2153                  }                  }
2154                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
2155          }          }
   
2156  // top neighbour, if allowed  // top neighbour, if allowed
2157          if (y != 0)          if (y != 0) {
2158          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2159                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2160                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2161                  }                  }
2162                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
2163    
2164  // top right neighbour, if allowed  // top right neighbour, if allowed
2165                  if (x != (iWcount-1))                  if ((uint32_t) x != (iWcount - 1)) {
2166                  {                          if (!(MotionFlags & PMV_HALFPEL16)) {
2167                          if (!(MotionFlags & PMV_HALFPEL16 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2168                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2169                          }                          }
2170                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
# Line 1648  Line 2176 
2176  */  */
2177    
2178          if ( (iMinSAD <= thresh2)          if ( (iMinSAD <= thresh2)
2179                  || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD <= pMB->sad16) ) )                  || (MVequal(*currMV, prevMB->mvs[0]) &&
2180                  {                          ((int32_t) iMinSAD <= prevMB->sad16))) {
2181                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2182                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2183                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1658  Line 2186 
2186    
2187  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
2188    
2189          backupMV = pMB->mvs[0];                 // last MV          backupMV = prevMB->mvs[0];      // collocated MV
2190          backupMV.x += (pMB->mvs[0].x - oldMB->mvs[0].x );       // acceleration X          backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x);     // acceleration X
2191          backupMV.y += (pMB->mvs[0].y - oldMB->mvs[0].y );       // acceleration Y          backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y);     // acceleration Y
2192    
2193          CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);          CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);
2194    
2195  // left neighbour  // left neighbour
2196          if (x != 0)          if (x != 0)
2197                  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);
2198    
2199  // top neighbour  // top neighbour
2200          if (y != 0)          if (y != 0)
2201                  CHECK_MV16_CANDIDATE((oldMB-iWcount)->mvs[0].x,oldMB->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,
2202                                                             (prevMB - iWcount)->mvs[0].y);
2203    
2204  // 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
2205    
2206          if (x != iWcount-1)          if ((uint32_t) x != iWcount - 1)
2207                  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);
2208    
2209  // bottom neighbour, dito  // bottom neighbour, dito
2210          if (y != iHcount-1)          if ((uint32_t) y != iHcount - 1)
2211                  CHECK_MV16_CANDIDATE((pMB+iWcount)->mvs[0].x,oldMB->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,
2212                                                             (prevMB + iWcount)->mvs[0].y);
2213    
2214  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
2215          if (iMinSAD <= thresh2)          if (iMinSAD <= thresh2) {
                 {  
2216                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2217                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2218                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1694  Line 2223 
2223    
2224          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2225    
 /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  
   
2226          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
2227                  EPZSMainSearchPtr = Square16_MainSearch;                  MainSearchPtr = Square16_MainSearch;
2228          else          else
2229                  EPZSMainSearchPtr = Diamond16_MainSearch;           if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2230                    MainSearchPtr = AdvDiamond16_MainSearch;
2231            else
2232                    MainSearchPtr = Diamond16_MainSearch;
2233    
2234          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);  
2235    
2236          if (iSAD < iMinSAD)          iSAD =
2237          {                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2238                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2239                                                      min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2240    
2241            if (iSAD < iMinSAD) {
2242                  *currMV = newMV;                  *currMV = newMV;
2243                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2244          }          }
2245    
2246    
2247          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
2248  /* 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) */
2249    
2250                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2251                  {                          iSAD =
2252                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2253                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2254                                  pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2255                                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    2, iFcode, iQuant, 0);
2256                  }                  }
2257    
2258                  if (iSAD < iMinSAD)                  if (iSAD < iMinSAD) {
                 {  
2259                          *currMV = newMV;                          *currMV = newMV;
2260                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2261                  }                  }
2262    
2263                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2264                  {                          iSAD =
2265                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2266                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2267                          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);  
2268    
2269                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2270                                  *currMV = newMV;                                  *currMV = newMV;
2271                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2272                          }                          }
# Line 1750  Line 2277 
2277    
2278  EPZS16_Terminate_with_Refine:  EPZS16_Terminate_with_Refine:
2279          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
2280                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2281                                  x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2282                                  currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2283                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
2284    
2285  EPZS16_Terminate_without_Refine:  EPZS16_Terminate_without_Refine:
2286    
2287          *oldMB = *pMB;          *oldMB = *prevMB;
2288    
2289          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2290          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2291          return iMinSAD;          return iMinSAD;
2292  }  }
2293    
2294    
2295  int32_t EPZSSearch8(  int32_t
2296                                          const uint8_t * const pRef,  EPZSSearch8(const uint8_t * const pRef,
2297                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2298                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2299                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2300                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2301                                          const int x, const int y,                          const int x,
2302                                          const int start_x, const int start_y,                          const int y,
2303                            const int start_x,
2304                            const int start_y,
2305                            const int center_x,
2306                            const int center_y,
2307                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2308                            const uint32_t iQuant,
2309                            const uint32_t iFcode,
2310                                          const MBParam * const pParam,                                          const MBParam * const pParam,
2311                                          MACROBLOCK * const pMBs,                          const MACROBLOCK * const pMBs,
2312                            const MACROBLOCK * const prevMBs,
2313                                          VECTOR * const currMV,                                          VECTOR * const currMV,
2314                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
2315  {  {
2316          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;  
2317    
2318            const uint32_t iWcount = pParam->mb_width;
2319          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
2320          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
2321          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 1804  Line 2337 
2337    
2338          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);
2339    
2340          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2341            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
2342    
2343          int32_t bPredEq;          int32_t bPredEq;
2344          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2345    
2346          MainSearch8FuncPtr EPZSMainSearchPtr;          MainSearch8FuncPtr MainSearchPtr;
2347    
2348  /* Get maximum range */  /* Get maximum range */
2349          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,
2350                          x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2351    
2352  /* 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 */
2353    
2354          if (!(MotionFlags & PMV_HALFPEL8 ))          if (!(MotionFlags & PMV_HALFPEL8)) {
2355          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2356            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2357            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2358            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2359          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2360            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2361          bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);          bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2362    
2363    
2364  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
# Line 1837  Line 2371 
2371  // Prepare for main loop  // Prepare for main loop
2372    
2373    
2374          if (!(MotionFlags & PMV_HALFPEL8))          if (!(MotionFlags & PMV_HALFPEL8)) {
         {  
2375                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2376                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2377          }          }
# Line 1855  Line 2388 
2388  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2389    
2390    
2391          iMinSAD = sad8( cur,          iMinSAD =
2392                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  sad8(cur,
2393                  iEdgedWidth);                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2394          iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                  iEdgedWidth), iEdgedWidth);
2395            iMinSAD +=
2396                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2397                                             (uint8_t) iFcode, iQuant);
2398    
2399    
2400  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2401          if (iMinSAD < 256/4 )          if (iMinSAD < 256 / 4) {
                 {  
2402                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2403                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2404                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
# Line 1872  Line 2407 
2407    
2408  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2409    
 // previous frame MV  
         CHECK_MV8_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);  
2410    
2411  // MV=(0,0) is often a good choice  // MV=(0,0) is often a good choice
   
2412          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
2413    
2414    // previous frame MV
2415            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x, prevMB->mvs[iSubBlock].y);
2416    
2417    // left neighbour, if allowed
2418            if (psad[1] != MV_MAX_ERROR) {
2419                    if (!(MotionFlags & PMV_HALFPEL8)) {
2420                            pmv[1].x = EVEN(pmv[1].x);
2421                            pmv[1].y = EVEN(pmv[1].y);
2422                    }
2423                    CHECK_MV8_CANDIDATE(pmv[1].x, pmv[1].y);
2424            }
2425    // top neighbour, if allowed
2426            if (psad[2] != MV_MAX_ERROR) {
2427                    if (!(MotionFlags & PMV_HALFPEL8)) {
2428                            pmv[2].x = EVEN(pmv[2].x);
2429                            pmv[2].y = EVEN(pmv[2].y);
2430                    }
2431                    CHECK_MV8_CANDIDATE(pmv[2].x, pmv[2].y);
2432    
2433    // top right neighbour, if allowed
2434                    if (psad[3] != MV_MAX_ERROR) {
2435                            if (!(MotionFlags & PMV_HALFPEL8)) {
2436                                    pmv[3].x = EVEN(pmv[3].x);
2437                                    pmv[3].y = EVEN(pmv[3].y);
2438                            }
2439                            CHECK_MV8_CANDIDATE(pmv[3].x, pmv[3].y);
2440                    }
2441            }
2442    
2443    /*  // this bias is zero anyway, at the moment!
2444    
2445            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
2446                    iMinSAD -= MV8_00_BIAS;
2447    
2448    */
2449    
2450  /* Terminate if MinSAD <= T_2  /* Terminate if MinSAD <= T_2
2451     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]
2452  */  */
2453    
2454          if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */          if (iMinSAD < 512 / 4) {        /* T_2 == 512/4 hardcoded */
                 {  
2455                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2456                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2457                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
2458                                  goto EPZS8_Terminate_with_Refine;                                  goto EPZS8_Terminate_with_Refine;
2459                  }                  }
2460    
2461  /************ (if Diamond Search)  **************/  /************ (Diamond Search)  **************/
2462    
2463          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2464    
2465          if (!(MotionFlags & PMV_HALFPELDIAMOND8))          if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2466                  iDiamondSize *= 2;                  iDiamondSize *= 2;
2467    
2468  /* 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 */
2469    
2470  //      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);  
2471    
2472      if (MotionFlags & PMV_USESQUARES8)
2473          MainSearchPtr = Square8_MainSearch;
2474      else
2475    
2476          if (iSAD < iMinSAD)          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2477          {                  MainSearchPtr = AdvDiamond8_MainSearch;
2478            else
2479                    MainSearchPtr = Diamond8_MainSearch;
2480    
2481            iSAD =
2482                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2483                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2484                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2485                                                      iQuant, 0);
2486    
2487    
2488            if (iSAD < iMinSAD) {
2489                  *currMV = newMV;                  *currMV = newMV;
2490                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2491          }          }
2492    
2493          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2494  /* 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) */
2495    
2496                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2497                  {                          iSAD =
2498                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2499                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2500                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2501                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, 0);
2502    
2503                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2504                                  *currMV = newMV;                                  *currMV = newMV;
2505                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2506                          }                          }
2507                  }                  }
2508    
2509                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2510                  {                          iSAD =
2511                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2512                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2513                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2514                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iQuant, 0);
2515    
2516                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2517                                  *currMV = newMV;                                  *currMV = newMV;
2518                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2519                          }                          }
# Line 1955  Line 2524 
2524    
2525  EPZS8_Terminate_with_Refine:  EPZS8_Terminate_with_Refine:
2526          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2527                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2528                                  x, y,                          Halfpel8_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  EPZS8_Terminate_without_Refine:  EPZS8_Terminate_without_Refine:
2533    
2534          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2535          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2536          return iMinSAD;          return iMinSAD;
2537  }  }
   

Legend:
Removed from v.96  
changed lines
  Added in v.605

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