[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 652, Sun Nov 17 00:35: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 file is part of XviD, a free MPEG-4 video encoder/decoder
10   *   *
11   **************************************************************************/   *  XviD is free software; you can redistribute it and/or modify it
12     *  under the terms of the GNU General Public License as published by
13     *  the Free Software Foundation; either version 2 of the License, or
14     *  (at your option) any later version.
15     *
16     *  This program is distributed in the hope that it will be useful,
17     *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18     *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19     *  GNU General Public License for more details.
20     *
21     *  You should have received a copy of the GNU General Public License
22     *  along with this program; if not, write to the Free Software
23     *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
24     *
25     *  Under section 8 of the GNU General Public License, the copyright
26     *  holders of XVID explicitly forbid distribution in the following
27     *  countries:
28     *
29     *    - Japan
30     *    - United States of America
31     *
32     *  Linking XviD statically or dynamically with other modules is making a
33     *  combined work based on XviD.  Thus, the terms and conditions of the
34     *  GNU General Public License cover the whole combination.
35     *
36     *  As a special exception, the copyright holders of XviD give you
37     *  permission to link XviD with independent modules that communicate with
38     *  XviD solely through the VFW1.1 and DShow interfaces, regardless of the
39     *  license terms of these independent modules, and to copy and distribute
40     *  the resulting combined work under terms of your choice, provided that
41     *  every copy of the combined work is accompanied by a complete copy of
42     *  the source code of XviD (the version of XviD used to produce the
43     *  combined work), being distributed under the terms of the GNU General
44     *  Public License plus this exception.  An independent module is a module
45     *  which is not derived from or based on XviD.
46     *
47     *  Note that people who make modified versions of XviD are not obligated
48     *  to grant this special exception for their modified versions; it is
49     *  their choice whether to do so.  The GNU General Public License gives
50     *  permission to release a modified version without this exception; this
51     *  exception also makes it possible to release a modified version which
52     *  carries forward this exception.
53     *
54     * $Id: motion_est.c,v 1.53 2002-11-17 00:32:06 edgomez Exp $
55     *
56     *************************************************************************/
57    
58  #include <assert.h>  #include <assert.h>
59  #include <stdio.h>  #include <stdio.h>
# Line 40  Line 64 
64  #include "../prediction/mbprediction.h"  #include "../prediction/mbprediction.h"
65  #include "../global.h"  #include "../global.h"
66  #include "../utils/timer.h"  #include "../utils/timer.h"
67    #include "motion.h"
68  #include "sad.h"  #include "sad.h"
69    
 // very large value  
 #define MV_MAX_ERROR    (4096 * 256)  
   
 // stop search if sdelta < THRESHOLD  
 #define MV16_THRESHOLD  192  
 #define MV8_THRESHOLD   56  
   
 /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */  
 /* nb  = vop pixels * 2^(bpp-8) */  
 #define MV16_00_BIAS    (128+1)  
   
 /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */  
 #define INTER_BIAS      512  
   
 /* Parameters which control inter/inter4v decision */  
 #define IMV16X16                        5  
   
 /* vector map (vlc delta size) smoother parameters */  
 #define NEIGH_TEND_16X16        2  
 #define NEIGH_TEND_8X8          2  
   
   
 // fast ((A)/2)*2  
 #define EVEN(A)         (((A)<0?(A)+1:(A)) & ~1)  
   
   
 #define MIN(X, Y) ((X)<(Y)?(X):(Y))  
 #define MAX(X, Y) ((X)>(Y)?(X):(Y))  
 #define ABS(X)    (((X)>0)?(X):-(X))  
 #define SIGN(X)   (((X)>0)?1:-1)  
   
 int32_t PMVfastSearch16(  
                                         const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const uint32_t MotionFlags,  
                                         const MBParam * const pParam,  
                                         MACROBLOCK * const pMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
 int32_t EPZSSearch16(  
                                         const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const uint32_t MotionFlags,  
                                         const MBParam * const pParam,  
                                         MACROBLOCK * const pMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
   
 int32_t PMVfastSearch8(  
                                         const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const int start_x, int start_y,  
                                         const uint32_t MotionFlags,  
                                         const MBParam * const pParam,  
                                         MACROBLOCK * const pMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
 int32_t EPZSSearch8(  
                                         const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const IMAGE * const pCur,  
                                         const int x, const int y,  
                                         const int start_x, int start_y,  
                                         const uint32_t MotionFlags,  
                                         const MBParam * const pParam,  
                                         MACROBLOCK * const pMBs,  
                                         VECTOR * const currMV,  
                                         VECTOR * const currPMV);  
   
70    
 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);  
71    
72  typedef MainSearch16Func* MainSearch16FuncPtr;  static int32_t lambda_vec16[32] =       /* rounded values for lambda param for weight of motion bits as in modified H.26L */
73    { 0, (int) (1.00235 + 0.5), (int) (1.15582 + 0.5), (int) (1.31976 + 0.5),
74                    (int) (1.49591 + 0.5), (int) (1.68601 + 0.5),
75            (int) (1.89187 + 0.5), (int) (2.11542 + 0.5), (int) (2.35878 + 0.5),
76                    (int) (2.62429 + 0.5), (int) (2.91455 + 0.5),
77            (int) (3.23253 + 0.5), (int) (3.58158 + 0.5), (int) (3.96555 + 0.5),
78                    (int) (4.38887 + 0.5), (int) (4.85673 + 0.5),
79            (int) (5.37519 + 0.5), (int) (5.95144 + 0.5), (int) (6.59408 + 0.5),
80                    (int) (7.31349 + 0.5), (int) (8.12242 + 0.5),
81            (int) (9.03669 + 0.5), (int) (10.0763 + 0.5), (int) (11.2669 + 0.5),
82                    (int) (12.6426 + 0.5), (int) (14.2493 + 0.5),
83            (int) (16.1512 + 0.5), (int) (18.442 + 0.5), (int) (21.2656 + 0.5),
84                    (int) (24.8580 + 0.5), (int) (29.6436 + 0.5),
85            (int) (36.4949 + 0.5)
86    };
87    
88    static int32_t *lambda_vec8 = lambda_vec16;     /* same table for INTER and INTER4V for now */
89    
 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);  
90    
 typedef MainSearch8Func* MainSearch8FuncPtr;  
91    
92  // mv.length table  // mv.length table
93  static const uint32_t mvtab[33] = {  static const uint32_t mvtab[33] = {
# Line 181  Line 98 
98  };  };
99    
100    
101  static __inline uint32_t mv_bits(int32_t component, const uint32_t iFcode)  static __inline uint32_t
102    mv_bits(int32_t component,
103                    const uint32_t iFcode)
104  {  {
105      if (component == 0)      if (component == 0)
106                  return 1;                  return 1;
# Line 189  Line 108 
108      if (component < 0)      if (component < 0)
109                  component = -component;                  component = -component;
110    
111      if (iFcode == 1)          if (iFcode == 1) {
     {  
112                  if (component > 32)                  if (component > 32)
113                      component = 32;                      component = 32;
114    
# Line 207  Line 125 
125  }  }
126    
127    
128  static __inline uint32_t calc_delta_16(const int32_t dx, const int32_t dy, const uint32_t iFcode)  static __inline uint32_t
129  {  calc_delta_16(const int32_t dx,
130          return NEIGH_TEND_16X16 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));                            const int32_t dy,
131  }                            const uint32_t iFcode,
132                              const uint32_t iQuant)
133  static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode)  {
134            return NEIGH_TEND_16X16 * lambda_vec16[iQuant] * (mv_bits(dx, iFcode) +
135  {                                                                                                            mv_bits(dy, iFcode));
136      return NEIGH_TEND_8X8 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));  }
137  }  
138    static __inline uint32_t
139    calc_delta_8(const int32_t dx,
140                             const int32_t dy,
141                             const uint32_t iFcode,
142  /* calculate the min/max range (in halfpixels)                           const uint32_t iQuant)
143          relative to the _MACROBLOCK_ position  {
144  */          return NEIGH_TEND_8X8 * lambda_vec8[iQuant] * (mv_bits(dx, iFcode) +
145                                                                                                       mv_bits(dy, iFcode));
146  static void __inline get_range(  }
147          int32_t * const min_dx, int32_t * const max_dx,  
148          int32_t * const min_dy, int32_t * const max_dy,  bool
149          const uint32_t x, const uint32_t y,  MotionEstimation(MBParam * const pParam,
150          const uint32_t block_sz,                                        // block dimension, 8 or 16                                   FRAMEINFO * const current,
151          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,  
152          const IMAGE * const pRefH,          const IMAGE * const pRefH,
153          const IMAGE * const pRefV,          const IMAGE * const pRefV,
154          const IMAGE * const pRefHV,          const IMAGE * const pRefHV,
         IMAGE * const pCurrent,  
155          const uint32_t iLimit)          const uint32_t iLimit)
   
