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

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

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