[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 486, Mon Sep 16 21:41:20 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  }  }
# 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          get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);  
383            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  */  */
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;                          iFound = 1;
445                          backupMV=*currMV;                          backupMV=*currMV;
446                            iDirectionBackup = iDirection;
447    
448                          if ( iDirection != 2)                          if (iDirectionBackup != 2)
449                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
450                          if ( iDirection != 1)                                                                                     backupMV.y, 1);
451                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);                          if (iDirectionBackup != 1)
452                          if ( iDirection != 4)                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
453                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);                                                                                     backupMV.y, 2);
454                          if ( iDirection != 3)                          if (iDirectionBackup != 4)
455                                  CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);                                  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          } else {
462                  {                  currMV->x = start_x;
463                          currMV->x = startx;                  currMV->y = start_y;
                         currMV->y = starty;  
464                  }                  }
465          return iMinSAD;          return iMinSAD;
466  }  }
467    
468  int32_t PMVfastSearch16_Refine(  int32_t
469                                          const uint8_t * const pRef,  Square16_MainSearch(const uint8_t * const pRef,
470                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
471                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
472                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
473                                          const uint8_t * const cur,                                          const uint8_t * const cur,
474                                          const int x, const int y,                                          const int x,
475                                            const int y,
476                                            const int start_x,
477                                            const int start_y,
478                                            int iMinSAD,
479                                          VECTOR * const currMV,                                          VECTOR * const currMV,
480                                          int32_t iMinSAD,                                          const int center_x,
481                                          const VECTOR * const pmv,                                          const int center_y,
482                                          const int32_t min_dx, const int32_t max_dx,                                          const int32_t min_dx,
483                                          const int32_t min_dy, const int32_t max_dy,                                          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,                                          const int32_t iFcode,
489                                          const int32_t iQuant,                                          const int32_t iQuant,
490                                          const int32_t iEdgedWidth)                                          int iFound)
491  {  {
492  /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  /* Do a square search around given starting point, return SAD of best */
493    
494            int32_t iDirection = 0;
495          int32_t iSAD;          int32_t iSAD;
496          VECTOR backupMV = *currMV;          VECTOR backupMV;
497    
498          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y-1);          backupMV.x = start_x;
499          CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y-1);          backupMV.y = start_y;
500          CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y-1);  
501          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y);  /* It's one search with full square pattern, and new parts for all following diamonds */
502          CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y);  
503          CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y+1);  /*   new direction are extra, so 1-4 is normal diamond
504          CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y+1);        537
505          CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y+1);        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;
527                            backupMV = *currMV;
528    
529                            switch (iDirection) {
530                            case 1:
531                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
532                                                                                       backupMV.y, 1);
533                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
534                                                                                     backupMV.y - iDiamondSize, 5);
535                                    CHECK_MV16_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
536                                                                                     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                    }
639            } else {
640                    currMV->x = start_x;
641                    currMV->y = start_y;
642            }
643          return iMinSAD;          return iMinSAD;
644  }  }
645    
 #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)  
646    
647  int32_t PMVfastSearch16(  int32_t
648                                          const uint8_t * const pRef,  Full16_MainSearch(const uint8_t * const pRef,
649                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
650                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
651                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
652                                          const IMAGE * const pCur,                                    const uint8_t * const cur,
653                                          const int x, const int y,                                    const int x,
654                                          const uint32_t MotionFlags,                                    const int y,
655                                          MBParam * const pParam,                                    const int start_x,
656                                          MACROBLOCK * const pMBs,                                    const int start_y,
657                                      int iMinSAD,
658                                          VECTOR * const currMV,                                          VECTOR * const currMV,
659                                          VECTOR * const currPMV)                                    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          const uint32_t iWcount = pParam->mb_width;          int32_t iSAD;
672          const int32_t iFcode = pParam->fixed_code;          int32_t dx, dy;
673          const int32_t iQuant = pParam->quant;          VECTOR backupMV;
         const int32_t iWidth = pParam->width;  
         const int32_t iHeight = pParam->height;  
         const int32_t iEdgedWidth = pParam->edged_width;  
674    
675          const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;          backupMV.x = start_x;
676            backupMV.y = start_y;
677    
678          int32_t iDiamondSize;          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          int32_t min_dx;          return iMinSAD;
683          int32_t max_dx;  }
         int32_t min_dy;  
         int32_t max_dy;  
684    
685          int32_t iFound;  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          VECTOR newMV;          int32_t iSAD;
711          VECTOR backupMV;        /* just for PMVFAST */          int start_x = start_xi, start_y = start_yi;
712    
713          VECTOR pmv[4];  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
         int32_t psad[4];  
714    
715          MACROBLOCK * const pMB = pMBs + x + y * iWcount;          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            return iMinSAD;
843    }
844    
845          static int32_t threshA,threshB;  #define CHECK_MV16_F_INTERPOL(X,Y) { \
846          int32_t bPredEq;    if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
847          int32_t iMinSAD,iSAD;      && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
848      { \
849        iSAD = sad16bi( cur, \
850                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
851                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
852                            iEdgedWidth); \
853        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
854        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
855        if (iSAD < iMinSAD) \
856        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); } } \
857    }
858    
859  /* Get maximum range */  #define CHECK_MV16_F_INTERPOL_FOUND(X,Y) { \
860          get_range(&min_dx, &max_dx, &min_dy, &max_dy,    if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \
861                          x, y, 16, iWidth, iHeight, iFcode);      && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \
862      { \
863        iSAD = sad16bi( cur, \
864                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
865                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \
866                            iEdgedWidth); \
867        iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\
868        iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\
869        if (iSAD < iMinSAD) \
870        {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); iFound=0;} } \
871    }
872    
873  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  #define CHECK_MV16_B_INTERPOL(X,Y) { \
874      if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
875        && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
876      { \
877        iSAD = sad16bi( cur, \
878                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
879                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
880                            iEdgedWidth); \
881        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
882        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
883        if (iSAD < iMinSAD) \
884        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); } } \
885    }
886    
887          if (!(MotionFlags & PMV_HALFPEL16 ))  #define CHECK_MV16_B_INTERPOL_FOUND(X,Y) { \
888          { min_dx = EVEN(min_dx);    if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \
889            max_dx = EVEN(max_dx);      && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \
890            min_dy = EVEN(min_dy);    { \
891            max_dy = EVEN(max_dy);      iSAD = sad16bi( cur, \
892          }               /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */                          get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \
893                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \
894                            iEdgedWidth); \
895        iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\
896        iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\
897        if (iSAD < iMinSAD) \
898        {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); iFound=0;} } \
899    }
900    
901    int32_t
902    Diamond16_InterpolMainSearch(const uint8_t * const f_pRef,
903                                                             const uint8_t * const f_pRefH,
904                                                             const uint8_t * const f_pRefV,
905                                                             const uint8_t * const f_pRefHV,
906    
907          bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);                                                           const uint8_t * const cur,
908    
909          if ((x==0) && (y==0) )                                                           const uint8_t * const b_pRef,
910          {                                                           const uint8_t * const b_pRefH,
911                  threshA =  512;                                                           const uint8_t * const b_pRefV,
912                  threshB = 1024;                                                           const uint8_t * const b_pRefHV,
913    
914                                                             const int x,
915                                                             const int y,
916    
917                                                             const int f_start_x,
918                                                             const int f_start_y,
919                                                             const int b_start_x,
920                                                             const int b_start_y,
921    
922                                                             int iMinSAD,
923                                                             VECTOR * const f_currMV,
924                                                             VECTOR * const b_currMV,
925    
926                                                             const int f_center_x,
927                                                             const int f_center_y,
928                                                             const int b_center_x,
929                                                             const int b_center_y,
930    
931                                                             const int32_t f_min_dx,
932                                                             const int32_t f_max_dx,
933                                                             const int32_t f_min_dy,
934                                                             const int32_t f_max_dy,
935    
936                                                             const int32_t b_min_dx,
937                                                             const int32_t b_max_dx,
938                                                             const int32_t b_min_dy,
939                                                             const int32_t b_max_dy,
940    
941          }                                                           const int32_t iEdgedWidth,
942          else                                                           const int32_t iDiamondSize,
943    
944                                                             const int32_t f_iFcode,
945                                                             const int32_t b_iFcode,
946    
947                                                             const int32_t iQuant,
948                                                             int iFound)
949          {          {
950                  threshA = psad[0];  /* Do a diamond search around given starting point, return SAD of best */
                 threshB = threshA+256;  
                 if (threshA< 512) threshA =  512;  
                 if (threshA>1024) threshA = 1024;  
                 if (threshB>1792) threshB = 1792;  
         }  
951    
952          iFound=0;          int32_t iSAD;
953    
954  /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion          VECTOR f_backupMV;
955          vector of the median.          VECTOR b_backupMV;
         If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2  
 */  
956    
957          if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[0]) ) )          f_currMV->x = f_start_x;
958                  iFound=2;          f_currMV->y = f_start_y;
959            b_currMV->x = b_start_x;
960            b_currMV->y = b_start_y;
961    
962  /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.          do
963          Otherwise select large Diamond Search.          {
964  */                  iFound = 1;
965    
966          if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536) || (bPredEq) )                  f_backupMV = *f_currMV;
                 iDiamondSize=1; // halfpel!  
         else  
                 iDiamondSize=2; // halfpel!  