156  {  {
157          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
158          const uint32_t iHcount = pParam->mb_height;          const uint32_t iHcount = pParam->mb_height;
159            MACROBLOCK *const pMBs = current->mbs;
160            MACROBLOCK *const prevMBs = reference->mbs;
161            const IMAGE *const pCurrent = &current->image;
162            const IMAGE *const pRef = &reference->image;
163    
164          uint32_t i, j, iIntra = 0;          static const VECTOR zeroMV = { 0, 0 };
165            VECTOR predMV;
166    
167          VECTOR mv16;          uint32_t x, y;
168          VECTOR pmv16;          uint32_t iIntra = 0;
169            VECTOR pmv;
170    
171          int32_t sad8 = 0;          if (sadInit)
172          int32_t sad16;                  (*sadInit) ();
         int32_t deviation;  
173    
174          // note: i==horizontal, j==vertical          for (y = 0; y < iHcount; y++)   {
175          for (i = 0; i < iHcount; i++)                  for (x = 0; x < iWcount; x ++)  {
                 for (j = 0; j < iWcount; j++)  
                 {  
                         MACROBLOCK *pMB = &pMBs[j + i * iWcount];  
176    
177                          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;  
178    
179                            predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
180    
181                          /* decide: MODE_INTER or MODE_INTRA                          pMB->sad16 =
182                             if (dev_intra < sad_inter - 2 * nb) use_intra                                  SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent,
183                          */                                                   x, y, predMV.x, predMV.y, predMV.x, predMV.y,
184                                                     current->motion_flags, current->quant,
185                                                     current->fcode, pParam, pMBs, prevMBs, &pMB->mv16,
186                                                     &pMB->pmvs[0]);
187    
188                            if (0 < (pMB->sad16 - MV16_INTER_BIAS)) {
189                                    int32_t deviation;
190    
191                          deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width);                                  deviation =
192                                            dev16(pCurrent->y + x * 16 + y * 16 * pParam->edged_width,
193                                                      pParam->edged_width);
194    
195                          if (deviation < (sad16 - INTER_BIAS))                                  if (deviation < (pMB->sad16 - MV16_INTER_BIAS)) {
                         {  
196                                  pMB->mode = MODE_INTRA;                                  pMB->mode = MODE_INTRA;
197                                  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] =
198                                  pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;                                                  pMB->mvs[3] = zeroMV;
199                                            pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
200                                                    pMB->sad8[3] = 0;
201    
202                                  iIntra++;                                  iIntra++;
203                                  if(iIntra >= iLimit)                                  if(iIntra >= iLimit)
# Line 370  Line 205 
205    
206                                  continue;                                  continue;
207                          }                          }
   
                         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];  
208                          }                          }
209    
210                            pmv = pMB->pmvs[0];
211                            if (current->global_flags & XVID_INTER4V)
212                                    if ((!(current->global_flags & XVID_LUMIMASKING) ||
213                                             pMB->dquant == NO_CHANGE)) {
214                                            int32_t sad8 = IMV16X16 * current->quant;
215    
216                                            if (sad8 < pMB->sad16) {
217                                                    sad8 += pMB->sad8[0] =
218                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
219                                                                            pCurrent, 2 * x, 2 * y,
220                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
221                                                                            current->motion_flags,
222                                                                            current->quant, current->fcode, pParam,
223                                                                            pMBs, prevMBs, &pMB->mvs[0],
224                                                                            &pMB->pmvs[0]);
225                                            }
226                                            if (sad8 < pMB->sad16) {
227    
228                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 1);
229                                                    sad8 += pMB->sad8[1] =
230                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
231                                                                            pCurrent, 2 * x + 1, 2 * y,
232                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
233                                                                            current->motion_flags,
234                                                                            current->quant, current->fcode, pParam,
235                                                                            pMBs, prevMBs, &pMB->mvs[1],
236                                                                            &pMB->pmvs[1]);
237                                            }
238                                            if (sad8 < pMB->sad16) {
239                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 2);
240                                                    sad8 += pMB->sad8[2] =
241                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
242                                                                            pCurrent, 2 * x, 2 * y + 1,
243                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
244                                                                            current->motion_flags,
245                                                                            current->quant, current->fcode, pParam,
246                                                                            pMBs, prevMBs, &pMB->mvs[2],
247                                                                            &pMB->pmvs[2]);
248                                            }
249                                            if (sad8 < pMB->sad16) {
250                                                    predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 3);
251                                                    sad8 += pMB->sad8[3] =
252                                                            SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y,
253                                                                            pCurrent, 2 * x + 1, 2 * y + 1,
254                                                                            pMB->mv16.x, pMB->mv16.y, predMV.x, predMV.y,
255                                                                            current->motion_flags,
256                                                                            current->quant, current->fcode, pParam,
257                                                                            pMBs, prevMBs,
258                                                                            &pMB->mvs[3],
259                                                                            &pMB->pmvs[3]);
260                                            }
261    
262                          /* decide: MODE_INTER or MODE_INTER4V                          /* decide: MODE_INTER or MODE_INTER4V
263                             mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v                                             mpeg4:   if (sad8 < pMB->sad16 - nb/2+1) use_inter4v
264                          */                          */
265    
266                          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  
267                                          pMB->mode = MODE_INTER4V;                                          pMB->mode = MODE_INTER4V;
268                                                    pMB->sad8[0] *= 4;
269                                                    pMB->sad8[1] *= 4;
270                                                    pMB->sad8[2] *= 4;
271                                                    pMB->sad8[3] *= 4;
272                                                    continue;
273                          }                          }
274                          else  
275                          {                                  }
276                                  sad8 = sad16;  
277                                  pMB->mode = MODE_INTER;                                  pMB->mode = MODE_INTER;
278                                  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 */
279                                  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;
280                                  pMB->pmvs[0].x = pmv16.x;                          pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] =
281                                  pMB->pmvs[0].y = pmv16.y;                                  pMB->sad16;
282                          }                          }
283                  }                  }
284    
285          return 0;          return 0;
286  }  }
287    
 #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )  
   
 #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )  
   
