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

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

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