967    
968          if (!(MotionFlags & PMV_HALFPELDIAMOND16) )                  CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x - iDiamondSize, f_backupMV.y);
969                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x + iDiamondSize, f_backupMV.y);
970                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y - iDiamondSize);
971                    CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y + iDiamondSize);
972    
973                    b_backupMV = *b_currMV;
974    
975                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x - iDiamondSize, b_backupMV.y);
976                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x + iDiamondSize, b_backupMV.y);
977                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y - iDiamondSize);
978                    CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y + iDiamondSize);
979    
980            } while (!iFound);
981    
982            return iMinSAD;
983    }
984    
985    /* Sorry, these MACROS really got too large... I'll turn them into function soon! */
986    
987    #define CHECK_MV16_DIRECT_FOUND(X,Y) \
988            if ( (X)>=(-32) && (X)<=(31) && ((Y)>=-32) && ((Y)<=31) ) \
989            { int k;\
990            VECTOR mvs,b_mvs;       \
991            iSAD = 0;\
992            for (k = 0; k < 4; k++) {       \
993                                            mvs.x = (int32_t) ((TRB * directmv[k].x) / TRD + (X));          \
994                        b_mvs.x = (int32_t) (((X) == 0)                                                     \
995                                                                                    ? ((TRB - TRD) * directmv[k].x) / TRD   \
996                                                : mvs.x - directmv[k].x);                           \
997                                                                                                                                                                    \
998                        mvs.y = (int32_t) ((TRB * directmv[k].y) / TRD + (Y));              \
999                            b_mvs.y = (int32_t) (((Y) == 0)                                                         \
1000                                                                                    ? ((TRB - TRD) * directmv[k].y) / TRD   \
1001                                                : mvs.y - directmv[k].y);                           \
1002                                                                                                                                                                    \
1003      if ( (mvs.x <= max_dx) && (mvs.x >= min_dx) \
1004        && (mvs.y <= max_dy) && (mvs.y >= min_dy)  \
1005            && (b_mvs.x <= max_dx) && (b_mvs.x >= min_dx)  \
1006        && (b_mvs.y <= max_dy) && (b_mvs.y >= min_dy) ) { \
1007                iSAD += sad8bi( cur + 8*(k&1) + 8*(k>>1)*iEdgedWidth,                                                                                                       \
1008                            get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \
1009                                            mvs.x, mvs.y, iEdgedWidth),                                                             \
1010                            get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \
1011                                            b_mvs.x, b_mvs.y, iEdgedWidth),                                                         \
1012                            iEdgedWidth); \
1013                    }       \
1014            else    \
1015                    iSAD = 65535;   \
1016            } \
1017            iSAD += calc_delta_16((X),(Y), 1, iQuant);\
1018            if (iSAD < iMinSAD) \
1019                {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iFound=0; } \
1020    }
1021    
1022    
1023    
1024    int32_t
1025    Diamond16_DirectMainSearch(
1026                                            const uint8_t * const f_pRef,
1027                                            const uint8_t * const f_pRefH,
1028                                            const uint8_t * const f_pRefV,
1029                                            const uint8_t * const f_pRefHV,
1030    
1031                                            const uint8_t * const cur,
1032    
1033                                            const uint8_t * const b_pRef,
1034                                            const uint8_t * const b_pRefH,
1035                                            const uint8_t * const b_pRefV,
1036                                            const uint8_t * const b_pRefHV,
1037    
1038                                            const int x,
1039                                            const int y,
1040    
1041                                            const int TRB,
1042                                            const int TRD,
1043    
1044                                        const int start_x,
1045                                        const int start_y,
1046    
1047                                        int iMinSAD,
1048                                        VECTOR * const currMV,
1049                                            const VECTOR * const directmv,
1050    
1051                                        const int32_t min_dx,
1052                                            const int32_t max_dx,
1053                                            const int32_t min_dy,
1054                                            const int32_t max_dy,
1055    
1056                                            const int32_t iEdgedWidth,
1057                                            const int32_t iDiamondSize,
1058    
1059                                            const int32_t iQuant,
1060                                            int iFound)
1061    {
1062    /* Do a diamond search around given starting point, return SAD of best */
1063    
1064            int32_t iSAD;
1065    
1066            VECTOR backupMV;
1067    
1068            currMV->x = start_x;
1069            currMV->y = start_y;
1070    
1071    /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1072    
1073            do
1074            {
1075                    iFound = 1;
1076    
1077                    backupMV = *currMV;
1078    
1079                    CHECK_MV16_DIRECT_FOUND(backupMV.x - iDiamondSize, backupMV.y);
1080                    CHECK_MV16_DIRECT_FOUND(backupMV.x + iDiamondSize, backupMV.y);
1081                    CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y - iDiamondSize);
1082                    CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y + iDiamondSize);
1083    
1084            } while (!iFound);
1085    
1086            return iMinSAD;
1087    }
1088    
1089    
1090    int32_t
1091    AdvDiamond8_MainSearch(const uint8_t * const pRef,
1092                                               const uint8_t * const pRefH,
1093                                               const uint8_t * const pRefV,
1094                                               const uint8_t * const pRefHV,
1095                                               const uint8_t * const cur,
1096                                               const int x,
1097                                               const int y,
1098                                               const int start_xi,
1099                                               const int start_yi,
1100                                               int iMinSAD,
1101                                               VECTOR * const currMV,
1102                                               const int center_x,
1103                                               const int center_y,
1104                                               const int32_t min_dx,
1105                                               const int32_t max_dx,
1106                                               const int32_t min_dy,
1107                                               const int32_t max_dy,
1108                                               const int32_t iEdgedWidth,
1109                                               const int32_t iDiamondSize,
1110                                               const int32_t iFcode,
1111                                               const int32_t iQuant,
1112                                               int iDirection)
1113    {
1114    
1115            int32_t iSAD;
1116            int start_x = start_xi, start_y = start_yi;
1117    
1118    /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
1119    
1120            if (iDirection) {
1121                    CHECK_MV8_CANDIDATE(start_x - iDiamondSize, start_y);
1122                    CHECK_MV8_CANDIDATE(start_x + iDiamondSize, start_y);
1123                    CHECK_MV8_CANDIDATE(start_x, start_y - iDiamondSize);
1124                    CHECK_MV8_CANDIDATE(start_x, start_y + iDiamondSize);
1125            } else {
1126                    int bDirection = 1 + 2 + 4 + 8;
1127    
1128                    do {
1129                            iDirection = 0;
1130                            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)
1131                                    CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1132    
1133                            if (bDirection & 2)
1134                                    CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1135    
1136                            if (bDirection & 4)
1137                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1138    
1139                            if (bDirection & 8)
1140                                    CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1141    
1142                            /* now we're doing diagonal checks near our candidate */
1143    
1144                            if (iDirection)         //checking if anything found
1145                            {
1146                                    bDirection = iDirection;
1147                                    iDirection = 0;
1148                                    start_x = currMV->x;
1149                                    start_y = currMV->y;
1150                                    if (bDirection & 3)     //our candidate is left or right
1151                                    {
1152                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
1153                                            CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
1154                                    } else                  // what remains here is up or down
1155                                    {
1156                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
1157                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
1158                                    }
1159    
1160                                    if (iDirection) {
1161                                            bDirection += iDirection;
1162                                            start_x = currMV->x;
1163                                            start_y = currMV->y;
1164                                    }
1165                            } else                          //about to quit, eh? not so fast....
1166                            {
1167                                    switch (bDirection) {
1168                                    case 2:
1169                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1170                                                                                            start_y - iDiamondSize, 2 + 4);
1171                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1172                                                                                            start_y + iDiamondSize, 2 + 8);
1173                                            break;
1174                                    case 1:
1175                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1176                                                                                            start_y - iDiamondSize, 1 + 4);
1177                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1178                                                                                            start_y + iDiamondSize, 1 + 8);
1179                                            break;
1180                                    case 2 + 4:
1181                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1182                                                                                            start_y - iDiamondSize, 1 + 4);
1183                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1184                                                                                            start_y - iDiamondSize, 2 + 4);
1185                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1186                                                                                            start_y + iDiamondSize, 2 + 8);
1187                                            break;
1188                                    case 4:
1189                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1190                                                                                            start_y - iDiamondSize, 2 + 4);
1191                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1192                                                                                            start_y - iDiamondSize, 1 + 4);
1193                                            break;
1194                                    case 8:
1195                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1196                                                                                            start_y + iDiamondSize, 2 + 8);
1197                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1198                                                                                            start_y + iDiamondSize, 1 + 8);
1199                                            break;
1200                                    case 1 + 4:
1201                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1202                                                                                            start_y + iDiamondSize, 1 + 8);
1203                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1204                                                                                            start_y - iDiamondSize, 1 + 4);
1205                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1206                                                                                            start_y - iDiamondSize, 2 + 4);
1207                                            break;
1208                                    case 2 + 8:
1209                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1210                                                                                            start_y - iDiamondSize, 1 + 4);
1211                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1212                                                                                            start_y + iDiamondSize, 1 + 8);
1213                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1214                                                                                            start_y + iDiamondSize, 2 + 8);
1215                                            break;
1216                                    case 1 + 8:
1217                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1218                                                                                            start_y - iDiamondSize, 2 + 4);
1219                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1220                                                                                            start_y + iDiamondSize, 2 + 8);
1221                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1222                                                                                            start_y + iDiamondSize, 1 + 8);
1223                                            break;
1224                                    default:                //1+2+4+8 == we didn't find anything at all
1225                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1226                                                                                            start_y - iDiamondSize, 1 + 4);
1227                                            CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1228                                                                                            start_y + iDiamondSize, 1 + 8);
1229                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1230                                                                                            start_y - iDiamondSize, 2 + 4);
1231                                            CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize,
1232                                                                                            start_y + iDiamondSize, 2 + 8);
1233                                            break;
1234                                    }
1235                                    if (!(iDirection))
1236                                            break;          //ok, the end. really
1237                                    else {
1238                                            bDirection = iDirection;
1239                                            start_x = currMV->x;
1240                                            start_y = currMV->y;
1241                                    }
1242                            }
1243                    }
1244                    while (1);                              //forever
1245            }
1246            return iMinSAD;
1247    }
1248    
1249    
1250    int32_t
1251    Full8_MainSearch(const uint8_t * const pRef,
1252                                     const uint8_t * const pRefH,
1253                                     const uint8_t * const pRefV,
1254                                     const uint8_t * const pRefHV,
1255                                     const uint8_t * const cur,
1256                                     const int x,
1257                                     const int y,
1258                               const int start_x,
1259                               const int start_y,
1260                               int iMinSAD,
1261                               VECTOR * const currMV,
1262                               const int center_x,
1263                               const int center_y,
1264                                     const int32_t min_dx,
1265                                     const int32_t max_dx,
1266                                     const int32_t min_dy,
1267                                     const int32_t max_dy,
1268                                     const int32_t iEdgedWidth,
1269                                     const int32_t iDiamondSize,
1270                                     const int32_t iFcode,
1271                                     const int32_t iQuant,
1272                                     int iFound)
1273    {
1274            int32_t iSAD;
1275            int32_t dx, dy;
1276            VECTOR backupMV;
1277    
1278            backupMV.x = start_x;
1279            backupMV.y = start_y;
1280    
1281            for (dx = min_dx; dx <= max_dx; dx += iDiamondSize)
1282                    for (dy = min_dy; dy <= max_dy; dy += iDiamondSize)
1283                            NOCHECK_MV8_CANDIDATE(dx, dy);
1284    
1285            return iMinSAD;
1286    }
1287    
1288    Halfpel8_RefineFuncPtr Halfpel8_Refine;
1289    
1290    int32_t
1291    Halfpel16_Refine(const uint8_t * const pRef,
1292                                     const uint8_t * const pRefH,
1293                                     const uint8_t * const pRefV,
1294                                     const uint8_t * const pRefHV,
1295                                     const uint8_t * const cur,
1296                                     const int x,
1297                                     const int y,
1298                                     VECTOR * const currMV,
1299                                     int32_t iMinSAD,
1300                               const int center_x,
1301                               const int center_y,
1302                                     const int32_t min_dx,
1303                                     const int32_t max_dx,
1304                                     const int32_t min_dy,
1305                                     const int32_t max_dy,
1306                                     const int32_t iFcode,
1307                                     const int32_t iQuant,
1308                                     const int32_t iEdgedWidth)
1309    {
1310    /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
1311    
1312            int32_t iSAD;
1313            VECTOR backupMV = *currMV;
1314    
1315            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y - 1);
1316            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y - 1);
1317            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y - 1);
1318            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y);
1319            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y);
1320            CHECK_MV16_CANDIDATE(backupMV.x - 1, backupMV.y + 1);
1321            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y + 1);
1322            CHECK_MV16_CANDIDATE(backupMV.x + 1, backupMV.y + 1);
1323    
1324            return iMinSAD;
1325    }
1326    
1327    #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
1328    
1329    
1330    
1331    int32_t
1332    PMVfastSearch16(const uint8_t * const pRef,
1333                                    const uint8_t * const pRefH,
1334                                    const uint8_t * const pRefV,
1335                                    const uint8_t * const pRefHV,
1336                                    const IMAGE * const pCur,
1337                                    const int x,
1338                                    const int y,
1339                                    const int start_x,      /* start is searched first, so it should contain the most */
1340                                    const int start_y,  /* likely motion vector for this block */
1341                                    const int center_x,     /* center is from where length of MVs is measured */
1342                                    const int center_y,
1343                                    const uint32_t MotionFlags,
1344                                    const uint32_t iQuant,
1345                                    const uint32_t iFcode,
1346                                    const MBParam * const pParam,
1347                                    const MACROBLOCK * const pMBs,
1348                                    const MACROBLOCK * const prevMBs,
1349                                    VECTOR * const currMV,
1350                                    VECTOR * const currPMV)
1351    {
1352            const uint32_t iWcount = pParam->mb_width;
1353            const int32_t iWidth = pParam->width;
1354            const int32_t iHeight = pParam->height;
1355            const int32_t iEdgedWidth = pParam->edged_width;
1356    
1357            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
1358    
1359            int32_t iDiamondSize;
1360    
1361            int32_t min_dx;
1362            int32_t max_dx;
1363            int32_t min_dy;
1364            int32_t max_dy;
1365    
1366            int32_t iFound;
1367    
1368            VECTOR newMV;
1369            VECTOR backupMV;                        /* just for PMVFAST */
1370    
1371            VECTOR pmv[4];
1372            int32_t psad[4];
1373    
1374            MainSearch16FuncPtr MainSearchPtr;
1375    
1376            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
1377    
1378            int32_t threshA, threshB;
1379            int32_t bPredEq;
1380            int32_t iMinSAD, iSAD;
1381    
1382    /* Get maximum range */
1383            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
1384                              iFcode);
1385    
1386    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
1387    
1388            if (!(MotionFlags & PMV_HALFPEL16)) {
1389                    min_dx = EVEN(min_dx);
1390                    max_dx = EVEN(max_dx);
1391                    min_dy = EVEN(min_dy);
1392                    max_dy = EVEN(max_dy);
1393            }
1394    
1395            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
1396            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1397    
1398            if ((x == 0) && (y == 0)) {
1399                    threshA = 512;
1400                    threshB = 1024;
1401            } else {
1402                    threshA = psad[0];
1403                    threshB = threshA + 256;
1404                    if (threshA < 512)
1405                            threshA = 512;
1406                    if (threshA > 1024)
1407                            threshA = 1024;
1408                    if (threshB > 1792)
1409                            threshB = 1792;
1410            }
1411    
1412            iFound = 0;
1413    
1414    /* Step 4: Calculate SAD around the Median prediction.
1415       MinSAD=SAD
1416       If Motion Vector equal to Previous frame motion vector
1417       and MinSAD<PrevFrmSAD goto Step 10.
1418       If SAD<=256 goto Step 10.
1419    */
1420    
1421            currMV->x = start_x;
1422            currMV->y = start_y;
1423    
1424            if (!(MotionFlags & PMV_HALFPEL16)) {   /* This should NOT be necessary! */
1425                    currMV->x = EVEN(currMV->x);
1426                    currMV->y = EVEN(currMV->y);
1427            }
1428    
1429            if (currMV->x > max_dx) {
1430                    currMV->x = max_dx;
1431            }
1432            if (currMV->x < min_dx) {
1433                    currMV->x = min_dx;
1434            }
1435            if (currMV->y > max_dy) {
1436                    currMV->y = max_dy;
1437            }
1438            if (currMV->y < min_dy) {
1439                    currMV->y = min_dy;
1440            }
1441    
1442            iMinSAD =
1443                    sad16(cur,
1444                              get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
1445                                                     iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
1446            iMinSAD +=
1447                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
1448                                              (uint8_t) iFcode, iQuant);
1449    
1450            if ((iMinSAD < 256) ||
1451                    ((MVequal(*currMV, prevMB->mvs[0])) &&
1452                     ((int32_t) iMinSAD < prevMB->sad16))) {
1453                    if (iMinSAD < (int)(2 * iQuant))        // high chances for SKIP-mode
1454                    {
1455                            if (!MVzero(*currMV)) {
1456                                    iMinSAD += MV16_00_BIAS;
1457                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
1458                                    iMinSAD -= MV16_00_BIAS;
1459                            }
1460                    }
1461    
1462                    if (MotionFlags & PMV_QUICKSTOP16)
1463                            goto PMVfast16_Terminate_without_Refine;
1464                    if (MotionFlags & PMV_EARLYSTOP16)
1465                            goto PMVfast16_Terminate_with_Refine;
1466            }
1467    
1468    
1469    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
1470       vector of the median.
1471       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
1472    */
1473    
1474            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[0])))
1475                    iFound = 2;
1476    
1477    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
1478       Otherwise select large Diamond Search.
1479    */
1480    
1481            if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
1482                    iDiamondSize = 1;               // halfpel!
1483            else
1484                    iDiamondSize = 2;               // halfpel!
1485    
1486            if (!(MotionFlags & PMV_HALFPELDIAMOND16))
1487                    iDiamondSize *= 2;
1488    
1489    /*
1490       Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
1491       Also calculate (0,0) but do not subtract offset.
1492       Let MinSAD be the smallest SAD up to this point.
1493       If MV is (0,0) subtract offset.
1494    */
1495    
1496    // (0,0) is always possible
1497    
1498            if (!MVzero(pmv[0]))
1499                    CHECK_MV16_ZERO;
1500    
1501    // previous frame MV is always possible
1502    
1503            if (!MVzero(prevMB->mvs[0]))
1504                    if (!MVequal(prevMB->mvs[0], pmv[0]))
1505                            CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
1506    
1507    // left neighbour, if allowed
1508    
1509            if (!MVzero(pmv[1]))
1510                    if (!MVequal(pmv[1], prevMB->mvs[0]))
1511                            if (!MVequal(pmv[1], pmv[0])) {
1512                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1513                                            pmv[1].x = EVEN(pmv[1].x);
1514                                            pmv[1].y = EVEN(pmv[1].y);
1515                                    }
1516    
1517                                    CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
1518                            }
1519    // top neighbour, if allowed
1520            if (!MVzero(pmv[2]))
1521                    if (!MVequal(pmv[2], prevMB->mvs[0]))
1522                            if (!MVequal(pmv[2], pmv[0]))
1523                                    if (!MVequal(pmv[2], pmv[1])) {
1524                                            if (!(MotionFlags & PMV_HALFPEL16)) {
1525                                                    pmv[2].x = EVEN(pmv[2].x);
1526                                                    pmv[2].y = EVEN(pmv[2].y);
1527                                            }
1528                                            CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
1529    
1530    // top right neighbour, if allowed
1531                                            if (!MVzero(pmv[3]))
1532                                                    if (!MVequal(pmv[3], prevMB->mvs[0]))
1533                                                            if (!MVequal(pmv[3], pmv[0]))
1534                                                                    if (!MVequal(pmv[3], pmv[1]))
1535                                                                            if (!MVequal(pmv[3], pmv[2])) {
1536                                                                                    if (!(MotionFlags & PMV_HALFPEL16)) {
1537                                                                                            pmv[3].x = EVEN(pmv[3].x);
1538                                                                                            pmv[3].y = EVEN(pmv[3].y);
1539                                                                                    }
1540                                                                                    CHECK_MV16_CANDIDATE(pmv[3].x,
1541                                                                                                                             pmv[3].y);
1542                                                                            }
1543                                    }
1544    
1545            if ((MVzero(*currMV)) &&
1546                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
1547                    iMinSAD -= MV16_00_BIAS;
1548    
1549    
1550    /* Step 6: If MinSAD <= thresa goto Step 10.
1551       If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
1552    */
1553    
1554            if ((iMinSAD <= threshA) ||
1555                    (MVequal(*currMV, prevMB->mvs[0]) &&
1556                     ((int32_t) iMinSAD < prevMB->sad16))) {
1557                    if (MotionFlags & PMV_QUICKSTOP16)
1558                            goto PMVfast16_Terminate_without_Refine;
1559                    if (MotionFlags & PMV_EARLYSTOP16)
1560                            goto PMVfast16_Terminate_with_Refine;
1561            }
1562    
1563    
1564    /************ (Diamond Search)  **************/
1565    /*
1566       Step 7: Perform Diamond search, with either the small or large diamond.
1567       If Found=2 only examine one Diamond pattern, and afterwards goto step 10
1568       Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
1569       If center then goto step 10.
1570       Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
1571       Refine by using small diamond and goto step 10.
1572    */
1573    
1574            if (MotionFlags & PMV_USESQUARES16)
1575                    MainSearchPtr = Square16_MainSearch;
1576            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
1577                    MainSearchPtr = AdvDiamond16_MainSearch;
1578            else
1579                    MainSearchPtr = Diamond16_MainSearch;
1580    
1581            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
1582    
1583    
1584    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
1585            iSAD =
1586                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1587                                                      currMV->x, currMV->y, iMinSAD, &newMV, center_x, center_y,
1588                                                      min_dx, max_dx,
1589                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
1590                                                      iQuant, iFound);
1591    
1592            if (iSAD < iMinSAD) {
1593                    *currMV = newMV;
1594                    iMinSAD = iSAD;
1595            }
1596    
1597            if (MotionFlags & PMV_EXTSEARCH16) {
1598    /* extended: search (up to) two more times: orignal prediction and (0,0) */
1599    
1600                    if (!(MVequal(pmv[0], backupMV))) {
1601                            iSAD =
1602                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
1603                                                                      center_x, center_y, iMinSAD, &newMV, center_x, center_y,
1604                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
1605                                                                      iDiamondSize, iFcode, iQuant, iFound);
1606    
1607                            if (iSAD < iMinSAD) {
1608                                    *currMV = newMV;
1609                                    iMinSAD = iSAD;
1610                            }
1611                    }
1612    
1613                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
1614                            iSAD =
1615                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
1616                                                                      iMinSAD, &newMV, center_x, center_y,
1617                                                                      min_dx, max_dx, min_dy, max_dy,
1618                                                                      iEdgedWidth, iDiamondSize, iFcode,
1619                                                                      iQuant, iFound);
1620    
1621                            if (iSAD < iMinSAD) {
1622                                    *currMV = newMV;
1623                                    iMinSAD = iSAD;
1624                            }
1625                    }
1626            }
1627    
1628    /*
1629       Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.
1630    */
1631    
1632      PMVfast16_Terminate_with_Refine:
1633            if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
1634                    iMinSAD =
1635                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1636                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
1637                                                             iFcode, iQuant, iEdgedWidth);
1638    
1639      PMVfast16_Terminate_without_Refine:
1640            currPMV->x = currMV->x - center_x;
1641            currPMV->y = currMV->y - center_y;
1642            return iMinSAD;
1643    }
1644    
1645    
1646    
1647    
1648    
1649    
1650    int32_t
1651    Diamond8_MainSearch(const uint8_t * const pRef,
1652                                            const uint8_t * const pRefH,
1653                                            const uint8_t * const pRefV,
1654                                            const uint8_t * const pRefHV,
1655                                            const uint8_t * const cur,
1656                                            const int x,
1657                                            const int y,
1658                                            const int32_t start_x,
1659                                            const int32_t start_y,
1660                                            int32_t iMinSAD,
1661                                            VECTOR * const currMV,
1662                                            const int center_x,
1663                                            const int center_y,
1664                                            const int32_t min_dx,
1665                                            const int32_t max_dx,
1666                                            const int32_t min_dy,
1667                                            const int32_t max_dy,
1668                                            const int32_t iEdgedWidth,
1669                                            const int32_t iDiamondSize,
1670                                            const int32_t iFcode,
1671                                            const int32_t iQuant,
1672                                            int iFound)
1673    {
1674    /* Do a diamond search around given starting point, return SAD of best */
1675    
1676            int32_t iDirection = 0;
1677            int32_t iDirectionBackup;
1678            int32_t iSAD;
1679            VECTOR backupMV;
1680    
1681            backupMV.x = start_x;
1682            backupMV.y = start_y;
1683    
1684    /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
1685    
1686            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1687            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1688            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1689            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1690    
1691            if (iDirection) {
1692                    while (!iFound) {
1693                            iFound = 1;
1694                            backupMV = *currMV;     // since iDirection!=0, this is well defined!
1695                            iDirectionBackup = iDirection;
1696    
1697                            if (iDirectionBackup != 2)
1698                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1699                                                                                      backupMV.y, 1);
1700                            if (iDirectionBackup != 1)
1701                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1702                                                                                      backupMV.y, 2);
1703                            if (iDirectionBackup != 4)
1704                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1705                                                                                      backupMV.y - iDiamondSize, 3);
1706                            if (iDirectionBackup != 3)
1707                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x,
1708                                                                                      backupMV.y + iDiamondSize, 4);
1709                    }
1710            } else {
1711                    currMV->x = start_x;
1712                    currMV->y = start_y;
1713            }
1714            return iMinSAD;
1715    }
1716    
1717    
1718    
1719    
1720    int32_t
1721    Square8_MainSearch(const uint8_t * const pRef,
1722                                       const uint8_t * const pRefH,
1723                                       const uint8_t * const pRefV,
1724                                       const uint8_t * const pRefHV,
1725                                       const uint8_t * const cur,
1726                                       const int x,
1727                                       const int y,
1728                                       const int32_t start_x,
1729                                       const int32_t start_y,
1730                                       int32_t iMinSAD,
1731                                       VECTOR * const currMV,
1732                                       const int center_x,
1733                                       const int center_y,
1734                                       const int32_t min_dx,
1735                                       const int32_t max_dx,
1736                                       const int32_t min_dy,
1737                                       const int32_t max_dy,
1738                                       const int32_t iEdgedWidth,
1739                                       const int32_t iDiamondSize,
1740                                       const int32_t iFcode,
1741                                       const int32_t iQuant,
1742                                       int iFound)
1743    {
1744    /* Do a square search around given starting point, return SAD of best */
1745    
1746            int32_t iDirection = 0;
1747            int32_t iSAD;
1748            VECTOR backupMV;
1749    
1750            backupMV.x = start_x;
1751            backupMV.y = start_y;
1752    
1753    /* It's one search with full square pattern, and new parts for all following diamonds */
1754    
1755    /*   new direction are extra, so 1-4 is normal diamond
1756          537
1757          1*2
1758          648
1759    */
1760    
1761            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize, backupMV.y, 1);
1762            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize, backupMV.y, 2);
1763            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y - iDiamondSize, 3);
1764            CHECK_MV8_CANDIDATE_DIR(backupMV.x, backupMV.y + iDiamondSize, 4);
1765    
1766            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1767                                                             backupMV.y - iDiamondSize, 5);
1768            CHECK_MV8_CANDIDATE_DIR(backupMV.x - iDiamondSize,
1769                                                             backupMV.y + iDiamondSize, 6);
1770            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1771                                                             backupMV.y - iDiamondSize, 7);
1772            CHECK_MV8_CANDIDATE_DIR(backupMV.x + iDiamondSize,
1773                                                             backupMV.y + iDiamondSize, 8);
1774    
1775    
1776            if (iDirection) {
1777                    while (!iFound) {
1778                            iFound = 1;
1779                            backupMV = *currMV;
1780    
1781                            switch (iDirection) {
1782                            case 1:
1783                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1784                                                                                       backupMV.y, 1);
1785                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1786                                                                                     backupMV.y - iDiamondSize, 5);
1787                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1788                                                                                     backupMV.y - iDiamondSize, 7);
1789                                    break;
1790                            case 2:
1791                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1792                                                                                     2);
1793                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1794                                                                                     backupMV.y + iDiamondSize, 6);
1795                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1796                                                                                     backupMV.y + iDiamondSize, 8);
1797                                    break;
1798    
1799                            case 3:
1800                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1801                                                                                     4);
1802                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1803                                                                                     backupMV.y - iDiamondSize, 7);
1804                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1805                                                                                     backupMV.y + iDiamondSize, 8);
1806                                    break;
1807    
1808                            case 4:
1809                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1810                                                                                     3);
1811                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1812                                                                                     backupMV.y - iDiamondSize, 5);
1813                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1814                                                                                     backupMV.y + iDiamondSize, 6);
1815                                    break;
1816    
1817                            case 5:
1818                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1819                                                                                     1);
1820                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1821                                                                                     3);
1822                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1823                                                                                     backupMV.y - iDiamondSize, 5);
1824                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1825                                                                                     backupMV.y + iDiamondSize, 6);
1826                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1827                                                                                     backupMV.y - iDiamondSize, 7);
1828                                    break;
1829    
1830                            case 6:
1831                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1832                                                                                     2);
1833                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1834                                                                                     3);
1835    
1836                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1837                                                                                     backupMV.y - iDiamondSize, 5);
1838                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1839                                                                                     backupMV.y + iDiamondSize, 6);
1840                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1841                                                                                     backupMV.y + iDiamondSize, 8);
1842    
1843                                    break;
1844    
1845                            case 7:
1846                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1847                                                                                       backupMV.y, 1);
1848                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1849                                                                                     4);
1850                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1851                                                                                     backupMV.y - iDiamondSize, 5);
1852                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1853                                                                                     backupMV.y - iDiamondSize, 7);
1854                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1855                                                                                     backupMV.y + iDiamondSize, 8);
1856                                    break;
1857    
1858                            case 8:
1859                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1860                                                                                     2);
1861                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1862                                                                                     4);
1863                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1864                                                                                     backupMV.y + iDiamondSize, 6);
1865                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1866                                                                                     backupMV.y - iDiamondSize, 7);
1867                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1868                                                                                     backupMV.y + iDiamondSize, 8);
1869                                    break;
1870                            default:
1871                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize, backupMV.y,
1872                                                                                     1);
1873                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize, backupMV.y,
1874                                                                                     2);
1875                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y - iDiamondSize,
1876                                                                                     3);
1877                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x, backupMV.y + iDiamondSize,
1878                                                                                     4);
1879    
1880                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1881                                                                                     backupMV.y - iDiamondSize, 5);
1882                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x - iDiamondSize,
1883                                                                                     backupMV.y + iDiamondSize, 6);
1884                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1885                                                                                     backupMV.y - iDiamondSize, 7);
1886                                    CHECK_MV8_CANDIDATE_FOUND(backupMV.x + iDiamondSize,
1887                                                                                     backupMV.y + iDiamondSize, 8);
1888                                    break;
1889                            }
1890                    }
1891            } else {
1892                    currMV->x = start_x;
1893                    currMV->y = start_y;
1894            }
1895            return iMinSAD;
1896    }
1897    
1898    
1899    
1900    
1901    
1902    int32_t
1903    Halfpel8_Refine_c(const uint8_t * const pRef,
1904                                      const uint8_t * const pRefH,
1905                                      const uint8_t * const pRefV,
1906                                      const uint8_t * const pRefHV,
1907                                      const uint8_t * const cur,
1908                                      const int x,
1909                                      const int y,
1910                                      VECTOR * const currMV,
1911                                      int32_t iMinSAD,
1912                                      const int center_x,
1913                                      const int center_y,
1914                                      const int32_t min_dx,
1915                                      const int32_t max_dx,
1916                                      const int32_t min_dy,
1917                                      const int32_t max_dy,
1918                                      const int32_t iFcode,
1919                                      const int32_t iQuant,
1920                                      const int32_t iEdgedWidth)
1921    {
1922    /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
1923    
1924            int32_t iSAD;
1925            VECTOR backupMV = *currMV;
1926    
1927            CHECK_MV8_CANDIDATE(backupMV.x - 1, backupMV.y - 1);
1928            CHECK_MV8_CANDIDATE(backupMV.x, backupMV.y - 1);
1929            CHECK_MV8_CANDIDATE(backupMV.x + 1, backupMV.y - 1);
1930            CHECK_MV8_CANDIDATE(backupMV.x - 1, backupMV.y);
1931            CHECK_MV8_CANDIDATE(backupMV.x + 1, backupMV.y);
1932            CHECK_MV8_CANDIDATE(backupMV.x - 1, backupMV.y + 1);
1933            CHECK_MV8_CANDIDATE(backupMV.x, backupMV.y + 1);
1934            CHECK_MV8_CANDIDATE(backupMV.x + 1, backupMV.y + 1);
1935    
1936            return iMinSAD;
1937    }
1938    
1939    
1940    #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
1941    
1942    int32_t
1943    PMVfastSearch8(const uint8_t * const pRef,
1944                               const uint8_t * const pRefH,
1945                               const uint8_t * const pRefV,
1946                               const uint8_t * const pRefHV,
1947                               const IMAGE * const pCur,
1948                               const int x,
1949                               const int y,
1950                               const int start_x,
1951                               const int start_y,
1952                                    const int center_x,
1953                                    const int center_y,
1954                               const uint32_t MotionFlags,
1955                               const uint32_t iQuant,
1956                               const uint32_t iFcode,
1957                               const MBParam * const pParam,
1958                               const MACROBLOCK * const pMBs,
1959                               const MACROBLOCK * const prevMBs,
1960                               VECTOR * const currMV,
1961                               VECTOR * const currPMV)
1962    {
1963            const uint32_t iWcount = pParam->mb_width;
1964            const int32_t iWidth = pParam->width;
1965            const int32_t iHeight = pParam->height;
1966            const int32_t iEdgedWidth = pParam->edged_width;
1967    
1968            const uint8_t *cur = pCur->y + x * 8 + y * 8 * iEdgedWidth;
1969    
1970            int32_t iDiamondSize;
1971    
1972            int32_t min_dx;
1973            int32_t max_dx;
1974            int32_t min_dy;
1975            int32_t max_dy;
1976    
1977            VECTOR pmv[4];
1978            int32_t psad[4];
1979            VECTOR newMV;
1980            VECTOR backupMV;
1981            VECTOR startMV;
1982    
1983    //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
1984            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
1985    
1986             int32_t threshA, threshB;
1987            int32_t iFound, bPredEq;
1988            int32_t iMinSAD, iSAD;
1989    
1990            int32_t iSubBlock = (y & 1) + (y & 1) + (x & 1);
1991    
1992            MainSearch8FuncPtr MainSearchPtr;
1993    
1994            /* Init variables */
1995            startMV.x = start_x;
1996            startMV.y = start_y;
1997    
1998            /* Get maximum range */
1999            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2000                              iFcode);
2001    
2002            if (!(MotionFlags & PMV_HALFPELDIAMOND8)) {
2003                    min_dx = EVEN(min_dx);
2004                    max_dx = EVEN(max_dx);
2005                    min_dy = EVEN(min_dy);
2006                    max_dy = EVEN(max_dy);
2007            }
2008    
2009            /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
2010            bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
2011    
2012            if ((x == 0) && (y == 0)) {
2013                    threshA = 512 / 4;
2014                    threshB = 1024 / 4;
2015    
2016            } else {
2017                    threshA = psad[0] / 4;  /* good estimate? */
2018                    threshB = threshA + 256 / 4;
2019                    if (threshA < 512 / 4)
2020                            threshA = 512 / 4;
2021                    if (threshA > 1024 / 4)
2022                            threshA = 1024 / 4;
2023                    if (threshB > 1792 / 4)
2024                            threshB = 1792 / 4;
2025            }
2026    
2027            iFound = 0;
2028    
2029    /* Step 4: Calculate SAD around the Median prediction.
2030       MinSAD=SAD
2031       If Motion Vector equal to Previous frame motion vector
2032       and MinSAD<PrevFrmSAD goto Step 10.
2033       If SAD<=256 goto Step 10.
2034    */
2035    
2036    
2037    // Prepare for main loop
2038    
2039      if (MotionFlags & PMV_USESQUARES8)
2040          MainSearchPtr = Square8_MainSearch;
2041      else
2042    
2043            if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2044                    MainSearchPtr = AdvDiamond8_MainSearch;
2045            else
2046                    MainSearchPtr = Diamond8_MainSearch;
2047    
2048    
2049            *currMV = startMV;
2050    
2051            iMinSAD =
2052                    sad8(cur,
2053                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2054                                                    iEdgedWidth), iEdgedWidth);
2055            iMinSAD +=
2056                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2057                                             (uint8_t) iFcode, iQuant);
2058    
2059            if ((iMinSAD < 256 / 4) || ((MVequal(*currMV, prevMB->mvs[iSubBlock]))
2060                                                                    && ((int32_t) iMinSAD <
2061                                                                            prevMB->sad8[iSubBlock]))) {
2062                    if (MotionFlags & PMV_QUICKSTOP16)
2063                            goto PMVfast8_Terminate_without_Refine;
2064                    if (MotionFlags & PMV_EARLYSTOP16)
2065                            goto PMVfast8_Terminate_with_Refine;
2066            }
2067    
2068    /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2069       vector of the median.
2070       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2071    */
2072    
2073            if ((bPredEq) && (MVequal(pmv[0], prevMB->mvs[iSubBlock])))
2074                    iFound = 2;
2075    
2076    /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2077       Otherwise select large Diamond Search.
2078    */
2079    
2080            if ((!MVzero(pmv[0])) || (threshB < 1536 / 4) || (bPredEq))
2081                    iDiamondSize = 1;               // 1 halfpel!
2082            else
2083                    iDiamondSize = 2;               // 2 halfpel = 1 full pixel!
2084    
2085            if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2086                  iDiamondSize*=2;                  iDiamondSize*=2;
2087    
2088    
2089    /*
2090       Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.
2091       Also calculate (0,0) but do not subtract offset.
2092       Let MinSAD be the smallest SAD up to this point.
2093       If MV is (0,0) subtract offset.
2094    */
2095    
2096    // the median prediction might be even better than mv16
2097    
2098            if (!MVequal(pmv[0], startMV))
2099                    CHECK_MV8_CANDIDATE(center_x, center_y);
2100    
2101    // (0,0) if needed
2102            if (!MVzero(pmv[0]))
2103                    if (!MVzero(startMV))
2104                            CHECK_MV8_ZERO;
2105    
2106    // previous frame MV if needed
2107            if (!MVzero(prevMB->mvs[iSubBlock]))
2108                    if (!MVequal(prevMB->mvs[iSubBlock], startMV))
2109                            if (!MVequal(prevMB->mvs[iSubBlock], pmv[0]))
2110                                    CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,
2111                                                                            prevMB->mvs[iSubBlock].y);
2112    
2113            if ((iMinSAD <= threshA) ||
2114                    (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2115                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2116                    if (MotionFlags & PMV_QUICKSTOP16)
2117                            goto PMVfast8_Terminate_without_Refine;
2118                    if (MotionFlags & PMV_EARLYSTOP16)
2119                            goto PMVfast8_Terminate_with_Refine;
2120            }
2121    
2122    // left neighbour, if allowed and needed
2123            if (!MVzero(pmv[1]))
2124                    if (!MVequal(pmv[1], startMV))
2125                            if (!MVequal(pmv[1], prevMB->mvs[iSubBlock]))
2126                                    if (!MVequal(pmv[1], pmv[0])) {
2127                                            if (!(MotionFlags & PMV_HALFPEL8)) {
2128                                                    pmv[1].x = EVEN(pmv[1].x);
2129                                                    pmv[1].y = EVEN(pmv[1].y);
2130                                            }
2131                                            CHECK_MV8_CANDIDATE(pmv[1].x, pmv[1].y);
2132                                    }
2133    // top neighbour, if allowed and needed
2134            if (!MVzero(pmv[2]))
2135                    if (!MVequal(pmv[2], startMV))
2136                            if (!MVequal(pmv[2], prevMB->mvs[iSubBlock]))
2137                                    if (!MVequal(pmv[2], pmv[0]))
2138                                            if (!MVequal(pmv[2], pmv[1])) {
2139                                                    if (!(MotionFlags & PMV_HALFPEL8)) {
2140                                                            pmv[2].x = EVEN(pmv[2].x);
2141                                                            pmv[2].y = EVEN(pmv[2].y);
2142                                                    }
2143                                                    CHECK_MV8_CANDIDATE(pmv[2].x, pmv[2].y);
2144    
2145    // top right neighbour, if allowed and needed
2146                                                    if (!MVzero(pmv[3]))
2147                                                            if (!MVequal(pmv[3], startMV))
2148                                                                    if (!MVequal(pmv[3], prevMB->mvs[iSubBlock]))
2149                                                                            if (!MVequal(pmv[3], pmv[0]))
2150                                                                                    if (!MVequal(pmv[3], pmv[1]))
2151                                                                                            if (!MVequal(pmv[3], pmv[2])) {
2152                                                                                                    if (!
2153                                                                                                            (MotionFlags &
2154                                                                                                             PMV_HALFPEL8)) {
2155                                                                                                            pmv[3].x = EVEN(pmv[3].x);
2156                                                                                                            pmv[3].y = EVEN(pmv[3].y);
2157                                                                                                    }
2158                                                                                                    CHECK_MV8_CANDIDATE(pmv[3].x,
2159                                                                                                                                            pmv[3].y);
2160                                                                                            }
2161                                            }
2162    
2163            if ((MVzero(*currMV)) &&
2164                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2165                    iMinSAD -= MV8_00_BIAS;
2166    
2167    
2168    /* Step 6: If MinSAD <= thresa goto Step 10.
2169       If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.
2170    */
2171    
2172            if ((iMinSAD <= threshA) ||
2173                    (MVequal(*currMV, prevMB->mvs[iSubBlock]) &&
2174                     ((int32_t) iMinSAD < prevMB->sad8[iSubBlock]))) {
2175                    if (MotionFlags & PMV_QUICKSTOP16)
2176                            goto PMVfast8_Terminate_without_Refine;
2177                    if (MotionFlags & PMV_EARLYSTOP16)
2178                            goto PMVfast8_Terminate_with_Refine;
2179            }
2180    
2181    /************ (Diamond Search)  **************/
2182    /*
2183       Step 7: Perform Diamond search, with either the small or large diamond.
2184       If Found=2 only examine one Diamond pattern, and afterwards goto step 10
2185       Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.
2186       If center then goto step 10.
2187       Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.
2188       Refine by using small diamond and goto step 10.
2189    */
2190    
2191            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2192    
2193    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2194            iSAD =
2195                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2196                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2197                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2198                                                      iQuant, iFound);
2199    
2200            if (iSAD < iMinSAD) {
2201                    *currMV = newMV;
2202                    iMinSAD = iSAD;
2203            }
2204    
2205            if (MotionFlags & PMV_EXTSEARCH8) {
2206    /* extended: search (up to) two more times: orignal prediction and (0,0) */
2207    
2208                    if (!(MVequal(pmv[0], backupMV))) {
2209                            iSAD =
2210                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2211                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2212                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2213                                                                      iDiamondSize, iFcode, iQuant, iFound);
2214    
2215                            if (iSAD < iMinSAD) {
2216                                    *currMV = newMV;
2217                                    iMinSAD = iSAD;
2218                            }
2219                    }
2220    
2221                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2222                            iSAD =
2223                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2224                                                                      iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2225                                                                      max_dy, iEdgedWidth, iDiamondSize, iFcode,
2226                                                                      iQuant, iFound);
2227    
2228                            if (iSAD < iMinSAD) {
2229                                    *currMV = newMV;
2230                                    iMinSAD = iSAD;
2231                            }
2232                    }
2233            }
2234    
2235    /* Step 10: The motion vector is chosen according to the block corresponding to MinSAD.
2236       By performing an optional local half-pixel search, we can refine this result even further.
2237    */
2238    
2239      PMVfast8_Terminate_with_Refine:
2240            if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step
2241                    iMinSAD =
2242                            Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2243                                                            iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2244                                                            iFcode, iQuant, iEdgedWidth);
2245    
2246    
2247      PMVfast8_Terminate_without_Refine:
2248            currPMV->x = currMV->x - center_x;
2249            currPMV->y = currMV->y - center_y;
2250    
2251            return iMinSAD;
2252    }
2253    
2254    int32_t
2255    EPZSSearch16(const uint8_t * const pRef,
2256                             const uint8_t * const pRefH,
2257                             const uint8_t * const pRefV,
2258                             const uint8_t * const pRefHV,
2259                             const IMAGE * const pCur,
2260                             const int x,
2261                             const int y,
2262                            const int start_x,
2263                            const int start_y,
2264                            const int center_x,
2265                            const int center_y,
2266                             const uint32_t MotionFlags,
2267                             const uint32_t iQuant,
2268                             const uint32_t iFcode,
2269                             const MBParam * const pParam,
2270                             const MACROBLOCK * const pMBs,
2271                             const MACROBLOCK * const prevMBs,
2272                             VECTOR * const currMV,
2273                             VECTOR * const currPMV)
2274    {
2275            const uint32_t iWcount = pParam->mb_width;
2276            const uint32_t iHcount = pParam->mb_height;
2277    
2278            const int32_t iWidth = pParam->width;
2279            const int32_t iHeight = pParam->height;
2280            const int32_t iEdgedWidth = pParam->edged_width;
2281    
2282            const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
2283    
2284            int32_t min_dx;
2285            int32_t max_dx;
2286            int32_t min_dy;
2287            int32_t max_dy;
2288    
2289            VECTOR newMV;
2290            VECTOR backupMV;
2291    
2292            VECTOR pmv[4];
2293            int32_t psad[8];
2294    
2295            static MACROBLOCK *oldMBs = NULL;
2296    
2297    //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;
2298            const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2299            MACROBLOCK *oldMB = NULL;
2300    
2301             int32_t thresh2;
2302            int32_t bPredEq;
2303            int32_t iMinSAD, iSAD = 9999;
2304    
2305            MainSearch16FuncPtr MainSearchPtr;
2306    
2307            if (oldMBs == NULL) {
2308                    oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
2309    //      fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));
2310            }
2311            oldMB = oldMBs + x + y * iWcount;
2312    
2313    /* Get maximum range */
2314            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,
2315                              iFcode);
2316    
2317            if (!(MotionFlags & PMV_HALFPEL16)) {
2318                    min_dx = EVEN(min_dx);
2319                    max_dx = EVEN(max_dx);
2320                    min_dy = EVEN(min_dy);
2321                    max_dy = EVEN(max_dy);
2322            }
2323            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2324            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2325    
2326  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2327          MinSAD=SAD          MinSAD=SAD
2328          If Motion Vector equal to Previous frame motion vector          If Motion Vector equal to Previous frame motion vector
# Line 688  Line 2330 
2330          If SAD<=256 goto Step 10.          If SAD<=256 goto Step 10.
2331  */  */
2332    
   