288    
289  #define CHECK_MV16_ZERO {\  #define CHECK_MV16_ZERO {\
290    if ( (0 <= max_dx) && (0 >= min_dx) \    if ( (0 <= max_dx) && (0 >= min_dx) \
291      && (0 <= max_dy) && (0 >= min_dy) ) \      && (0 <= max_dy) && (0 >= min_dy) ) \
292    { \    { \
293      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); \
294      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; \  
295      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
296      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \      {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }     \
297  }  }
298    
299  #define NOCHECK_MV16_CANDIDATE(X,Y) { \  #define NOCHECK_MV16_CANDIDATE(X,Y) { \
300      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
301      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
302      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
303      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
304  }  }
# Line 454  Line 308 
308      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
309    { \    { \
310      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
311      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
312      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
313      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
314  }  }
# Line 464  Line 318 
318      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
319    { \    { \
320      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
321      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
322      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
323      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
324  }  }
# Line 474  Line 328 
328      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
329    { \    { \
330      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \      iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); \
331      iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_16((X) - center_x, (Y) - center_y, (uint8_t)iFcode, iQuant);\
332      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
333      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
334  }  }
# Line 482  Line 336 
336    
337  #define CHECK_MV8_ZERO {\  #define CHECK_MV8_ZERO {\
338    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); \
339    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);\
340    if (iSAD < iMinSAD) \    if (iSAD < iMinSAD) \
341    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \    { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } \
342  }  }
# Line 490  Line 344 
344  #define NOCHECK_MV8_CANDIDATE(X,Y) \  #define NOCHECK_MV8_CANDIDATE(X,Y) \
345    { \    { \
346      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
347      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
348      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
349      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } \
350  }  }
# Line 500  Line 354 
354      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
355    { \    { \
356      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
357      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
358      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
359      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } \
360  }  }
# Line 510  Line 364 
364      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
365    { \    { \
366      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
367      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
368      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
369      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } \
370  }  }
# Line 520  Line 374 
374      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \      && ((Y) <= max_dy) && ((Y) >= min_dy) ) \
375    { \    { \
376      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \      iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); \
377      iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;\      iSAD += calc_delta_8((X)-center_x, (Y)-center_y, (uint8_t)iFcode, iQuant);\
378      if (iSAD < iMinSAD) \      if (iSAD < iMinSAD) \
379      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
380  }  }
381    
382    #if 0
383  /* too slow and not fully functional at the moment */  /* too slow and not fully functional at the moment */
 /*  
384  int32_t ZeroSearch16(  int32_t ZeroSearch16(
385                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
386                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
# Line 535  Line 389 
389                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
390                                          const int x, const int y,                                          const int x, const int y,
391                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
392                                            const uint32_t iQuant,
393                                            const uint32_t iFcode,
394                                          MBParam * const pParam,                                          MBParam * const pParam,
395                                          MACROBLOCK * const pMBs,                                          const MACROBLOCK * const pMBs,
396                                            const MACROBLOCK * const prevMBs,
397                                          VECTOR * const currMV,                                          VECTOR * const currMV,
398                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
399  {  {
400          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
         const int32_t iQuant = pParam->quant;  
401          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
402          int32_t iSAD;          int32_t iSAD;
403          int32_t pred_x,pred_y;          VECTOR pred;
404    
405    
406          get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);          pred = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
407    
408          iSAD = sad16( cur,          iSAD = sad16( cur,
409                  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 413 
413    
414          currMV->x = 0;          currMV->x = 0;
415          currMV->y = 0;          currMV->y = 0;
416          currPMV->x = -pred_x;          currPMV->x = -pred.x;
417          currPMV->y = -pred_y;          currPMV->y = -pred.y;
418    
419          return iSAD;          return iSAD;
420    
421  }  }
422  */  #endif /* 0 */
423    
424  int32_t Diamond16_MainSearch(  int32_t
425          const uint8_t * const pRef,  Diamond16_MainSearch(const uint8_t * const pRef,
426          const uint8_t * const pRefH,          const uint8_t * const pRefH,
427          const uint8_t * const pRefV,          const uint8_t * const pRefV,
428          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
429          const uint8_t * const cur,          const uint8_t * const cur,
430          const int x, const int y,                                           const int x,
431          int32_t startx, int32_t starty,                                           const int y,
432          int32_t iMinSAD,                                           const int start_x,
433                                             const int start_y,
434                                             int iMinSAD,
435          VECTOR * const currMV,          VECTOR * const currMV,
436          const VECTOR * const pmv,                                           const int center_x,
437          const int32_t min_dx, const int32_t max_dx,                                           const int center_y,
438          const int32_t min_dy, const int32_t max_dy,                                           const int32_t min_dx,
439                                             const int32_t max_dx,
440                                             const int32_t min_dy,
441                                             const int32_t max_dy,
442          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
443          const int32_t iDiamondSize,          const int32_t iDiamondSize,
444          const int32_t iFcode,          const int32_t iFcode,
# Line 586  Line 448 
448  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
449    
450          int32_t iDirection=0;          int32_t iDirection=0;
451            int32_t iDirectionBackup;
452          int32_t iSAD;          int32_t iSAD;
453          VECTOR backupMV;          VECTOR backupMV;
454          backupMV.x = startx;  
455          backupMV.y = starty;          backupMV.x = start_x;
456            backupMV.y = start_y;
457    
458  /* 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 */
459    
# Line 598  Line 462 
462          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
463          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
464    
465          if (iDirection)          if (iDirection) {
466                  while (!iFound)                  while (!iFound) {
                 {  
467                          iFound = 1;                          iFound = 1;
468                          backupMV=*currMV;                          backupMV=*currMV;
469                            iDirectionBackup = iDirection;
470    
471                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
472                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
473                          if ( iDirection != 1)                                                                                     backupMV.y, 1);
474                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
475                          if ( iDirection != 4)                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
476                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                     backupMV.y, 2);
477                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
478                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
479                                                                                       backupMV.y - iDiamondSize, 3);
480                            if (iDirectionBackup != 3)
481                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x,
482                                                                                       backupMV.y + iDiamondSize, 4);
483                  }                  }
484          else          } else {
485          {                  currMV->x = start_x;
486                  currMV->x = startx;                  currMV->y = start_y;
                 currMV->y = starty;  
487          }          }
488          return iMinSAD;          return iMinSAD;
489  }  }
490    
491  int32_t Square16_MainSearch(  int32_t
492                                          const uint8_t * const pRef,  Square16_MainSearch(const uint8_t * const pRef,
493                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
494                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
495                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
496                                          const uint8_t * const cur,                                          const uint8_t * const cur,
497                                          const int x, const int y,                                          const int x,
498                                          int32_t startx, int32_t starty,                                          const int y,
499                                          int32_t iMinSAD,                                          const int start_x,
500                                            const int start_y,
501                                            int iMinSAD,
502                                          VECTOR * const currMV,                                          VECTOR * const currMV,
503                                          const VECTOR * const pmv,                                          const int center_x,
504                                          const int32_t min_dx, const int32_t max_dx,                                          const int center_y,
505                                          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
506                                            const int32_t max_dx,
507                                            const int32_t min_dy,
508                                            const int32_t max_dy,
509                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
510                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
511                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 645  Line 517 
517          int32_t iDirection=0;          int32_t iDirection=0;
518          int32_t iSAD;          int32_t iSAD;
519          VECTOR backupMV;          VECTOR backupMV;
520          backupMV.x = startx;  
521          backupMV.y = starty;          backupMV.x = start_x;
522            backupMV.y = start_y;
523    
524  /* 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 */
525    
# Line 661  Line 534 
534          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
535          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
536    
537          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
538          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                           backupMV.y - iDiamondSize, 5);
539          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);          CHECK_MV16_CANDIDATE_DIR(backupMV.x - iDiamondSize,
540          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                                           backupMV.y + iDiamondSize, 6);
541            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
542                                                             backupMV.y - iDiamondSize, 7);
543            CHECK_MV16_CANDIDATE_DIR(backupMV.x + iDiamondSize,
544                                                             backupMV.y + iDiamondSize, 8);
545    
546    
547          if (iDirection)          if (iDirection) {
548                  while (!iFound)                  while (!iFound) {
                 {  
549                          iFound = 1;                          iFound = 1;
550                          backupMV=*currMV;                          backupMV=*currMV;
551    
552                          switch (iDirection)                          switch (iDirection) {
                         {  
553                                  case 1:                                  case 1:
554                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
555                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                     backupMV.y, 1);
556                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
557                                                                                     backupMV.y - iDiamondSize, 5);
558                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
559                                                                                     backupMV.y - iDiamondSize, 7);
560                                          break;                                          break;
561                                  case 2:                                  case 2:
562                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
563                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   2);
564                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
565                                                                                     backupMV.y + iDiamondSize, 6);
566                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
567                                                                                     backupMV.y + iDiamondSize, 8);
568                                          break;                                          break;
569    
570                                  case 3:                                  case 3:
571                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
572                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
573                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
574                                                                                     backupMV.y - iDiamondSize, 7);
575                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
576                                                                                     backupMV.y + iDiamondSize, 8);
577                                          break;                                          break;
578    
579                                  case 4:                                  case 4:
580                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  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);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
583                                                                                     backupMV.y - iDiamondSize, 5);
584                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
585                                                                                     backupMV.y + iDiamondSize, 6);
586                                          break;                                          break;
587    
588                                  case 5:                                  case 5:
589                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
590                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   1);
591                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
592                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                                                                   3);
593                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
594                                                                                     backupMV.y - iDiamondSize, 5);
595                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
596                                                                                     backupMV.y + iDiamondSize, 6);
597                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
598                                                                                     backupMV.y - iDiamondSize, 7);
599                                          break;                                          break;
600    
601                                  case 6:                                  case 6:
602                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
603                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                   2);
604                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
605                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
606                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);  
607                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
608                                                                                     backupMV.y - iDiamondSize, 5);
609                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
610                                                                                     backupMV.y + iDiamondSize, 6);
611                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
612                                                                                     backupMV.y + iDiamondSize, 8);
613    
614                                          break;                                          break;
615    
616                                  case 7:                                  case 7:
617                                          CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
618                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                     backupMV.y, 1);
619                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
620                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
621                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
622                                                                                     backupMV.y - iDiamondSize, 5);
623                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
624                                                                                     backupMV.y - iDiamondSize, 7);
625                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
626                                                                                     backupMV.y + iDiamondSize, 8);
627                                          break;                                          break;
628    
629                                  case 8:                                  case 8:
630                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
631                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
632                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
633                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
634                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
635                                                                                     backupMV.y + iDiamondSize, 6);
636                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
637                                                                                     backupMV.y - iDiamondSize, 7);
638                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
639                                                                                     backupMV.y + iDiamondSize, 8);
640                                          break;                                          break;
641                          default:                          default:
642                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
643                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);                                                                                   1);
644                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
645                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);                                                                                   2);
646                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
647                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);                                                                                   3);
648                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
649                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);                                                                                   4);
650                                          CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);  
651                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
652                                                                                     backupMV.y - iDiamondSize, 5);
653                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
654                                                                                     backupMV.y + iDiamondSize, 6);
655                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
656                                                                                     backupMV.y - iDiamondSize, 7);
657                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
658                                                                                     backupMV.y + iDiamondSize, 8);
659                                          break;                                          break;
660                          }                          }
661                  }                  }
662          else          } else {
663                  {                  currMV->x = start_x;
664                          currMV->x = startx;                  currMV->y = start_y;
                         currMV->y = starty;  
665                  }                  }
666          return iMinSAD;          return iMinSAD;
667  }  }
668    
669    
670  int32_t Full16_MainSearch(  int32_t
671                                          const uint8_t * const pRef,  Full16_MainSearch(const uint8_t * const pRef,
672                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
673                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
674                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
675                                          const uint8_t * const cur,                                          const uint8_t * const cur,
676                                          const int x, const int y,                                    const int x,
677                                          int32_t startx, int32_t starty,                                    const int y,
678                                          int32_t iMinSAD,                                    const int start_x,
679                                      const int start_y,
680                                      int iMinSAD,
681                                          VECTOR * const currMV,                                          VECTOR * const currMV,
682                                          const VECTOR * const pmv,                                    const int center_x,
683                                          const int32_t min_dx, const int32_t max_dx,                                    const int center_y,
684                                          const int32_t min_dy, const int32_t max_dy,                                    const int32_t min_dx,
685                                      const int32_t max_dx,
686                                      const int32_t min_dy,
687                                      const int32_t max_dy,
688                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
689                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
690                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 775  Line 694 
694          int32_t iSAD;          int32_t iSAD;
695          int32_t dx,dy;          int32_t dx,dy;
696          VECTOR backupMV;          VECTOR backupMV;
697          backupMV.x = startx;  
698          backupMV.y = starty;          backupMV.x = start_x;
699            backupMV.y = start_y;
700    
701          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
702                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
# Line 785  Line 705 
705          return iMinSAD;          return iMinSAD;
706  }  }
707    
708  int32_t Full8_MainSearch(  int32_t
709                                          const uint8_t * const pRef,  AdvDiamond16_MainSearch(const uint8_t * const pRef,
710                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
711                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
712                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
713                                          const uint8_t * const cur,                                          const uint8_t * const cur,
714                                          const int x, const int y,                                                  const int x,
715                                          int32_t startx, int32_t starty,                                                  const int y,
716                                          int32_t iMinSAD,                                                  const int start_xi,
717                                                    const int start_yi,
718                                                    int iMinSAD,
719                                                    VECTOR * const currMV,
720                                                    const int center_x,
721                                                    const int center_y,
722                                                    const int32_t min_dx,
723                                                    const int32_t max_dx,
724                                                    const int32_t min_dy,
725                                                    const int32_t max_dy,
726                                                    const int32_t iEdgedWidth,
727                                                    const int32_t iDiamondSize,
728                                                    const int32_t iFcode,
729                                                    const int32_t iQuant,
730                                                    int iDirection)
731    {
732    
733            int32_t iSAD;
734            int start_x = start_xi, start_y = start_yi;
735    
736    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
737    
738            if (iDirection) {
739                    CHECK_MV16_CANDIDATE(start_x - iDiamondSize, start_y);
740                    CHECK_MV16_CANDIDATE(start_x + iDiamondSize, start_y);
741                    CHECK_MV16_CANDIDATE(start_x, start_y - iDiamondSize);
742                    CHECK_MV16_CANDIDATE(start_x, start_y + iDiamondSize);
743            } else {
744                    int bDirection = 1 + 2 + 4 + 8;
745    
746                    do {
747                            iDirection = 0;
748                            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)
749                                    CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
750    
751                            if (bDirection & 2)
752                                    CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
753    
754                            if (bDirection & 4)
755                                    CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
756    
757                            if (bDirection & 8)
758                                    CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
759    
760                            /* now we're doing diagonal checks near our candidate */
761    
762                            if (iDirection)         //checking if anything found
763                            {
764                                    bDirection = iDirection;
765                                    iDirection = 0;
766                                    start_x = currMV->x;
767                                    start_y = currMV->y;
768                                    if (bDirection & 3)     //our candidate is left or right
769                                    {
770                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
771                                            CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
772                                    } else                  // what remains here is up or down
773                                    {
774                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
775                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
776                                    }
777    
778                                    if (iDirection) {
779                                            bDirection += iDirection;
780                                            start_x = currMV->x;
781                                            start_y = currMV->y;
782                                    }
783                            } else                          //about to quit, eh? not so fast....
784                            {
785                                    switch (bDirection) {
786                                    case 2:
787                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
788                                                                                             start_y - iDiamondSize, 2 + 4);
789                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
790                                                                                             start_y + iDiamondSize, 2 + 8);
791                                            break;
792                                    case 1:
793    
794                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
795                                                                                             start_y - iDiamondSize, 1 + 4);
796                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
797                                                                                             start_y + iDiamondSize, 1 + 8);
798                                            break;
799                                    case 2 + 4:
800                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
801                                                                                             start_y - iDiamondSize, 1 + 4);
802                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
803                                                                                             start_y - iDiamondSize, 2 + 4);
804                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
805                                                                                             start_y + iDiamondSize, 2 + 8);
806                                            break;
807                                    case 4:
808                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
809                                                                                             start_y - iDiamondSize, 2 + 4);
810                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
811                                                                                             start_y - iDiamondSize, 1 + 4);
812                                            break;
813                                    case 8:
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                                    case 1 + 4:
820                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
821                                                                                             start_y + iDiamondSize, 1 + 8);
822                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
823                                                                                             start_y - iDiamondSize, 1 + 4);
824                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
825                                                                                             start_y - iDiamondSize, 2 + 4);
826                                            break;
827                                    case 2 + 8:
828                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
829                                                                                             start_y - iDiamondSize, 1 + 4);
830                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
831                                                                                             start_y + iDiamondSize, 1 + 8);
832                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
833                                                                                             start_y + iDiamondSize, 2 + 8);
834                                            break;
835                                    case 1 + 8:
836                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
837                                                                                             start_y - iDiamondSize, 2 + 4);
838                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
839                                                                                             start_y + iDiamondSize, 2 + 8);
840                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
841                                                                                             start_y + iDiamondSize, 1 + 8);
842                                            break;
843                                    default:                //1+2+4+8 == we didn't find anything at all
844                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
845                                                                                             start_y - iDiamondSize, 1 + 4);
846                                            CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
847                                                                                             start_y + iDiamondSize, 1 + 8);
848                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
849                                                                                             start_y - iDiamondSize, 2 + 4);
850                                            CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize,
851                                                                                             start_y + iDiamondSize, 2 + 8);
852                                            break;
853                                    }
854                                    if (!iDirection)
855                                            break;          //ok, the end. really
856                                    else {
857                                            bDirection = iDirection;
858                                            start_x = currMV->x;
859                                            start_y = currMV->y;
860                                    }
861                            }
862                    }
863                    while (1);                              //forever
864            }
865    
866            return iMinSAD;
867    }
868    
869    int32_t
870    AdvDiamond8_MainSearch(const uint8_t * const pRef,
871                                               const uint8_t * const pRefH,
872                                               const uint8_t * const pRefV,
873                                               const uint8_t * const pRefHV,
874                                               const uint8_t * const cur,
875                                               const int x,
876                                               const int y,
877                                               const int start_xi,
878                                               const int start_yi,
879                                               int iMinSAD,
880                                          VECTOR * const currMV,                                          VECTOR * const currMV,
881                                          const VECTOR * const pmv,                                             const int center_x,
882                                          const int32_t min_dx, const int32_t max_dx,                                             const int center_y,
883                                          const int32_t min_dy, const int32_t max_dy,                                             const int32_t min_dx,
884                                               const int32_t max_dx,
885                                               const int32_t min_dy,
886                                               const int32_t max_dy,
887                                               const int32_t iEdgedWidth,
888                                               const int32_t iDiamondSize,
889                                               const int32_t iFcode,
890                                               const int32_t iQuant,
891                                               int iDirection)
892    {
893    
894            int32_t iSAD;
895            int start_x = start_xi, start_y = start_yi;
896    
897    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
898    
899            if (iDirection) {
900                    CHECK_MV8_CANDIDATE(start_x - iDiamondSize, start_y);
901                    CHECK_MV8_CANDIDATE(start_x + iDiamondSize, start_y);
902                    CHECK_MV8_CANDIDATE(start_x, start_y - iDiamondSize);
903                    CHECK_MV8_CANDIDATE(start_x, start_y + iDiamondSize);
904            } else {
905                    int bDirection = 1 + 2 + 4 + 8;
906    
907                    do {
908                            iDirection = 0;
909                            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)
910                                    CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
911    
912                            if (bDirection & 2)
913                                    CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
914    
915                            if (bDirection & 4)
916                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
917    
918                            if (bDirection & 8)
919                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
920    
921                            /* now we're doing diagonal checks near our candidate */
922    
923                            if (iDirection)         //checking if anything found
924                            {
925                                    bDirection = iDirection;
926                                    iDirection = 0;
927                                    start_x = currMV->x;
928                                    start_y = currMV->y;
929                                    if (bDirection & 3)     //our candidate is left or right
930                                    {
931                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
932                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
933                                    } else                  // what remains here is up or down
934                                    {
935                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
936                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
937                                    }
938    
939                                    if (iDirection) {
940                                            bDirection += iDirection;
941                                            start_x = currMV->x;
942                                            start_y = currMV->y;
943                                    }
944                            } else                          //about to quit, eh? not so fast....
945                            {
946                                    switch (bDirection) {
947                                    case 2:
948                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
949                                                                                            start_y - iDiamondSize, 2 + 4);
950                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
951                                                                                            start_y + iDiamondSize, 2 + 8);
952                                            break;
953                                    case 1:
954                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
955                                                                                            start_y - iDiamondSize, 1 + 4);
956                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
957                                                                                            start_y + iDiamondSize, 1 + 8);
958                                            break;
959                                    case 2 + 4:
960                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
961                                                                                            start_y - iDiamondSize, 1 + 4);
962                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
963                                                                                            start_y - iDiamondSize, 2 + 4);
964                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
965                                                                                            start_y + iDiamondSize, 2 + 8);
966                                            break;
967                                    case 4:
968                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
969                                                                                            start_y - iDiamondSize, 2 + 4);
970                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
971                                                                                            start_y - iDiamondSize, 1 + 4);
972                                            break;
973                                    case 8:
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                                    case 1 + 4:
980                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
981                                                                                            start_y + iDiamondSize, 1 + 8);
982                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
983                                                                                            start_y - iDiamondSize, 1 + 4);
984                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
985                                                                                            start_y - iDiamondSize, 2 + 4);
986                                            break;
987                                    case 2 + 8:
988                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
989                                                                                            start_y - iDiamondSize, 1 + 4);
990                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
991                                                                                            start_y + iDiamondSize, 1 + 8);
992                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
993                                                                                            start_y + iDiamondSize, 2 + 8);
994                                            break;
995                                    case 1 + 8:
996                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
997                                                                                            start_y - iDiamondSize, 2 + 4);
998                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
999                                                                                            start_y + iDiamondSize, 2 + 8);
1000                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1001                                                                                            start_y + iDiamondSize, 1 + 8);
1002                                            break;
1003                                    default:                //1+2+4+8 == we didn't find anything at all
1004                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1005                                                                                            start_y - iDiamondSize, 1 + 4);
1006                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1007                                                                                            start_y + iDiamondSize, 1 + 8);
1008                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1009                                                                                            start_y - iDiamondSize, 2 + 4);
1010                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1011                                                                                            start_y + iDiamondSize, 2 + 8);
1012                                            break;
1013                                    }
1014                                    if (!(iDirection))
1015                                            break;          //ok, the end. really
1016                                    else {
1017                                            bDirection = iDirection;
1018                                            start_x = currMV->x;
1019                                            start_y = currMV->y;
1020                                    }
1021                            }
1022                    }
1023                    while (1);                              //forever
1024            }
1025            return iMinSAD;
1026    }
1027    
1028    
1029    int32_t
1030    Full8_MainSearch(const uint8_t * const pRef,
1031                                     const uint8_t * const pRefH,
1032                                     const uint8_t * const pRefV,
1033                                     const uint8_t * const pRefHV,
1034                                     const uint8_t * const cur,
1035                                     const int x,
1036                                     const int y,
1037                               const int start_x,
1038                               const int start_y,
1039                               int iMinSAD,
1040                               VECTOR * const currMV,
1041                               const int center_x,
1042                               const int center_y,
1043                                     const int32_t min_dx,
1044                                     const int32_t max_dx,
1045                                     const int32_t min_dy,
1046                                     const int32_t max_dy,
1047                                          const int32_t iEdgedWidth,                                          const int32_t iEdgedWidth,
1048                                          const int32_t iDiamondSize,                                          const int32_t iDiamondSize,
1049                                          const int32_t iFcode,                                          const int32_t iFcode,
# Line 807  Line 1053 
1053          int32_t iSAD;          int32_t iSAD;
1054          int32_t dx,dy;          int32_t dx,dy;
1055          VECTOR backupMV;          VECTOR backupMV;
1056          backupMV.x = startx;  
1057          backupMV.y = starty;          backupMV.x = start_x;
1058            backupMV.y = start_y;
1059    
1060          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)          for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
1061                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)                  for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
# Line 817  Line 1064 
1064          return iMinSAD;          return iMinSAD;
1065  }  }
1066    
1067    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1068    
1069    int32_t
1070  int32_t Halfpel16_Refine(  Halfpel16_Refine(const uint8_t * const pRef,
         const uint8_t * const pRef,  
1071          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1072          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1073          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1074          const uint8_t * const cur,          const uint8_t * const cur,
1075          const int x, const int y,                                   const int x,
1076                                     const int y,
1077          VECTOR * const currMV,          VECTOR * const currMV,
1078          int32_t iMinSAD,          int32_t iMinSAD,
1079          const VECTOR * const pmv,                             const int center_x,
1080          const int32_t min_dx, const int32_t max_dx,                             const int center_y,
1081          const int32_t min_dy, const int32_t max_dy,                                   const int32_t min_dx,
1082                                     const int32_t max_dx,
1083                                     const int32_t min_dy,
1084                                     const int32_t max_dy,
1085          const int32_t iFcode,          const int32_t iFcode,
1086          const int32_t iQuant,          const int32_t iQuant,
1087          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 855  Line 1106 
1106  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1107    
1108    
1109  int32_t PMVfastSearch16(  
1110                                          const uint8_t * const pRef,  int32_t
1111    PMVfastSearch16(const uint8_t * const pRef,
1112                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1113                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1114                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1115                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1116                                          const int x, const int y,                                  const int x,
1117                                    const int y,
1118                                    const int start_x,      /* start is searched first, so it should contain the most */
1119                                    const int start_y,  /* likely motion vector for this block */
1120                                    const int center_x,     /* center is from where length of MVs is measured */
1121                                    const int center_y,
1122                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1123                                    const uint32_t iQuant,
1124                                    const uint32_t iFcode,
1125                                          const MBParam * const pParam,                                          const MBParam * const pParam,
1126                                          MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1127                                    const MACROBLOCK * const prevMBs,
1128                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1129                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
1130  {  {
1131          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;  
1132          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1133          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
1134          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 892  Line 1150 
1150          VECTOR pmv[4];          VECTOR pmv[4];
1151          int32_t psad[4];          int32_t psad[4];
1152    
1153          MACROBLOCK * const pMB = pMBs + x + y * iWcount;          MainSearch16FuncPtr MainSearchPtr;
1154    
1155            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
1156    
1157          static int32_t threshA,threshB;          int32_t threshA, threshB;
1158          int32_t bPredEq;          int32_t bPredEq;
1159          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1160    
1161  /* Get maximum range */  /* Get maximum range */
1162          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,
1163                    x, y, 16, iWidth, iHeight, iFcode);                            iFcode);
1164    
1165  /* 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 */
1166    
1167          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
1168          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
1169          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1170          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1171          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1172          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
   
1173    
1174          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1175            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1176    
1177          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1178                  threshA =  512;                  threshA =  512;
1179                  threshB = 1024;                  threshB = 1024;
1180            } else {
         }  
         else  
         {  
1181                  threshA = psad[0];                  threshA = psad[0];
1182                  threshB = threshA+256;                  threshB = threshA+256;
1183                  if (threshA< 512) threshA =  512;                  if (threshA < 512)
1184                  if (threshA>1024) threshA = 1024;                          threshA = 512;
1185                  if (threshB>1792) threshB = 1792;                  if (threshA > 1024)
1186                            threshA = 1024;
1187                    if (threshB > 1792)
1188                            threshB = 1792;
1189          }          }
1190    
1191          iFound=0;          iFound=0;
1192    
 /* 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;  
   
1193  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1194     MinSAD=SAD     MinSAD=SAD
1195     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 958  Line 1197 
1197     If SAD<=256 goto Step 10.     If SAD<=256 goto Step 10.
1198  */  */
1199    
1200            currMV->x = start_x;
1201            currMV->y = start_y;
1202    
1203  // 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! */  
1204                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
1205                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
1206          }          }
1207    
1208          if (currMV->x > max_dx)          if (currMV->x > max_dx) {
         {  
1209                  currMV->x=max_dx;                  currMV->x=max_dx;
1210          }          }
1211          if (currMV->x < min_dx)          if (currMV->x < min_dx) {
         {  
1212                  currMV->x=min_dx;                  currMV->x=min_dx;
1213          }          }
1214          if (currMV->y > max_dy)          if (currMV->y > max_dy) {
         {  
1215                  currMV->y=max_dy;                  currMV->y=max_dy;
1216          }          }
1217          if (currMV->y < min_dy)          if (currMV->y < min_dy) {
         {  
1218                  currMV->y=min_dy;                  currMV->y=min_dy;
1219          }          }
1220    
1221          iMinSAD = sad16( cur,          iMinSAD =
1222                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
1223                           iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1224          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1225            iMinSAD +=
1226          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
1227          {                                            (uint8_t) iFcode, iQuant);
1228    
1229            if ((iMinSAD < 256) ||
1230                    ((MVequal(*currMV, prevMB->mvs[0])) &&
1231                     ((int32_t) iMinSAD < prevMB->sad16))) {
1232                    if (iMinSAD < (int)(2 * iQuant))        // high chances for SKIP-mode
1233                    {
1234                            if (!MVzero(*currMV)) {
1235                                    iMinSAD += MV16_00_BIAS;
1236                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
1237                                    iMinSAD -= MV16_00_BIAS;
1238                            }
1239                    }
1240    
1241                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1242                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
# Line 999  Line 1244 
1244                          goto PMVfast16_Terminate_with_Refine;                          goto PMVfast16_Terminate_with_Refine;
1245          }          }
1246    
1247    
1248    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1249       vector of the median.
1250       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1251    */
1252    
1253            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[0])))
1254                    iFound = 2;
1255    
1256    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1257       Otherwise select large Diamond Search.
1258    */
1259    
1260            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
1261                    iDiamondSize = 1;               // halfpel!
1262            else
1263                    iDiamondSize = 2;               // halfpel!
1264    
1265            if (!(MotionFlags & PMV_HALFPELDIAMOND16))
1266                    iDiamondSize *= 2;
1267    
1268  /*  /*
1269     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.
1270     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1271     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1272     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1273  */  */
1274    
1275  // (0,0) is always possible  // (0,0) is always possible
1276    
1277            if (!MVzero(pmv[0]))
1278          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
1279    
1280  // previous frame MV is always possible  // previous frame MV is always possible
1281          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);  
1282            if (!MVzero(prevMB->mvs[0]))
1283                    if (!MVequal(prevMB->mvs[0], pmv[0]))
1284                            CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
1285    
1286  // left neighbour, if allowed  // left neighbour, if allowed
1287          if (x != 0)  
1288          {          if (!MVzero(pmv[1]))
1289                  if (!(MotionFlags & PMV_HALFPEL16 ))                  if (!MVequal(pmv[1], prevMB->mvs[0]))
1290                  {       pmv[1].x = EVEN(pmv[1].x);                          if (!MVequal(pmv[1], pmv[0])) {
1291                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1292                                            pmv[1].x = EVEN(pmv[1].x);
1293                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1294                  }                  }
1295    
1296                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
1297          }          }
   