2333  // Prepare for main loop  // Prepare for main loop
2334    
2335          *currMV=pmv[0];         /* current best := prediction */          currMV->x = start_x;
2336          if (!(MotionFlags & PMV_HALFPEL16 ))          currMV->y = start_y;
2337          {       /* This should NOT be necessary! */  
2338            if (!(MotionFlags & PMV_HALFPEL16)) {
2339                  currMV->x = EVEN(currMV->x);                  currMV->x = EVEN(currMV->x);
2340                  currMV->y = EVEN(currMV->y);                  currMV->y = EVEN(currMV->y);
2341          }          }
2342    
2343          if (currMV->x > max_dx)          if (currMV->x > max_dx)
                 {  
2344                          currMV->x=max_dx;                          currMV->x=max_dx;
                 }  
2345          if (currMV->x < min_dx)          if (currMV->x < min_dx)
                 {  
2346                          currMV->x=min_dx;                          currMV->x=min_dx;
                 }  
2347          if (currMV->y > max_dy)          if (currMV->y > max_dy)
                 {  
2348                          currMV->y=max_dy;                          currMV->y=max_dy;
                 }  
2349          if (currMV->y < min_dy)          if (currMV->y < min_dy)
                 {  
2350                          currMV->y=min_dy;                          currMV->y=min_dy;
2351    
2352    /***************** This is predictor SET A: only median prediction ******************/
2353    
2354            iMinSAD =
2355                    sad16(cur,
2356                              get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV,
2357                                                     iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2358            iMinSAD +=
2359                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2360                                              (uint8_t) iFcode, iQuant);
2361    
2362    // thresh1 is fixed to 256
2363            if ((iMinSAD < 256) ||
2364                    ((MVequal(*currMV, prevMB->mvs[0])) &&
2365                     ((int32_t) iMinSAD < prevMB->sad16))) {
2366                    if (MotionFlags & PMV_QUICKSTOP16)
2367                            goto EPZS16_Terminate_without_Refine;
2368                    if (MotionFlags & PMV_EARLYSTOP16)
2369                            goto EPZS16_Terminate_with_Refine;
2370            }
2371    
2372    /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2373    
2374    // previous frame MV
2375            CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
2376    
2377    // set threshhold based on Min of Prediction and SAD of collocated block
2378    // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
2379    
2380            if ((x == 0) && (y == 0)) {
2381                    thresh2 = 512;
2382            } else {
2383    /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */
2384    
2385                    thresh2 = MIN(psad[0], iSAD) * 6 / 5 + 128;
2386            }
2387    
2388    // MV=(0,0) is often a good choice
2389    
2390            CHECK_MV16_ZERO;
2391    
2392    
2393    // left neighbour, if allowed
2394            if (x != 0) {
2395                    if (!(MotionFlags & PMV_HALFPEL16)) {
2396                            pmv[1].x = EVEN(pmv[1].x);
2397                            pmv[1].y = EVEN(pmv[1].y);
2398                    }
2399                    CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
2400            }
2401    // top neighbour, if allowed
2402            if (y != 0) {
2403                    if (!(MotionFlags & PMV_HALFPEL16)) {
2404                            pmv[2].x = EVEN(pmv[2].x);
2405                            pmv[2].y = EVEN(pmv[2].y);
2406                    }
2407                    CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
2408    
2409    // top right neighbour, if allowed
2410                    if ((uint32_t) x != (iWcount - 1)) {
2411                            if (!(MotionFlags & PMV_HALFPEL16)) {
2412                                    pmv[3].x = EVEN(pmv[3].x);
2413                                    pmv[3].y = EVEN(pmv[3].y);
2414                            }
2415                            CHECK_MV16_CANDIDATE(pmv[3].x, pmv[3].y);
2416                    }
2417            }
2418    
2419    /* Terminate if MinSAD <= T_2
2420       Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
2421    */
2422    
2423            if ((iMinSAD <= thresh2)
2424                    || (MVequal(*currMV, prevMB->mvs[0]) &&
2425                            ((int32_t) iMinSAD <= prevMB->sad16))) {
2426                    if (MotionFlags & PMV_QUICKSTOP16)
2427                            goto EPZS16_Terminate_without_Refine;
2428                    if (MotionFlags & PMV_EARLYSTOP16)
2429                            goto EPZS16_Terminate_with_Refine;
2430            }
2431    
2432    /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
2433    
2434            backupMV = prevMB->mvs[0];      // collocated MV
2435            backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x);     // acceleration X
2436            backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y);     // acceleration Y
2437    
2438            CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y);
2439    
2440    // left neighbour
2441            if (x != 0)
2442                    CHECK_MV16_CANDIDATE((prevMB - 1)->mvs[0].x, (prevMB - 1)->mvs[0].y);
2443    
2444    // top neighbour
2445            if (y != 0)
2446                    CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,
2447                                                             (prevMB - iWcount)->mvs[0].y);
2448    
2449    // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs
2450    
2451            if ((uint32_t) x != iWcount - 1)
2452                    CHECK_MV16_CANDIDATE((prevMB + 1)->mvs[0].x, (prevMB + 1)->mvs[0].y);
2453    
2454    // bottom neighbour, dito
2455            if ((uint32_t) y != iHcount - 1)
2456                    CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,
2457                                                             (prevMB + iWcount)->mvs[0].y);
2458    
2459    /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
2460            if (iMinSAD <= thresh2) {
2461                    if (MotionFlags & PMV_QUICKSTOP16)
2462                            goto EPZS16_Terminate_without_Refine;
2463                    if (MotionFlags & PMV_EARLYSTOP16)
2464                            goto EPZS16_Terminate_with_Refine;
2465            }
2466    
2467    /************ (if Diamond Search)  **************/
2468    
2469            backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */
2470    
2471            if (MotionFlags & PMV_USESQUARES16)
2472                    MainSearchPtr = Square16_MainSearch;
2473            else
2474             if (MotionFlags & PMV_ADVANCEDDIAMOND16)
2475                    MainSearchPtr = AdvDiamond16_MainSearch;
2476            else
2477                    MainSearchPtr = Diamond16_MainSearch;
2478    
2479    /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
2480    
2481            iSAD =
2482                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2483                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2484                                                      min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2485    
2486            if (iSAD < iMinSAD) {
2487                    *currMV = newMV;
2488                    iMinSAD = iSAD;
2489            }
2490    
2491    
2492            if (MotionFlags & PMV_EXTSEARCH16) {
2493    /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
2494    
2495                    if (!(MVequal(pmv[0], backupMV))) {
2496                            iSAD =
2497                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2498                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2499                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2500                                                                      2, iFcode, iQuant, 0);
2501                    }
2502    
2503                    if (iSAD < iMinSAD) {
2504                            *currMV = newMV;
2505                            iMinSAD = iSAD;
2506                    }
2507    
2508                    if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2509                            iSAD =
2510                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2511                                                                      iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2512                                                                      max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
2513    
2514                            if (iSAD < iMinSAD) {
2515                                    *currMV = newMV;
2516                                    iMinSAD = iSAD;
2517                            }
2518                    }
2519            }
2520    
2521    /***************        Choose best MV found     **************/
2522    
2523      EPZS16_Terminate_with_Refine:
2524            if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
2525                    iMinSAD =
2526                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2527                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2528                                                             iFcode, iQuant, iEdgedWidth);
2529    
2530      EPZS16_Terminate_without_Refine:
2531    
2532            *oldMB = *prevMB;
2533    
2534            currPMV->x = currMV->x - center_x;
2535            currPMV->y = currMV->y - center_y;
2536            return iMinSAD;
2537    }
2538    
2539    
2540    int32_t
2541    EPZSSearch8(const uint8_t * const pRef,
2542                            const uint8_t * const pRefH,
2543                            const uint8_t * const pRefV,
2544                            const uint8_t * const pRefHV,
2545                            const IMAGE * const pCur,
2546                            const int x,
2547                            const int y,
2548                            const int start_x,
2549                            const int start_y,
2550                            const int center_x,
2551                            const int center_y,
2552                            const uint32_t MotionFlags,
2553                            const uint32_t iQuant,
2554                            const uint32_t iFcode,
2555                            const MBParam * const pParam,
2556                            const MACROBLOCK * const pMBs,
2557                            const MACROBLOCK * const prevMBs,
2558                            VECTOR * const currMV,
2559                            VECTOR * const currPMV)
2560    {
2561    /* Please not that EPZS might not be a good choice for 8x8-block motion search ! */
2562    
2563            const uint32_t iWcount = pParam->mb_width;
2564            const int32_t iWidth = pParam->width;
2565            const int32_t iHeight = pParam->height;
2566            const int32_t iEdgedWidth = pParam->edged_width;
2567    
2568            const uint8_t *cur = pCur->y + x * 8 + y * 8 * iEdgedWidth;
2569    
2570            int32_t iDiamondSize = 1;
2571    
2572            int32_t min_dx;
2573            int32_t max_dx;
2574            int32_t min_dy;
2575            int32_t max_dy;
2576    
2577            VECTOR newMV;
2578            VECTOR backupMV;
2579    
2580            VECTOR pmv[4];
2581            int32_t psad[8];
2582    
2583            const int32_t iSubBlock = ((y & 1) << 1) + (x & 1);
2584    
2585    //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
2586            const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
2587    
2588            int32_t bPredEq;
2589            int32_t iMinSAD, iSAD = 9999;
2590    
2591            MainSearch8FuncPtr MainSearchPtr;
2592    
2593    /* Get maximum range */
2594            get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 8, iWidth, iHeight,
2595                              iFcode);
2596    
2597    /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2598    
2599            if (!(MotionFlags & PMV_HALFPEL8)) {
2600                    min_dx = EVEN(min_dx);
2601                    max_dx = EVEN(max_dx);
2602                    min_dy = EVEN(min_dy);
2603                    max_dy = EVEN(max_dy);
2604            }
2605            /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
2606            bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2607    
2608    
2609    /* Step 4: Calculate SAD around the Median prediction.
2610            MinSAD=SAD
2611            If Motion Vector equal to Previous frame motion vector
2612                    and MinSAD<PrevFrmSAD goto Step 10.
2613            If SAD<=256 goto Step 10.
2614    */
2615    
2616    // Prepare for main loop
2617    
2618    
2619            if (!(MotionFlags & PMV_HALFPEL8)) {
2620                    currMV->x = EVEN(currMV->x);
2621                    currMV->y = EVEN(currMV->y);
2622                  }                  }
2623    
2624          iMinSAD = sad16( cur,          if (currMV->x > max_dx)
2625                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),                  currMV->x = max_dx;
2626                  iEdgedWidth, MV_MAX_ERROR);          if (currMV->x < min_dx)
2627          iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;                  currMV->x = min_dx;
2628            if (currMV->y > max_dy)
2629                    currMV->y = max_dy;
2630            if (currMV->y < min_dy)
2631                    currMV->y = min_dy;
2632    
2633    /***************** This is predictor SET A: only median prediction ******************/
2634    
2635    
2636            iMinSAD =
2637                    sad8(cur,
2638                             get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV,
2639                                                    iEdgedWidth), iEdgedWidth);
2640            iMinSAD +=
2641                    calc_delta_8(currMV->x - center_x, currMV->y - center_y,
2642                                             (uint8_t) iFcode, iQuant);
2643    
         if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )  
                 {  
2644    
2645                          if (MotionFlags & PMV_QUICKSTOP16)  // thresh1 is fixed to 256
2646                                  goto step10b;          if (iMinSAD < 256 / 4) {
2647                          if (MotionFlags & PMV_EARLYSTOP16)                  if (MotionFlags & PMV_QUICKSTOP8)
2648                                  goto step10;                          goto EPZS8_Terminate_without_Refine;
2649                    if (MotionFlags & PMV_EARLYSTOP8)
2650                            goto EPZS8_Terminate_with_Refine;
2651                  }                  }
2652    
2653  /*  /************** 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' ??? ***********  
 */  
2654    
 // (0,0) is always possible  
2655    
2656          CHECK_MV16_ZERO;  // MV=(0,0) is often a good choice
2657            CHECK_MV8_ZERO;
2658    
2659  // previous frame MV is always possible  // previous frame MV
2660          CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x, prevMB->mvs[iSubBlock].y);
2661    
2662  // left neighbour, if allowed  // left neighbour, if allowed
2663          if (x != 0)          if (psad[1] != MV_MAX_ERROR) {
2664          {                  if (!(MotionFlags & PMV_HALFPEL8)) {
2665                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[1].x = EVEN(pmv[1].x);
                 {       pmv[1].x = EVEN(pmv[1].x);  
2666                          pmv[1].y = EVEN(pmv[1].y);                          pmv[1].y = EVEN(pmv[1].y);
2667                  }                  }
2668                  CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x, pmv[1].y);
2669          }          }
   
2670  // top neighbour, if allowed  // top neighbour, if allowed
2671          if (y != 0)          if (psad[2] != MV_MAX_ERROR) {
2672          {                  if (!(MotionFlags & PMV_HALFPEL8)) {
2673                  if (!(MotionFlags & PMV_HALFPEL16 ))                          pmv[2].x = EVEN(pmv[2].x);
                 {       pmv[2].x = EVEN(pmv[2].x);  
2674                          pmv[2].y = EVEN(pmv[2].y);                          pmv[2].y = EVEN(pmv[2].y);
2675                  }                  }
2676                  CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x, pmv[2].y);
2677    
2678  // top right neighbour, if allowed  // top right neighbour, if allowed
2679                  if (x != (iWcount-1))                  if (psad[3] != MV_MAX_ERROR) {
2680                  {                          if (!(MotionFlags & PMV_HALFPEL8)) {
2681                          if (!(MotionFlags & PMV_HALFPEL16 ))                                  pmv[3].x = EVEN(pmv[3].x);
                         {       pmv[3].x = EVEN(pmv[3].x);  
2682                                  pmv[3].y = EVEN(pmv[3].y);                                  pmv[3].y = EVEN(pmv[3].y);
2683                          }                          }
2684                          CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);                          CHECK_MV8_CANDIDATE(pmv[3].x, pmv[3].y);
2685                  }                  }
2686          }          }
2687    
2688  /* Step 6: If MinSAD <= thresa goto Step 10.  /*  // this bias is zero anyway, at the moment!
2689     If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.  
2690            if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)
2691                    iMinSAD -= MV8_00_BIAS;
2692    
2693  */  */
2694    
2695          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )  /* Terminate if MinSAD <= T_2
2696                  {     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
2697                          if (MotionFlags & PMV_QUICKSTOP16)  */
                                 goto step10b;  
                         if (MotionFlags & PMV_EARLYSTOP16)  
                                 goto step10;  
                 }  