1298  // top neighbour, if allowed  // top neighbour, if allowed
1299          if (y != 0)          if (!MVzero(pmv[2]))
1300          {                  if (!MVequal(pmv[2], prevMB->mvs[0]))
1301                  if (!(MotionFlags & PMV_HALFPEL16 ))                          if (!MVequal(pmv[2], pmv[0]))
1302                  {       pmv[2].x = EVEN(pmv[2].x);                                  if (!MVequal(pmv[2], pmv[1])) {
1303                                            if (!(MotionFlags & PMV_HALFPEL16)) {
1304                                                    pmv[2].x = EVEN(pmv[2].x);
1305                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
1306                  }                  }
1307                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
1308    
1309  // top right neighbour, if allowed  // top right neighbour, if allowed
1310                  if (x != (iWcount-1))                                          if (!MVzero(pmv[3]))
1311                  {                                                  if (!MVequal(pmv[3], prevMB->mvs[0]))
1312                          if (!(MotionFlags & PMV_HALFPEL16 ))                                                          if (!MVequal(pmv[3], pmv[0]))
1313                          {       pmv[3].x = EVEN(pmv[3].x);                                                                  if (!MVequal(pmv[3], pmv[1]))
1314                                                                            if (!MVequal(pmv[3], pmv[2])) {
1315                                                                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1316                                                                                            pmv[3].x = EVEN(pmv[3].x);
1317                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1318                          }                          }
1319                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                  CHECK_MV16_CANDIDATE(pmv[3].x,
1320                                                                                                                             pmv[3].y);
1321                  }                  }
1322          }          }
1323    
1324            if ((MVzero(*currMV)) &&
1325                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1326                    iMinSAD -= MV16_00_BIAS;
1327    
1328    
1329  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1330     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.
1331  */  */
1332    
1333          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )          if ((iMinSAD <= threshA) ||
1334          {                  (MVequal(*currMV, prevMB->mvs[0]) &&
1335                     ((int32_t) iMinSAD < prevMB->sad16))) {
1336                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1337                          goto PMVfast16_Terminate_without_Refine;                          goto PMVfast16_Terminate_without_Refine;
1338                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1066  Line 1350 
1350     Refine by using small diamond and goto step 10.     Refine by using small diamond and goto step 10.
1351  */  */
1352    
1353            if (MotionFlags & PMV_USESQUARES16)
1354                    MainSearchPtr = Square16_MainSearch;
1355            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
1356                    MainSearchPtr = AdvDiamond16_MainSearch;
1357            else
1358                    MainSearchPtr = Diamond16_MainSearch;
1359    
1360          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1361    
1362    
1363  /* 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 */
1364          iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1365                                            x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1366                                            currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->x, currMV->y, iMinSAD, &newMV, center_x, center_y,
1367                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dx, max_dx,
1368                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1369                                                      iQuant, iFound);
1370    
1371          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1372                  *currMV = newMV;                  *currMV = newMV;
1373                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1374          }          }
1375    
1376          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
1377  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1378    
1379                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1380                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1381                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1382                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    center_x, center_y, iMinSAD, &newMV, center_x, center_y,
1383                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1384                                                                      iDiamondSize, iFcode, iQuant, iFound);
1385    
1386                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1387                          *currMV = newMV;                          *currMV = newMV;
1388                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1389                  }                  }
1390                  }                  }
1391    
1392                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1393                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1394                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1395                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y,
1396                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy,
1397                                                                      iEdgedWidth, iDiamondSize, iFcode,
1398                                                                      iQuant, iFound);
1399    
1400                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1401                          *currMV = newMV;                          *currMV = newMV;
1402                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1403                  }                  }
# Line 1117  Line 1410 
1410    
1411  PMVfast16_Terminate_with_Refine:  PMVfast16_Terminate_with_Refine:
1412          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
1413                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
1414                                    x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1415                                    currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1416                                    pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
1417    
1418  PMVfast16_Terminate_without_Refine:  PMVfast16_Terminate_without_Refine:
1419          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
1420          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
1421          return iMinSAD;          return iMinSAD;
1422  }  }
1423    
# Line 1133  Line 1426 
1426    
1427    
1428    
1429  int32_t Diamond8_MainSearch(  int32_t
1430          const uint8_t * const pRef,  Diamond8_MainSearch(const uint8_t * const pRef,
1431          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1432          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1433          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1434          const uint8_t * const cur,          const uint8_t * const cur,
1435          const int x, const int y,                                          const int x,
1436          int32_t startx, int32_t starty,                                          const int y,
1437                                            const int32_t start_x,
1438                                            const int32_t start_y,
1439          int32_t iMinSAD,          int32_t iMinSAD,
1440          VECTOR * const currMV,          VECTOR * const currMV,
1441          const VECTOR * const pmv,                                          const int center_x,
1442          const int32_t min_dx, const int32_t max_dx,                                          const int center_y,
1443          const int32_t min_dy, const int32_t max_dy,                                          const int32_t min_dx,
1444                                            const int32_t max_dx,
1445                                            const int32_t min_dy,
1446                                            const int32_t max_dy,
1447          const int32_t iEdgedWidth,          const int32_t iEdgedWidth,
1448          const int32_t iDiamondSize,          const int32_t iDiamondSize,
1449          const int32_t iFcode,          const int32_t iFcode,
# Line 1155  Line 1453 
1453  /* Do a diamond search around given starting point, return SAD of best */  /* Do a diamond search around given starting point, return SAD of best */
1454    
1455          int32_t iDirection=0;          int32_t iDirection=0;
1456            int32_t iDirectionBackup;
1457          int32_t iSAD;          int32_t iSAD;
1458          VECTOR backupMV;          VECTOR backupMV;
1459          backupMV.x = startx;  
1460          backupMV.y = starty;          backupMV.x = start_x;
1461            backupMV.y = start_y;
1462    
1463  /* 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 */
1464    
# Line 1167  Line 1467 
1467          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
1468          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);          CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
1469    
1470          if (iDirection)          if (iDirection) {
1471                  while (!iFound)                  while (!iFound) {
                 {  
1472                          iFound = 1;                          iFound = 1;
1473                          backupMV=*currMV;       // since iDirection!=0, this is well defined!                          backupMV=*currMV;       // since iDirection!=0, this is well defined!
1474                            iDirectionBackup = iDirection;
1475    
1476                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
1477                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1478                          if ( iDirection != 1)                                                                                    backupMV.y, 1);
1479                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
1480                          if ( iDirection != 4)                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1481                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                    backupMV.y, 2);
1482                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
1483                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1484                                                                                      backupMV.y - iDiamondSize, 3);
1485                            if (iDirectionBackup != 3)
1486                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1487                                                                                      backupMV.y + iDiamondSize, 4);
1488                  }                  }
1489          else          } else {
1490                    currMV->x = start_x;
1491                    currMV->y = start_y;
1492            }
1493            return iMinSAD;
1494    }
1495    
1496    
1497    
1498    
1499    int32_t
1500    Square8_MainSearch(const uint8_t * const pRef,
1501                                       const uint8_t * const pRefH,
1502                                       const uint8_t * const pRefV,
1503                                       const uint8_t * const pRefHV,
1504                                       const uint8_t * const cur,
1505                                       const int x,
1506                                       const int y,
1507                                       const int32_t start_x,
1508                                       const int32_t start_y,
1509                                       int32_t iMinSAD,
1510                                       VECTOR * const currMV,
1511                                       const int center_x,
1512                                       const int center_y,
1513                                       const int32_t min_dx,
1514                                       const int32_t max_dx,
1515                                       const int32_t min_dy,
1516                                       const int32_t max_dy,
1517                                       const int32_t iEdgedWidth,
1518                                       const int32_t iDiamondSize,
1519                                       const int32_t iFcode,
1520                                       const int32_t iQuant,
1521                                       int iFound)
1522          {          {
1523                  currMV->x = startx;  /* Do a square search around given starting point, return SAD of best */
1524                  currMV->y = starty;  
1525            int32_t iDirection = 0;
1526            int32_t iSAD;
1527            VECTOR backupMV;
1528    
1529            backupMV.x = start_x;
1530            backupMV.y = start_y;
1531    
1532    /* It's one search with full square pattern, and new parts for all following diamonds */
1533    
1534    /*   new direction are extra, so 1-4 is normal diamond
1535          537
1536          1*2
1537          648
1538    */
1539    
1540            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1541            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1542            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1543            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1544    
1545            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1546                                                             backupMV.y - iDiamondSize, 5);
1547            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1548                                                             backupMV.y + iDiamondSize, 6);
1549            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1550                                                             backupMV.y - iDiamondSize, 7);
1551            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1552                                                             backupMV.y + iDiamondSize, 8);
1553    
1554    
1555            if (iDirection) {
1556                    while (!iFound) {
1557                            iFound = 1;
1558                            backupMV = *currMV;
1559    
1560                            switch (iDirection) {
1561                            case 1:
1562                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1563                                                                                       backupMV.y, 1);
1564                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1565                                                                                     backupMV.y - iDiamondSize, 5);
1566                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1567                                                                                     backupMV.y - iDiamondSize, 7);
1568                                    break;
1569                            case 2:
1570                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1571                                                                                     2);
1572                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1573                                                                                     backupMV.y + iDiamondSize, 6);
1574                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1575                                                                                     backupMV.y + iDiamondSize, 8);
1576                                    break;
1577    
1578                            case 3:
1579                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1580                                                                                     4);
1581                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1582                                                                                     backupMV.y - iDiamondSize, 7);
1583                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1584                                                                                     backupMV.y + iDiamondSize, 8);
1585                                    break;
1586    
1587                            case 4:
1588                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1589                                                                                     3);
1590                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1591                                                                                     backupMV.y - iDiamondSize, 5);
1592                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1593                                                                                     backupMV.y + iDiamondSize, 6);
1594                                    break;
1595    
1596                            case 5:
1597                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1598                                                                                     1);
1599                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1600                                                                                     3);
1601                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1602                                                                                     backupMV.y - iDiamondSize, 5);
1603                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1604                                                                                     backupMV.y + iDiamondSize, 6);
1605                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1606                                                                                     backupMV.y - iDiamondSize, 7);
1607                                    break;
1608    
1609                            case 6:
1610                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1611                                                                                     2);
1612                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1613                                                                                     3);
1614    
1615                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1616                                                                                     backupMV.y - iDiamondSize, 5);
1617                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1618                                                                                     backupMV.y + iDiamondSize, 6);
1619                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1620                                                                                     backupMV.y + iDiamondSize, 8);
1621    
1622                                    break;
1623    
1624                            case 7:
1625                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1626                                                                                       backupMV.y, 1);
1627                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1628                                                                                     4);
1629                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1630                                                                                     backupMV.y - iDiamondSize, 5);
1631                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1632                                                                                     backupMV.y - iDiamondSize, 7);
1633                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1634                                                                                     backupMV.y + iDiamondSize, 8);
1635                                    break;
1636    
1637                            case 8:
1638                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1639                                                                                     2);
1640                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1641                                                                                     4);
1642                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1643                                                                                     backupMV.y + iDiamondSize, 6);
1644                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1645                                                                                     backupMV.y - iDiamondSize, 7);
1646                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1647                                                                                     backupMV.y + iDiamondSize, 8);
1648                                    break;
1649                            default:
1650                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1651                                                                                     1);
1652                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1653                                                                                     2);
1654                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1655                                                                                     3);
1656                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1657                                                                                     4);
1658    
1659                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1660                                                                                     backupMV.y - iDiamondSize, 5);
1661                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1662                                                                                     backupMV.y + iDiamondSize, 6);
1663                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1664                                                                                     backupMV.y - iDiamondSize, 7);
1665                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1666                                                                                     backupMV.y + iDiamondSize, 8);
1667                                    break;
1668                            }
1669                    }
1670            } else {
1671                    currMV->x = start_x;
1672                    currMV->y = start_y;
1673          }          }
1674          return iMinSAD;          return iMinSAD;
1675  }  }
1676    
1677  int32_t Halfpel8_Refine(  
1678          const uint8_t * const pRef,  
1679    
1680    
1681    int32_t
1682    Halfpel8_Refine_c(const uint8_t * const pRef,
1683          const uint8_t * const pRefH,          const uint8_t * const pRefH,
1684          const uint8_t * const pRefV,          const uint8_t * const pRefV,
1685          const uint8_t * const pRefHV,          const uint8_t * const pRefHV,
1686          const uint8_t * const cur,          const uint8_t * const cur,
1687          const int x, const int y,                                    const int x,
1688                                      const int y,
1689          VECTOR * const currMV,          VECTOR * const currMV,
1690          int32_t iMinSAD,          int32_t iMinSAD,
1691          const VECTOR * const pmv,                                    const int center_x,
1692          const int32_t min_dx, const int32_t max_dx,                                    const int center_y,
1693          const int32_t min_dy, const int32_t max_dy,                                    const int32_t min_dx,
1694                                      const int32_t max_dx,
1695                                      const int32_t min_dy,
1696                                      const int32_t max_dy,
1697          const int32_t iFcode,          const int32_t iFcode,
1698          const int32_t iQuant,          const int32_t iQuant,
1699          const int32_t iEdgedWidth)          const int32_t iEdgedWidth)
# Line 1226  Line 1718 
1718    
1719  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1720    
1721  int32_t PMVfastSearch8(  int32_t
1722                                          const uint8_t * const pRef,  PMVfastSearch8(const uint8_t * const pRef,
1723                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
1724                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
1725                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
1726                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
1727                                          const int x, const int y,                             const int x,
1728                                          const int start_x, int start_y,                             const int y,
1729                               const int start_x,
1730                               const int start_y,
1731                                    const int center_x,
1732                                    const int center_y,
1733                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
1734                               const uint32_t iQuant,
1735                               const uint32_t iFcode,
1736                                          const MBParam * const pParam,                                          const MBParam * const pParam,
1737                                          MACROBLOCK * const pMBs,                             const MACROBLOCK * const pMBs,
1738                               const MACROBLOCK * const prevMBs,
1739                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1740                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
1741  {  {
1742          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;  
1743          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
1744          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
1745          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 1261  Line 1757 
1757          int32_t psad[4];          int32_t psad[4];
1758          VECTOR newMV;          VECTOR newMV;
1759          VECTOR backupMV;          VECTOR backupMV;
1760            VECTOR startMV;
1761    
1762          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1763            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
1764    
1765          static int32_t threshA,threshB;           int32_t threshA, threshB;
1766          int32_t iFound,bPredEq;          int32_t iFound,bPredEq;
1767          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
1768    
1769          int32_t iSubBlock = ((y&1)<<1) + (x&1);          int32_t iSubBlock = (y & 1) + (y & 1) + (x & 1);
1770    
1771  /* Get maximum range */          MainSearch8FuncPtr MainSearchPtr;
         get_range(&min_dx, &max_dx, &min_dy, &max_dy,  
                   x, y, 8, iWidth, iHeight, iFcode);  
1772    
1773  /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */          /* Init variables */
1774            startMV.x = start_x;
1775            startMV.y = start_y;
1776    
1777          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          /* Get maximum range */
1778          { min_dx = EVEN(min_dx);          get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
1779                              iFcode);
1780    
1781            if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
1782                    min_dx = EVEN(min_dx);
1783          max_dx = EVEN(max_dx);          max_dx = EVEN(max_dx);
1784          min_dy = EVEN(min_dy);          min_dy = EVEN(min_dy);
1785          max_dy = EVEN(max_dy);          max_dy = EVEN(max_dy);
1786          }               /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          }
   
1787    
1788          bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
1789            bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
1790    
1791          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
1792                  threshA =  512/4;                  threshA =  512/4;
1793                  threshB = 1024/4;                  threshB = 1024/4;
1794    
1795          }          } else {
1796          else                  threshA = psad[0] / 4;  /* good estimate? */
         {  
                 threshA = psad[0]/4;                    /* good estimate */  
1797                  threshB = threshA+256/4;                  threshB = threshA+256/4;
1798                  if (threshA< 512/4) threshA =  512/4;                  if (threshA < 512 / 4)
1799                  if (threshA>1024/4) threshA = 1024/4;                          threshA = 512 / 4;
1800                  if (threshB>1792/4) threshB = 1792/4;                  if (threshA > 1024 / 4)
1801                            threshA = 1024 / 4;
1802                    if (threshB > 1792 / 4)
1803                            threshB = 1792 / 4;
1804          }          }
1805    
1806          iFound=0;          iFound=0;
1807    
 /* 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;  
   
1808  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
1809     MinSAD=SAD     MinSAD=SAD
1810     If Motion Vector equal to Previous frame motion vector     If Motion Vector equal to Previous frame motion vector
# Line 1333  Line 1815 
1815    
1816  // Prepare for main loop  // Prepare for main loop
1817    
1818          currMV->x=start_x;              /* start with mv16 */    if (MotionFlags & PMV_USESQUARES8)
1819          currMV->y=start_y;        MainSearchPtr = Square8_MainSearch;
1820      else
1821    
1822            if (MotionFlags & PMV_ADVANCEDDIAMOND8)
1823                    MainSearchPtr = AdvDiamond8_MainSearch;
1824            else
1825                    MainSearchPtr = Diamond8_MainSearch;
1826    
         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;  