2698    
2699            if (iMinSAD < 512 / 4) {        /* T_2 == 512/4 hardcoded */
2700                    if (MotionFlags & PMV_QUICKSTOP8)
2701                            goto EPZS8_Terminate_without_Refine;
2702                    if (MotionFlags & PMV_EARLYSTOP8)
2703                            goto EPZS8_Terminate_with_Refine;
2704            }
2705    
2706  /************ (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.  
 */  
2707    
2708          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
2709    
2710  /* default: use best prediction as starting point for one call of PMVfast_MainSearch */          if (!(MotionFlags & PMV_HALFPELDIAMOND8))
2711          iSAD = PMVfastSearch16_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);  
2712    
2713          if (iSAD < iMinSAD)  /* default: use best prediction as starting point for one call of EPZS_MainSearch */
         {  
                 *currMV = newMV;  
                 iMinSAD = iSAD;  
         }  
2714    
2715          if (MotionFlags & PMV_EXTSEARCH16)  // there is no EPZS^2 for inter4v at the moment
         {  
 /* extended: search (up to) two more times: orignal prediction and (0,0) */  
2716    
2717                  if (!(MVequal(pmv[0],backupMV)) )    if (MotionFlags & PMV_USESQUARES8)
2718                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,        MainSearchPtr = Square8_MainSearch;
2719                                  x, y,    else
                         pmv[0].x, pmv[0].y, iMinSAD, &newMV,  
                         pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);  
2720    
2721                          if (iSAD < iMinSAD)          if (MotionFlags & PMV_ADVANCEDDIAMOND8)
2722                          {                  MainSearchPtr = AdvDiamond8_MainSearch;
2723            else
2724                    MainSearchPtr = Diamond8_MainSearch;
2725    
2726            iSAD =
2727                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
2728                                                      currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
2729                                                      min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
2730                                                      iQuant, 0);
2731    
2732    
2733            if (iSAD < iMinSAD) {
2734                                  *currMV = newMV;                                  *currMV = newMV;
2735                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2736                          }                          }
                 }  
2737    
2738                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )          if (MotionFlags & PMV_EXTSEARCH8) {
2739                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,  /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
                                 x, y,  
                         0, 0, iMinSAD, &newMV,  
                         pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);  
2740    
2741                          if (iSAD < iMinSAD)                  if (!(MVequal(pmv[0], backupMV))) {
2742                          {                          iSAD =
2743                                    (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
2744                                                                      pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
2745                                                                      min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
2746                                                                      iDiamondSize, iFcode, iQuant, 0);
2747    
2748                            if (iSAD < iMinSAD) {
2749                                  *currMV = newMV;                                  *currMV = newMV;
2750                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
2751                          }                          }
2752                  }                  }
         }  
   
 /*  
         Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.  
 */  
   
 step10:  
         if (MotionFlags & PMV_HALFPELREFINE16)          // perform final half-pel step  
                 iMinSAD = PMVfastSearch16_Refine( pRef, pRefH, pRefV, pRefHV, cur,  
                                 x, y,  
                                 currMV, iMinSAD,  
                                 pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);  
   
 step10b:  
         currPMV->x = currMV->x - pmv[0].x;  
         currPMV->y = currMV->y - pmv[0].y;  
         return iMinSAD;  
 }  
   
   
   
   
   
   
 int32_t PMVfastSearch8_MainSearch(  
                                         const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const uint8_t * const cur,  
                                         const int x, const int y,  
                                         int32_t startx, int32_t starty,  
                                         int32_t iMinSAD,  
                                         VECTOR * const currMV,  
                                         const VECTOR * const pmv,  
                                         const int32_t min_dx, const int32_t max_dx,  
                                         const int32_t min_dy, const int32_t max_dy,  
                                         const int32_t iEdgedWidth,  
                                         const int32_t iDiamondSize,  
                                         const int32_t iFcode,  
                                         const int32_t iQuant,  
                                         int iFound)  
 {  
 /* Do a diamond search around given starting point, return SAD of best */  
   
         int32_t iDirection=0;  
         int32_t iSAD;  
         VECTOR backupMV;  
         backupMV.x = startx;  
         backupMV.y = starty;  
   
 /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */  
   
         CHECK_MV8_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);  
         CHECK_MV8_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);  
         CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);  
         CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);  