1827    
1828          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          *currMV = startMV;
1829          {  
1830            iMinSAD =
1831                    sad8(cur,
1832                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
1833                                                    iEdgedWidth), iEdgedWidth);
1834            iMinSAD +=
1835                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
1836                                             (uint8_t) iFcode, iQuant);
1837    
1838            if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))
1839                                                                    && ((int32_t) iMinSAD <
1840                                                                            prevMB->sad8[iSubBlock]))) {
1841                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1842                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
1843                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
1844                          goto PMVfast8_Terminate_with_Refine;                          goto PMVfast8_Terminate_with_Refine;
1845          }          }
1846    
1847    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1848       vector of the median.
1849       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1850    */
1851    
1852            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[iSubBlock])))
1853                    iFound = 2;
1854    
1855    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1856       Otherwise select large Diamond Search.
1857    */
1858    
1859            if ((!MVzero(pmv[0])) || (threshB < 1536 / 4) || (bPredEq))
1860                    iDiamondSize = 1;               // 1 halfpel!
1861            else
1862                    iDiamondSize = 2;               // 2 halfpel = 1 full pixel!
1863    
1864            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
1865                    iDiamondSize *= 2;
1866    
1867    
1868  /*  /*
1869     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.
1870     Also calculate (0,0) but do not subtract offset.     Also calculate (0,0) but do not subtract offset.
1871     Let MinSAD be the smallest SAD up to this point.     Let MinSAD be the smallest SAD up to this point.
1872     If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
1873  */  */
1874    
1875  // 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);  
1876    
1877  // (0,0) is always possible          if (!MVequal(pmv[0], startMV))
1878                    CHECK_MV8_CANDIDATE(center_x, center_y);
1879    
1880    // (0,0) if needed
1881            if (!MVzero(pmv[0]))
1882                    if (!MVzero(startMV))
1883          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
1884    
1885  // previous frame MV is always possible  // previous frame MV if needed
1886          CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);          if (!MVzero(prevMB->mvs[iSubBlock]))
1887                    if (!MVequal(prevMB->mvs[iSubBlock], startMV))
1888                            if (!MVequal(prevMB->mvs[iSubBlock], pmv[0]))
1889                                    CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,
1890                                                                            prevMB->mvs[iSubBlock].y);
1891    
1892            if ((iMinSAD <= threshA) ||
1893                    (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
1894                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
1895                    if (MotionFlags & PMV_QUICKSTOP16)
1896                            goto PMVfast8_Terminate_without_Refine;
1897                    if (MotionFlags & PMV_EARLYSTOP16)
1898                            goto PMVfast8_Terminate_with_Refine;
1899            }
1900    
1901  // left neighbour, if allowed  // left neighbour, if allowed and needed
1902          if (psad[1] != MV_MAX_ERROR)          if (!MVzero(pmv[1]))
1903          {                  if (!MVequal(pmv[1], startMV))
1904                  if (!(MotionFlags & PMV_HALFPEL8 ))                          if (!MVequal(pmv[1], prevMB->mvs[iSubBlock]))
1905                  {       pmv[1].x = EVEN(pmv[1].x);                                  if (!MVequal(pmv[1], pmv[0])) {
1906                                            if (!(MotionFlags & PMV_HALFPEL8)) {
1907                                                    pmv[1].x = EVEN(pmv[1].x);
1908                  pmv[1].y = EVEN(pmv[1].y);                  pmv[1].y = EVEN(pmv[1].y);
1909                  }                  }
1910                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
1911          }          }
1912    // top neighbour, if allowed and needed
1913  // top neighbour, if allowed          if (!MVzero(pmv[2]))
1914          if (psad[2] != MV_MAX_ERROR)                  if (!MVequal(pmv[2], startMV))
1915          {                          if (!MVequal(pmv[2], prevMB->mvs[iSubBlock]))
1916                  if (!(MotionFlags & PMV_HALFPEL8 ))                                  if (!MVequal(pmv[2], pmv[0]))
1917                  {       pmv[2].x = EVEN(pmv[2].x);                                          if (!MVequal(pmv[2], pmv[1])) {
1918                                                    if (!(MotionFlags & PMV_HALFPEL8)) {
1919                                                            pmv[2].x = EVEN(pmv[2].x);
1920                  pmv[2].y = EVEN(pmv[2].y);                  pmv[2].y = EVEN(pmv[2].y);
1921                  }                  }
1922                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
1923    
1924  // top right neighbour, if allowed  // top right neighbour, if allowed and needed
1925                  if (psad[3] != MV_MAX_ERROR)                                                  if (!MVzero(pmv[3]))
1926                  {                                                          if (!MVequal(pmv[3], startMV))
1927                          if (!(MotionFlags & PMV_HALFPEL8 ))                                                                  if (!MVequal(pmv[3], prevMB->mvs[iSubBlock]))
1928                          {       pmv[3].x = EVEN(pmv[3].x);                                                                          if (!MVequal(pmv[3], pmv[0]))
1929                                                                                    if (!MVequal(pmv[3], pmv[1]))
1930                                                                                            if (!MVequal(pmv[3], pmv[2])) {
1931                                                                                                    if (!
1932                                                                                                            (MotionFlags &
1933                                                                                                             PMV_HALFPEL8)) {
1934                                                                                                            pmv[3].x = EVEN(pmv[3].x);
1935                          pmv[3].y = EVEN(pmv[3].y);                          pmv[3].y = EVEN(pmv[3].y);
1936                          }                          }
1937                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                                  CHECK_MV8_CANDIDATE(pmv[3].x,
1938                                                                                                                                            pmv[3].y);
1939                  }                  }
1940          }          }
1941    
1942            if ((MVzero(*currMV)) &&
1943                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1944                    iMinSAD -= MV8_00_BIAS;
1945    
1946    
1947  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
1948     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.
1949  */  */
1950    
1951          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
1952          {                  (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
1953                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
1954                  if (MotionFlags & PMV_QUICKSTOP16)                  if (MotionFlags & PMV_QUICKSTOP16)
1955                          goto PMVfast8_Terminate_without_Refine;                          goto PMVfast8_Terminate_without_Refine;
1956                  if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_EARLYSTOP16)
# Line 1421  Line 1970 
1970          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
1971    
1972  /* 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 */
1973          iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
1974                                           x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
1975                                           currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
1976                                           pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1977                                                      iQuant, iFound);
1978    
1979          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
1980                  *currMV = newMV;                  *currMV = newMV;
1981                  iMinSAD = iSAD;                  iMinSAD = iSAD;
1982          }          }
1983    
1984          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
1985  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
1986    
1987                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
1988                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
1989                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1990                                                            pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
1991                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1992                                                                      iDiamondSize, iFcode, iQuant, iFound);
1993    
1994                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
1995                          *currMV = newMV;                          *currMV = newMV;
1996                          iMinSAD = iSAD;                          iMinSAD = iSAD;
1997                  }                  }
1998                  }                  }
1999    
2000                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2001                  {       iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
2002                                                            x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2003                                                            0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2004                                                            pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2005                                                                      iQuant, iFound);
2006    
2007                  if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                 {  
2008                          *currMV = newMV;                          *currMV = newMV;
2009                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2010                  }                  }
# Line 1469  Line 2017 
2017    
2018  PMVfast8_Terminate_with_Refine:  PMVfast8_Terminate_with_Refine:
2019          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2020                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2021                                                   x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2022                                                   currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2023                                                   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2024    
2025    
2026  PMVfast8_Terminate_without_Refine:  PMVfast8_Terminate_without_Refine:
2027          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2028          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2029    
2030          return iMinSAD;          return iMinSAD;
2031  }  }
2032    
2033  int32_t EPZSSearch16(  int32_t
2034                                          const uint8_t * const pRef,  EPZSSearch16(const uint8_t * const pRef,
2035                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2036                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2037                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2038                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2039                                          const int x, const int y,                           const int x,
2040                             const int y,
2041                            const int start_x,
2042                            const int start_y,
2043                            const int center_x,
2044                            const int center_y,
2045                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2046                             const uint32_t iQuant,
2047                             const uint32_t iFcode,
2048                                          const MBParam * const pParam,                                          const MBParam * const pParam,
2049                                          MACROBLOCK * const pMBs,                           const MACROBLOCK * const pMBs,
2050                             const MACROBLOCK * const prevMBs,
2051                                          VECTOR * const currMV,                                          VECTOR * const currMV,
2052                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
2053  {  {
2054          const uint32_t iWcount = pParam->mb_width;          const uint32_t iWcount = pParam->mb_width;
2055          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;  
2056    
2057          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
2058          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
# Line 1518  Line 2072 
2072          int32_t psad[8];          int32_t psad[8];
2073    
2074          static MACROBLOCK * oldMBs = NULL;          static MACROBLOCK * oldMBs = NULL;
2075          MACROBLOCK * const pMB = pMBs + x + y * iWcount;  
2076    //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
2077            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2078          MACROBLOCK * oldMB = NULL;          MACROBLOCK * oldMB = NULL;
2079    
2080          static int32_t thresh2;           int32_t thresh2;
2081          int32_t bPredEq;          int32_t bPredEq;
2082          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2083    
2084          MainSearch16FuncPtr EPZSMainSearchPtr;          MainSearch16FuncPtr MainSearchPtr;
2085    
2086          if (oldMBs == NULL)          if (oldMBs == NULL) {
2087          {       oldMBs = (MACROBLOCK*) calloc(1,iWcount*iHcount*sizeof(MACROBLOCK));                  oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
2088                  fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));  //      fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
2089          }          }
2090          oldMB = oldMBs + x + y * iWcount;          oldMB = oldMBs + x + y * iWcount;
2091    
2092  /* Get maximum range */  /* Get maximum range */
2093          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,
2094                          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 */  
2095    
2096          if (!(MotionFlags & PMV_HALFPEL16 ))          if (!(MotionFlags & PMV_HALFPEL16)) {
2097          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2098            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2099            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2100            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2101          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2102            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2103          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);          bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2104    
2105  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2106          MinSAD=SAD          MinSAD=SAD
# Line 1557  Line 2111 
2111    
2112  // Prepare for main loop  // Prepare for main loop
2113    
2114          *currMV=pmv[0];         /* current best := median prediction */          currMV->x = start_x;
2115          if (!(MotionFlags & PMV_HALFPEL16))          currMV->y = start_y;
2116          {  
2117            if (!(MotionFlags & PMV_HALFPEL16)) {
2118                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2119                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2120          }          }
# Line 1575  Line 2130 
2130    
2131  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2132    
2133          iMinSAD = sad16( cur,          iMinSAD =
2134                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  sad16(cur,
2135                  iEdgedWidth, MV_MAX_ERROR);                            get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2136          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                   iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2137            iMinSAD +=
2138                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2139                                              (uint8_t) iFcode, iQuant);
2140    
2141  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2142          if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )          if ((iMinSAD < 256) ||
2143                  {                  ((MVequal(*currMV, prevMB->mvs[0])) &&
2144                     ((int32_t) iMinSAD < prevMB->sad16))) {
2145                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2146                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2147                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1592  Line 2151 
2151  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2152    
2153  // previous frame MV  // previous frame MV
2154          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
2155    
2156  // set threshhold based on Min of Prediction and SAD of collocated block  // set threshhold based on Min of Prediction and SAD of collocated block
2157  // 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
2158    
2159          if ((x==0) && (y==0) )          if ((x == 0) && (y == 0)) {
         {  
2160                  thresh2 =  512;                  thresh2 =  512;
2161          }          } else {
         else  
         {  
2162  /* 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] */
2163    
2164                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;                  thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
# Line 1614  Line 2170 
2170    
2171    
2172  // left neighbour, if allowed  // left neighbour, if allowed
2173          if (x != 0)          if (x != 0) {
2174          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2175                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2176                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2177                  }                  }
2178                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
2179          }          }
   
2180  // top neighbour, if allowed  // top neighbour, if allowed
2181          if (y != 0)          if (y != 0) {
2182          {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2183                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2184                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2185                  }                  }
2186                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
2187    
2188  // top right neighbour, if allowed  // top right neighbour, if allowed
2189                  if (x != (iWcount-1))                  if ((uint32_t) x != (iWcount - 1)) {
2190                  {                          if (!(MotionFlags & PMV_HALFPEL16)) {
2191                          if (!(MotionFlags & PMV_HALFPEL16 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2192                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2193                          }                          }
2194                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
# Line 1648  Line 2200 
2200  */  */
2201    
2202          if ( (iMinSAD <= thresh2)          if ( (iMinSAD <= thresh2)
2203                  || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD <= pMB->sad16) ) )                  || (MVequal(*currMV, prevMB->mvs[0]) &&
2204                  {                          ((int32_t) iMinSAD <= prevMB->sad16))) {
2205                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2206                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2207                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1658  Line 2210 
2210    
2211  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
2212    
2213          backupMV = pMB->mvs[0];                 // last MV          backupMV = prevMB->mvs[0];      // collocated MV
2214          backupMV.x += (pMB->mvs[0].x - oldMB->mvs[0].x );       // acceleration X          backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x);     // acceleration X
2215          backupMV.y += (pMB->mvs[0].y - oldMB->mvs[0].y );       // acceleration Y          backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y);     // acceleration Y
2216    
2217          CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);          CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);
2218    
2219  // left neighbour  // left neighbour
2220          if (x != 0)          if (x != 0)
2221                  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);
2222    
2223  // top neighbour  // top neighbour
2224          if (y != 0)          if (y != 0)
2225                  CHECK_MV16_CANDIDATE((oldMB-iWcount)->mvs[0].x,oldMB->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,
2226                                                             (prevMB - iWcount)->mvs[0].y);
2227    
2228  // 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
2229    
2230          if (x != iWcount-1)          if ((uint32_t) x != iWcount - 1)
2231                  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);
2232    
2233  // bottom neighbour, dito  // bottom neighbour, dito
2234          if (y != iHcount-1)          if ((uint32_t) y != iHcount - 1)
2235                  CHECK_MV16_CANDIDATE((pMB+iWcount)->mvs[0].x,oldMB->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,
2236                                                             (prevMB + iWcount)->mvs[0].y);
2237    
2238  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */  /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
2239          if (iMinSAD <= thresh2)          if (iMinSAD <= thresh2) {
                 {  
2240                          if (MotionFlags & PMV_QUICKSTOP16)                          if (MotionFlags & PMV_QUICKSTOP16)
2241                                  goto EPZS16_Terminate_without_Refine;                                  goto EPZS16_Terminate_without_Refine;
2242                          if (MotionFlags & PMV_EARLYSTOP16)                          if (MotionFlags & PMV_EARLYSTOP16)
# Line 1694  Line 2247 
2247    
2248          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2249    
 /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  
   
2250          if (MotionFlags & PMV_USESQUARES16)          if (MotionFlags & PMV_USESQUARES16)
2251                  EPZSMainSearchPtr = Square16_MainSearch;                  MainSearchPtr = Square16_MainSearch;
2252          else          else
2253                  EPZSMainSearchPtr = Diamond16_MainSearch;           if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2254                    MainSearchPtr = AdvDiamond16_MainSearch;
2255            else
2256                    MainSearchPtr = Diamond16_MainSearch;
2257    
2258          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);  
2259    
2260          if (iSAD < iMinSAD)          iSAD =
2261          {                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2262                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2263                                                      min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2264    
2265            if (iSAD < iMinSAD) {
2266                  *currMV = newMV;                  *currMV = newMV;
2267                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2268          }          }
2269    
2270    
2271          if (MotionFlags & PMV_EXTSEARCH16)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
2272  /* 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) */
2273    
2274                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2275                  {                          iSAD =
2276                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2277                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2278                                  pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2279                                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);                                                                    2, iFcode, iQuant, 0);
2280                  }                  }
2281    
2282                  if (iSAD < iMinSAD)                  if (iSAD < iMinSAD) {
                 {  
2283                          *currMV = newMV;                          *currMV = newMV;
2284                          iMinSAD = iSAD;                          iMinSAD = iSAD;
2285                  }                  }
2286    
2287                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2288                  {                          iSAD =
2289                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2290                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2291                          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);  
2292    
2293                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2294                                  *currMV = newMV;                                  *currMV = newMV;
2295                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2296                          }                          }
# Line 1750  Line 2301 
2301    
2302  EPZS16_Terminate_with_Refine:  EPZS16_Terminate_with_Refine:
2303          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step
2304                  iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2305                                  x, y,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2306                                  currMV, iMinSAD,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2307                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                           iFcode, iQuant, iEdgedWidth);
2308    
2309  EPZS16_Terminate_without_Refine:  EPZS16_Terminate_without_Refine:
2310    
2311          *oldMB = *pMB;          *oldMB = *prevMB;
2312    
2313          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2314          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2315          return iMinSAD;          return iMinSAD;
2316  }  }
2317    
2318    
2319  int32_t EPZSSearch8(  int32_t
2320                                          const uint8_t * const pRef,  EPZSSearch8(const uint8_t * const pRef,
2321                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2322                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2323                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2324                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2325                                          const int x, const int y,                          const int x,
2326                                          const int start_x, const int start_y,                          const int y,
2327                            const int start_x,
2328                            const int start_y,
2329                            const int center_x,
2330                            const int center_y,
2331                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2332                            const uint32_t iQuant,
2333                            const uint32_t iFcode,
2334                                          const MBParam * const pParam,                                          const MBParam * const pParam,
2335                                          MACROBLOCK * const pMBs,                          const MACROBLOCK * const pMBs,
2336                            const MACROBLOCK * const prevMBs,
2337                                          VECTOR * const currMV,                                          VECTOR * const currMV,
2338                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
2339  {  {
2340          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;  
2341    
2342            const uint32_t iWcount = pParam->mb_width;
2343          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
2344          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
2345          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
# Line 1804  Line 2361 
2361    
2362          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);          const   int32_t iSubBlock = ((y&1)<<1) + (x&1);
2363    
2364          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2365            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
2366    
2367          int32_t bPredEq;          int32_t bPredEq;
2368          int32_t iMinSAD,iSAD=9999;          int32_t iMinSAD,iSAD=9999;
2369    
2370          MainSearch8FuncPtr EPZSMainSearchPtr;          MainSearch8FuncPtr MainSearchPtr;
2371    
2372  /* Get maximum range */  /* Get maximum range */
2373          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,
2374                          x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2375    
2376  /* 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 */
2377    
2378          if (!(MotionFlags & PMV_HALFPEL8 ))          if (!(MotionFlags & PMV_HALFPEL8)) {
2379          { min_dx = EVEN(min_dx);                  min_dx = EVEN(min_dx);
2380            max_dx = EVEN(max_dx);            max_dx = EVEN(max_dx);
2381            min_dy = EVEN(min_dy);            min_dy = EVEN(min_dy);
2382            max_dy = EVEN(max_dy);            max_dy = EVEN(max_dy);
2383          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          }
2384            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2385          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);
2386    
2387    
2388  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
# Line 1837  Line 2395 
2395  // Prepare for main loop  // Prepare for main loop
2396    
2397    
2398          if (!(MotionFlags & PMV_HALFPEL8))          if (!(MotionFlags & PMV_HALFPEL8)) {
         {  
2399                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2400                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2401          }          }
# Line 1855  Line 2412 
2412  /***************** This is predictor SET A: only median prediction ******************/  /***************** This is predictor SET A: only median prediction ******************/
2413    
2414    
2415          iMinSAD = sad8( cur,          iMinSAD =
2416                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  sad8(cur,
2417                  iEdgedWidth);                           get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2418          iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                                                  iEdgedWidth), iEdgedWidth);
2419            iMinSAD +=
2420                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2421                                             (uint8_t) iFcode, iQuant);
2422    
2423    
2424  // thresh1 is fixed to 256  // thresh1 is fixed to 256
2425          if (iMinSAD < 256/4 )          if (iMinSAD < 256 / 4) {
                 {  
2426                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2427                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2428                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
# Line 1872  Line 2431 
2431    
2432  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2433    
 // previous frame MV  
         CHECK_MV8_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);  
2434    
2435  // MV=(0,0) is often a good choice  // MV=(0,0) is often a good choice
   
2436          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
2437    
2438    // previous frame MV
2439            CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x, prevMB->mvs[iSubBlock].y);
2440    
2441    // left neighbour, if allowed
2442            if (psad[1] != MV_MAX_ERROR) {
2443                    if (!(MotionFlags & PMV_HALFPEL8)) {
2444                            pmv[1].x = EVEN(pmv[1].x);
2445                            pmv[1].y = EVEN(pmv[1].y);
2446                    }
2447                    CHECK_MV8_CANDIDATE(pmv[1].x, pmv[1].y);
2448            }
2449    // top neighbour, if allowed
2450            if (psad[2] != MV_MAX_ERROR) {
2451                    if (!(MotionFlags & PMV_HALFPEL8)) {
2452                            pmv[2].x = EVEN(pmv[2].x);
2453                            pmv[2].y = EVEN(pmv[2].y);
2454                    }
2455                    CHECK_MV8_CANDIDATE(pmv[2].x, pmv[2].y);
2456    
2457    // top right neighbour, if allowed
2458                    if (psad[3] != MV_MAX_ERROR) {
2459                            if (!(MotionFlags & PMV_HALFPEL8)) {
2460                                    pmv[3].x = EVEN(pmv[3].x);
2461                                    pmv[3].y = EVEN(pmv[3].y);
2462                            }
2463                            CHECK_MV8_CANDIDATE(pmv[3].x, pmv[3].y);
2464                    }
2465            }
2466    
2467    /*  // this bias is zero anyway, at the moment!
2468    
2469            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
2470                    iMinSAD -= MV8_00_BIAS;
2471    
2472    */
2473    
2474  /* Terminate if MinSAD <= T_2  /* Terminate if MinSAD <= T_2
2475     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]
2476  */  */
2477    
2478          if (iMinSAD < 512/4)    /* T_2 == 512/4 hardcoded */          if (iMinSAD < 512 / 4) {        /* T_2 == 512/4 hardcoded */
                 {  
2479                          if (MotionFlags & PMV_QUICKSTOP8)                          if (MotionFlags & PMV_QUICKSTOP8)
2480                                  goto EPZS8_Terminate_without_Refine;                                  goto EPZS8_Terminate_without_Refine;
2481                          if (MotionFlags & PMV_EARLYSTOP8)                          if (MotionFlags & PMV_EARLYSTOP8)
2482                                  goto EPZS8_Terminate_with_Refine;                                  goto EPZS8_Terminate_with_Refine;
2483                  }                  }
2484    
2485  /************ (if Diamond Search)  **************/  /************ (Diamond Search)  **************/
2486    
2487          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2488    
2489          if (!(MotionFlags & PMV_HALFPELDIAMOND8))          if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2490                  iDiamondSize *= 2;                  iDiamondSize *= 2;
2491    
2492  /* 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 */
2493    
2494  //      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);  
2495    
2496      if (MotionFlags & PMV_USESQUARES8)
2497          MainSearchPtr = Square8_MainSearch;
2498      else
2499    
2500          if (iSAD < iMinSAD)          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2501          {                  MainSearchPtr = AdvDiamond8_MainSearch;
2502            else
2503                    MainSearchPtr = Diamond8_MainSearch;
2504    
2505            iSAD =
2506                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2507                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2508                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2509                                                      iQuant, 0);
2510    
2511    
2512            if (iSAD < iMinSAD) {
2513                  *currMV = newMV;                  *currMV = newMV;
2514                  iMinSAD = iSAD;                  iMinSAD = iSAD;
2515          }          }
2516    
2517          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH8) {
         {  
2518  /* 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) */
2519    
2520                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
2521                  {                          iSAD =
2522                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2523                                  x, y,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2524                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2525                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iDiamondSize, iFcode, iQuant, 0);
2526    
2527                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2528                                  *currMV = newMV;                                  *currMV = newMV;
2529                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2530                          }                          }
2531                  }                  }
2532    
2533                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2534                  {                          iSAD =
2535                          iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2536                                  x, y,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2537                          0, 0, iMinSAD, &newMV,                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2538                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);                                                                    iQuant, 0);
2539    
2540                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
2541                                  *currMV = newMV;                                  *currMV = newMV;
2542                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2543                          }                          }
# Line 1955  Line 2548 
2548    
2549  EPZS8_Terminate_with_Refine:  EPZS8_Terminate_with_Refine:
2550          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step
2551                  iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,                  iMinSAD =
2552                                  x, y,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2553                                  currMV, iMinSAD,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2554                                  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);                                                          iFcode, iQuant, iEdgedWidth);
2555    
2556  EPZS8_Terminate_without_Refine:  EPZS8_Terminate_without_Refine:
2557    
2558          currPMV->x = currMV->x - pmv[0].x;          currPMV->x = currMV->x - center_x;
2559          currPMV->y = currMV->y - pmv[0].y;          currPMV->y = currMV->y - center_y;
2560          return iMinSAD;          return iMinSAD;
2561  }  }
   

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

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