2753    
2754          if (iDirection)                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
2755                  while (!iFound)                          iSAD =
2756                  {                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
2757                          iFound = 1;                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
2758                          backupMV=*currMV;       // since iDirection!=0, this is well defined!                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
2759                                                                      iQuant, 0);
2760    
2761                          if ( iDirection != 2)                          if (iSAD < iMinSAD) {
2762                                  CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);                                  *currMV = newMV;
2763                          if ( iDirection != 1)                                  iMinSAD = iSAD;
                                 CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);  
                         if ( iDirection != 4)  
                                 CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);  
                         if ( iDirection != 3)  
                                 CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);  
2764                  }                  }
         else  
                 {  
                         currMV->x = startx;  
                         currMV->y = starty;  
2765                  }                  }
         return iMinSAD;  
2766  }  }
2767    
2768  int32_t PMVfastSearch8_Refine(  /***************        Choose best MV found     **************/
                                         const uint8_t * const pRef,  
                                         const uint8_t * const pRefH,  
                                         const uint8_t * const pRefV,  
                                         const uint8_t * const pRefHV,  
                                         const uint8_t * const cur,  
                                         const int x, const int y,  
                                         VECTOR * const currMV,  
                                         int32_t iMinSAD,  
                                         const VECTOR * const pmv,  
                                         const int32_t min_dx, const int32_t max_dx,  
                                         const int32_t min_dy, const int32_t max_dy,  
                                         const int32_t iFcode,  
                                         const int32_t iQuant,  
                                         const int32_t iEdgedWidth)  
 {  
 /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */  
2769    
2770          int32_t iSAD;    EPZS8_Terminate_with_Refine:
2771          VECTOR backupMV = *currMV;          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step
2772                    iMinSAD =
2773                            Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2774                                                            iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
2775                                                            iFcode, iQuant, iEdgedWidth);
2776    
2777          CHECK_MV8_CANDIDATE(backupMV.x-1,backupMV.y-1);    EPZS8_Terminate_without_Refine:
         CHECK_MV8_CANDIDATE(backupMV.x  ,backupMV.y-1);  
         CHECK_MV8_CANDIDATE(backupMV.x+1,backupMV.y-1);  
         CHECK_MV8_CANDIDATE(backupMV.x-1,backupMV.y);  
         CHECK_MV8_CANDIDATE(backupMV.x+1,backupMV.y);  
         CHECK_MV8_CANDIDATE(backupMV.x-1,backupMV.y+1);  
         CHECK_MV8_CANDIDATE(backupMV.x  ,backupMV.y+1);  
         CHECK_MV8_CANDIDATE(backupMV.x+1,backupMV.y+1);  
2778    
2779            currPMV->x = currMV->x - center_x;
2780            currPMV->y = currMV->y - center_y;
2781          return iMinSAD;          return iMinSAD;
2782  }  }
2783    
2784    
 #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)  
2785    
2786  int32_t PMVfastSearch8(  int32_t
2787                                          const uint8_t * const pRef,  PMVfastIntSearch16(const uint8_t * const pRef,
2788                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
2789                                          const uint8_t * const pRefV,                                          const uint8_t * const pRefV,
2790                                          const uint8_t * const pRefHV,                                          const uint8_t * const pRefHV,
2791                                          const IMAGE * const pCur,                                          const IMAGE * const pCur,
2792                                          const int x, const int y,                                  const int x,
2793                                          const int start_x, int start_y,                                  const int y,
2794                                    const int start_x,              /* start should be most likely vector */
2795                                    const int start_y,
2796                                    const int center_x,             /* center is from where length of MVs is measured */
2797                                    const int center_y,
2798                                          const uint32_t MotionFlags,                                          const uint32_t MotionFlags,
2799                                          MBParam * const pParam,                                  const uint32_t iQuant,
2800                                          MACROBLOCK * const pMBs,                                  const uint32_t iFcode,
2801                                    const MBParam * const pParam,
2802                                    const MACROBLOCK * const pMBs,
2803                                    const MACROBLOCK * const prevMBs,
2804                                          VECTOR * const currMV,                                          VECTOR * const currMV,
2805                                          VECTOR * const currPMV)                                          VECTOR * const currPMV)
2806  {  {
2807          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;  
2808          const int32_t iWidth = pParam->width;          const int32_t iWidth = pParam->width;
2809          const int32_t iHeight = pParam->height;          const int32_t iHeight = pParam->height;
2810          const int32_t iEdgedWidth = pParam->edged_width;          const int32_t iEdgedWidth = pParam->edged_width;
2811    
2812          const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;          const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;
2813            const VECTOR zeroMV = { 0, 0 };
2814    
2815          int32_t iDiamondSize;          int32_t iDiamondSize;
2816    
# Line 987  Line 2819 
2819          int32_t min_dy;          int32_t min_dy;
2820          int32_t max_dy;          int32_t max_dy;
2821    
2822          VECTOR pmv[4];          int32_t iFound;
2823          int32_t psad[4];  
2824          VECTOR newMV;          VECTOR newMV;
2825          VECTOR backupMV;          VECTOR backupMV;
2826    
2827          MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;          VECTOR pmv[4];
2828            int32_t psad[4];
2829    
2830          static int32_t threshA,threshB;          MainSearch16FuncPtr MainSearchPtr;
2831          int32_t iFound,bPredEq;  
2832            MACROBLOCK *const prevMB = (MACROBLOCK *const)prevMBs + x + y * iWcount;
2833            MACROBLOCK *const pMB = (MACROBLOCK *const)(pMBs + x + y * iWcount);
2834    
2835            int32_t threshA, threshB;
2836            int32_t bPredEq;
2837          int32_t iMinSAD,iSAD;          int32_t iMinSAD,iSAD;
2838    
         int32_t iSubBlock = ((y&1)<<1) + (x&1);  
2839    
2840  /* Get maximum range */  /* Get maximum range */
2841      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,
2842                          x, y, 8, iWidth, iHeight, iFcode);                            iFcode);
2843    
2844  /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */  /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
2845    
2846          if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))          if ((x == 0) && (y == 0)) {
2847          { min_dx = EVEN(min_dx);                  threshA = 512;
2848            max_dx = EVEN(max_dx);                  threshB = 1024;
           min_dy = EVEN(min_dy);  
           max_dy = EVEN(max_dy);  
         }               /* because we might use IF (dx>max_dx) THEN dx=max_dx; */  
2849    
2850                    bPredEq = 0;
2851                    psad[0] = psad[1] = psad[2] = psad[3] = 0;
2852                    *currMV = pmv[0] = pmv[1] = pmv[2] = pmv[3] = zeroMV;
2853    
2854          bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);          } else {
2855    
2856          if ((x==0) && (y==0) )                  bPredEq = get_ipmvdata(pMBs, iWcount, 0, x, y, 0, pmv, psad);
         {  
                 threshA =  512/4;  
                 threshB = 1024/4;  
2857    
2858          }                  threshA = psad[0];
2859          else                  threshB = threshA + 256;
2860          {                  if (threshA < 512)
2861                  threshA = psad[0]/4;                    /* good estimate */                          threshA = 512;
2862                  threshB = threshA+256/4;                  if (threshA > 1024)
2863                  if (threshA< 512/4) threshA =  512/4;                          threshA = 1024;
2864                  if (threshA>1024/4) threshA = 1024/4;                  if (threshB > 1792)
2865                  if (threshB>1792/4) threshB = 1792/4;                          threshB = 1792;
2866    
2867                    *currMV = pmv[0];                       /* current best := prediction */
2868          }          }
2869    
2870          iFound=0;          iFound=0;
2871    
 /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  
         vector of the median.  
         If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2  
 */  
   
         if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[iSubBlock]) ) )  
                 iFound=2;  
   
 /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  
         Otherwise select large Diamond Search.  
 */  
   
         if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536/4) || (bPredEq) )  
                 iDiamondSize=1; // 1 halfpel!  
         else  
                 iDiamondSize=2; // 2 halfpel = 1 full pixel!  
   
         if (!(MotionFlags & PMV_HALFPELDIAMOND8) )  
                 iDiamondSize*=2;  
   
2872  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2873          MinSAD=SAD          MinSAD=SAD
2874          If Motion Vector equal to Previous frame motion vector          If Motion Vector equal to Previous frame motion vector
# Line 1060  Line 2876 
2876          If SAD<=256 goto Step 10.          If SAD<=256 goto Step 10.
2877  */  */
2878    
2879            if (currMV->x > max_dx) {
2880                    currMV->x = EVEN(max_dx);
2881            }
2882            if (currMV->x < min_dx) {
2883                    currMV->x = EVEN(min_dx);
2884            }
2885            if (currMV->y > max_dy) {
2886                    currMV->y = EVEN(max_dy);
2887            }
2888            if (currMV->y < min_dy) {
2889                    currMV->y = EVEN(min_dy);
2890            }
2891    
2892            iMinSAD =
2893                    sad16(cur,
2894                              get_iref_mv(pRef, x, y, 16, currMV,
2895                                                     iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);
2896            iMinSAD +=
2897                    calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2898                                              (uint8_t) iFcode, iQuant);
2899    
2900            if ((iMinSAD < 256) ||
2901                    ((MVequal(*currMV, prevMB->i_mvs[0])) &&
2902                     ((int32_t) iMinSAD < prevMB->i_sad16))) {
2903                    if (iMinSAD < (int)(2 * iQuant))        // high chances for SKIP-mode
2904                    {
2905                            if (!MVzero(*currMV)) {
2906                                    iMinSAD += MV16_00_BIAS;
2907                                    CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures
2908                                    iMinSAD -= MV16_00_BIAS;
2909                            }
2910                    }
2911    
2912                    if (MotionFlags & PMV_EARLYSTOP16)
2913                            goto PMVfastInt16_Terminate_with_Refine;
2914            }
2915    
 // Prepare for main loop  
2916    
2917          currMV->x=start_x;              /* start with mv16 */  /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion
2918          currMV->y=start_y;     vector of the median.
2919       If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2
2920    */
2921    
2922          iMinSAD = sad8( cur,          if ((bPredEq) && (MVequal(pmv[0], prevMB->i_mvs[0])))
2923                  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),                  iFound = 2;
                 iEdgedWidth);  
         iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode) * iQuant;  
2924    
2925          if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && (iMinSAD < pMB->sad8[iSubBlock]) ) )  /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.
2926                  {     Otherwise select large Diamond Search.
2927                          if (MotionFlags & PMV_QUICKSTOP8)  */
2928                                  goto step10_8b;  
2929                          if (MotionFlags & PMV_EARLYSTOP8)          if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
2930                                  goto step10_8;                  iDiamondSize = 2;               // halfpel units!
2931                  }          else
2932                    iDiamondSize = 4;               // halfpel units!
2933    
2934  /*  /*
2935  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.
2936          Also calculate (0,0) but do not subtract offset.          Also calculate (0,0) but do not subtract offset.
2937          Let MinSAD be the smallest SAD up to this point.          Let MinSAD be the smallest SAD up to this point.
2938          If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********     If MV is (0,0) subtract offset.
2939  */  */
2940    
2941  // the prediction might be even better than mv16  // (0,0) is often a good choice
         CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);  
2942    
2943  // (0,0) is always possible          if (!MVzero(pmv[0]))
2944          CHECK_MV8_ZERO;                  CHECK_MV16_ZERO;
2945    
2946  // previous frame MV is always possible  // previous frame MV is always possible
2947          CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);  
2948            if (!MVzero(prevMB->i_mvs[0]))
2949                    if (!MVequal(prevMB->i_mvs[0], pmv[0]))
2950                            CHECK_MV16_CANDIDATE(prevMB->i_mvs[0].x, prevMB->i_mvs[0].y);
2951    
2952  // left neighbour, if allowed  // left neighbour, if allowed
2953          if (psad[1] != MV_MAX_ERROR)  
2954          {          if (!MVzero(pmv[1]))
2955                  if (!(MotionFlags & PMV_HALFPEL8 ))                  if (!MVequal(pmv[1], prevMB->i_mvs[0]))
2956                  {       pmv[1].x = EVEN(pmv[1].x);                          if (!MVequal(pmv[1], pmv[0]))
2957                          pmv[1].y = EVEN(pmv[1].y);                                  CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
                 }  
                 CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);  
         }  
2958    
2959  // top neighbour, if allowed  // top neighbour, if allowed
2960          if (psad[2] != MV_MAX_ERROR)          if (!MVzero(pmv[2]))
2961          {                  if (!MVequal(pmv[2], prevMB->i_mvs[0]))
2962                  if (!(MotionFlags & PMV_HALFPEL8 ))                          if (!MVequal(pmv[2], pmv[0]))
2963                  {       pmv[2].x = EVEN(pmv[2].x);                                  if (!MVequal(pmv[2], pmv[1]))
2964                          pmv[2].y = EVEN(pmv[2].y);                                          CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
                 }  
                 CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);  
2965    
2966  // top right neighbour, if allowed  // top right neighbour, if allowed
2967                  if (psad[3] != MV_MAX_ERROR)                                          if (!MVzero(pmv[3]))
2968                  {                                                  if (!MVequal(pmv[3], prevMB->i_mvs[0]))
2969                  if (!(MotionFlags & PMV_HALFPEL8 ))                                                          if (!MVequal(pmv[3], pmv[0]))
2970                  {       pmv[3].x = EVEN(pmv[3].x);                                                                  if (!MVequal(pmv[3], pmv[1]))
2971                          pmv[3].y = EVEN(pmv[3].y);                                                                          if (!MVequal(pmv[3], pmv[2]))
2972                  }                                                                                  CHECK_MV16_CANDIDATE(pmv[3].x,
2973                          CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);                                                                                                                           pmv[3].y);
2974                  }  
2975          }          if ((MVzero(*currMV)) &&
2976                    (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )
2977                    iMinSAD -= MV16_00_BIAS;
2978    
2979    
2980  /* Step 6: If MinSAD <= thresa goto Step 10.  /* Step 6: If MinSAD <= thresa goto Step 10.
2981     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.
2982  */  */
2983    
2984          if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && (iMinSAD < pMB->sad8[iSubBlock]) ) )          if ((iMinSAD <= threshA) ||
2985                  {                  (MVequal(*currMV, prevMB->i_mvs[0]) &&
2986                          if (MotionFlags & PMV_QUICKSTOP8)                   ((int32_t) iMinSAD < prevMB->i_sad16))) {
2987                                  goto step10_8b;  
2988                          if (MotionFlags & PMV_EARLYSTOP8)                  if (MotionFlags & PMV_EARLYSTOP16)
2989                                  goto step10_8;                          goto PMVfastInt16_Terminate_with_Refine;
2990                  }                  }
2991    
2992    
2993  /************ (Diamond Search)  **************/  /************ (Diamond Search)  **************/
2994  /*  /*
2995  Step 7: Perform Diamond search, with either the small or large diamond.  Step 7: Perform Diamond search, with either the small or large diamond.
# Line 1147  Line 3000 
3000          Refine by using small diamond and goto step 10.          Refine by using small diamond and goto step 10.
3001  */  */
3002    
3003            if (MotionFlags & PMV_USESQUARES16)
3004                    MainSearchPtr = Square16_MainSearch;
3005            else if (MotionFlags & PMV_ADVANCEDDIAMOND16)
3006                    MainSearchPtr = AdvDiamond16_MainSearch;
3007            else
3008                    MainSearchPtr = Diamond16_MainSearch;
3009    
3010          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */          backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
3011    
3012    
3013  /* 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 */
3014          iSAD = PMVfastSearch8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,          iSAD =
3015                  x, y,                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,
3016                  currMV->x, currMV->y, iMinSAD, &newMV,                                                    currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,
3017                  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                    min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,
3018                                                      iQuant, iFound);
3019    
3020          if (iSAD < iMinSAD)          if (iSAD < iMinSAD) {
         {  
3021                  *currMV = newMV;                  *currMV = newMV;
3022                  iMinSAD = iSAD;                  iMinSAD = iSAD;
3023          }          }
3024    
3025          if (MotionFlags & PMV_EXTSEARCH8)          if (MotionFlags & PMV_EXTSEARCH16) {
         {  
3026  /* extended: search (up to) two more times: orignal prediction and (0,0) */  /* extended: search (up to) two more times: orignal prediction and (0,0) */
3027    
3028                  if (!(MVequal(pmv[0],backupMV)) )                  if (!(MVequal(pmv[0], backupMV))) {
3029                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
3030                                  x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,
3031                          pmv[0].x, pmv[0].y, iMinSAD, &newMV,                                                                    pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,
3032                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    min_dx, max_dx, min_dy, max_dy, iEdgedWidth,
3033                                                                      iDiamondSize, iFcode, iQuant, iFound);
3034    
3035                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
3036                                  *currMV = newMV;                                  *currMV = newMV;
3037                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
3038                          }                          }
3039                  }                  }
3040    
3041                  if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )                  if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {
3042                  {       iSAD = PMVfastSearch16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,                          iSAD =
3043                                  x, y,                                  (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,
3044                          0, 0, iMinSAD, &newMV,                                                                    iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,
3045                          pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);                                                                    max_dy, iEdgedWidth, iDiamondSize, iFcode,
3046                                                                      iQuant, iFound);
3047    
3048                          if (iSAD < iMinSAD)                          if (iSAD < iMinSAD) {
                         {  
3049                                  *currMV = newMV;                                  *currMV = newMV;
3050                                  iMinSAD = iSAD;                                  iMinSAD = iSAD;
3051                          }                          }
3052                  }                  }
3053          }          }
3054    
3055  /* Step 10: The motion vector is chosen according to the block corresponding to MinSAD.  /*
3056           By performing an optional local half-pixel search, we can refine this result even further.     Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.
3057  */  */
3058    
3059  step10_8:  PMVfastInt16_Terminate_with_Refine:
3060          if (MotionFlags & PMV_HALFPELREFINE8)           // perform final half-pel step  
3061                  iMinSAD = PMVfastSearch8_Refine( pRef, pRefH, pRefV, pRefHV, cur,          pMB->i_mvs[0] = pMB->i_mvs[1] = pMB->i_mvs[2] = pMB->i_mvs[3] = pMB->i_mv16 = *currMV;
3062                                  x, y,          pMB->i_sad8[0] = pMB->i_sad8[1] = pMB->i_sad8[2] = pMB->i_sad8[3] = pMB->i_sad16 = iMinSAD;
                                 currMV, iMinSAD,  
                                 pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);  
3063    
3064  step10_8b:          if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step
3065                    iMinSAD =
3066                            Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
3067                                                             iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
3068                                                             iFcode, iQuant, iEdgedWidth);
3069    
3070          currPMV->x = currMV->x - pmv[0].x;          pmv[0] = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          // get _REAL_ prediction (halfpel possible)
         currPMV->y = currMV->y - pmv[0].y;  
3071    
3072            currPMV->x = currMV->x - center_x;
3073            currPMV->y = currMV->y - center_y;
3074          return iMinSAD;          return iMinSAD;
3075  }  }
3076    

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

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